STM32 USART串口通信


一、介紹

通用同步異步收發器(USART)提供了一種靈活的方法與使用工業標准NRZ異步串行數據格式的外部設備之間進行全雙工數據交換。USART利用分數波特率發生器提供寬范圍的波特率選擇。它支持同步單向通信和半雙工單線通信,也支持LIN(局部互連網),智能卡協議和IrDA(紅外數據組織)SIR ENDEC規范,以及調制解調器(CTS/RTS)操作。它還允許多處理器通信。使用多緩沖器配置的DMA方式,可以實現高速數據通信。

二、硬件連接

  1. 串口之間的接線方式
  2. TTL與RS232的電平標准
  3. STM32 USART框圖

三、通信協議

  1. 數據包
    串口通訊的數據包由發送設備通過自身的TXD接口傳輸到接收設備得RXD接口,在協議層中規定了數據包的內容,具體包括起始位、主體數據(8位或9位)、校驗位以及停止位,通訊的雙方必須將數據包的格式約定一致才能正常收發數據。

  2. 波特率
    由於異步通信中沒有時鍾信號,所以接收雙方要約定好波特率,常見的波特率有4800、9600、115200等。

  3. 起始和停止信號
    數據包的首尾分別是起始位和停止位,數據包的起始信號由一個邏輯0的數據位表示,停止位信號可由0.5、1、1.5、2個邏輯1的數據位表示,雙方需約定一致。

  4. 有效數據
    有效數據規定了主題數據的長度,一般為8或9位。

  5. 數據校驗
    在有效數據之后,有一個可選的數據校驗位。由於數據通信相對更容易受到外部干擾導致傳輸數據出現偏差,可以在傳輸過程加上校驗位來解決這個問題。校驗方法有奇校驗(odd)、偶校驗(even)、 0 校驗(space)、 1 校驗(mark)以及無(noparity)。

4、STM32 USART的寄存器

  1. STM32 USART的配置的寄存器,庫函數中的結構體積是基於寄存器進行封裝的,還沒學會怎么看寄存器的小伙伴可以看我之前的筆記
寄存器 偏移 復位值 描述
USART_SR 0x00 0x00C0 狀態寄存器
USART_DR 0x04 不確定 數據寄存器
USART_BRR 0x08 0x0000 波特比率寄存器
USART_CR1 0x0C 0x0000 控制寄存器1
USART_CR2 0x10 0x0000 控制寄存器2
USART_CR3 0x14 0x0000 控制寄存器3
USART_GTPR 0x18 0x0000 保護時間和預分頻寄存器
  1. 寄存器的地址映象

四、代碼分析

  1. 配置串口的結構體
typedef struct
{
    uint32_t USART_BaudRate;  // 波特率設置
    uint16_t USART_WordLength;    //數據位數設置
    uint16_t USART_StopBits;    //停止位設置
    uint16_t USART_Parity;    //是否奇偶校驗
    uint16_t USART_Mode;    //接收與發送都使能
    uint16_t USART_HardwareFlowControl;      //硬件流控制模式設置
} USART_InitTypeDef;

  1. 中斷配置結構體
typedef struct
{
    uint8_t NVIC_IRQChannel;    // 配置USART為中斷源
    uint8_t NVIC_IRQChannelPreemptionPriority;    // 搶斷優先級
    uint8_t NVIC_IRQChannelSubPriority;    // 子優先級
    FunctionalState NVIC_IRQChannelCmd;    // 使能中斷
} NVIC_InitTypeDef;

  1. 配置USART 的 IO引腳
    將Tx配置為復用推挽輸出,將Rx配置為浮空輸入
    /* USART1 使用IO端口配置 */    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);    
  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空輸入
    GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA

  1. 配置USART 的工作模式配置
    /* USART1 工作模式配置 */
    USART_InitStructure.USART_BaudRate = 115200;	//波特率設置:115200
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//數據位數設置:8位
    USART_InitStructure.USART_StopBits = USART_StopBits_1; 	//停止位設置:1位
    USART_InitStructure.USART_Parity = USART_Parity_No ;  //是否奇偶校驗:無
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制模式設置:沒有使能
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//接收與發送都使能

  1. 將Rx讀取配置為中斷讀取模式
void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
	
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		// 設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
  
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;		// 配置USART為中斷源
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;		// 搶斷優先級
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		// 子優先級
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		// 使能中斷
    NVIC_Init(&NVIC_InitStructure);		// 初始化配置NVIC
}

  1. 中斷函數使用
    當串口接收到數據后此中斷函數會被調用,調用次函數后,會將接收到的信息有通過串口發送獲取。這里的中斷函數名已經在啟動文件中已經定義好了的,建議不做更改。

    注意:有的小伙伴編寫好程序后,發現串口無法收到發送的信息,可能是這里的中斷函數名寫錯了。
void USART1_IRQHandler(void)
{
	uint16_t  res;
	/* 判斷是否收到中斷信號 */
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		res = USART_ReceiveData(USART1);
		USART_SendData(USART1, res);
	}
	//USART_SendData(USART1,(uint16_t)0xAC);	

}

五、程序源碼

  1. usart1.c文件
/***************************************
 * 文件名  :usart1.c
 * 描述    :配置USART1         
 * 實驗平台:MINI STM32開發板 基於STM32F103C8T6
 * 硬件連接:------------------------
 *          | PA9  - USART1(Tx)      |
 *          | PA10 - USART1(Rx)      |
 *           ------------------------


**********************************************************************************/

#include "usart1.h"
#include <stdarg.h>
#include "misc.h"


void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);		// 設置NVIC中斷分組2:2位搶占優先級,2位響應優先級
  
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;		// 配置USART為中斷源
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;		// 搶斷優先級
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		// 子優先級
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		// 使能中斷
	NVIC_Init(&NVIC_InitStructure);		// 初始化配置NVIC
}


void USART1_Config(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

	/* 使能 USART1 時鍾*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); 

	/* USART1 使用IO端口配置 */    
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復用推挽輸出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);    
  
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空輸入
	GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA
	  
	/* USART1 工作模式配置 */
	USART_InitStructure.USART_BaudRate = 115200;	//波特率設置:115200
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//數據位數設置:8位
	USART_InitStructure.USART_StopBits = USART_StopBits_1; 	//停止位設置:1位
	USART_InitStructure.USART_Parity = USART_Parity_No ;  //是否奇偶校驗:無
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制模式設置:沒有使能
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//接收與發送都使能
	
	USART_Init(USART1, &USART_InitStructure);  //初始化USART1
	USART_Cmd(USART1, ENABLE);// USART1使能
	
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);	// 開啟串口接受中斷	
	NVIC_Configuration();// 串口中斷優先級配置
	
	
}

void USART1_IRQHandler(void)
{
	uint16_t  res;
	/* 判斷是否收到中斷信號 */
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)
	{
		res = USART_ReceiveData(USART1);
		USART_SendData(USART1, res);
	}
	//USART_SendData(USART1,(uint16_t)0xAC);	

}

  1. main.c文件
#include "stm32f10x.h"
#include "usart1.h"



int main(void)
{  
	     
    SystemInit();	//配置系統時鍾為 72M 
   
	USART1_Config(); //USART1 配置 		

	while (1)
	{	 

	}
}

五、編譯運行

  1. 編譯

  2. 運行

六、常見問題

程序下載后運行后發送數據無反饋。
解決辦法:

  1. 檢查中斷函數名是否正確。
  2. 將STM32的引腳設置為運行模式,有不知道的怎么設置為運行模式的小伙伴可以參考STM32零基礎入門教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM