01、USART的特點
USART是通用異步收發傳輸器(UniversalAsynchronousReceiver/Transmitter),通常稱作UART,是一種異步收發傳輸器,是設備間進行異步通信的關鍵模塊。UART負責處理數據總線和串行口之間的串/並、並/串轉換,並規定了幀格式;通信雙方只要采用相同的幀格式和波特率,就能在未共享時鍾信號的情況下,僅用兩根信號線(Rx和Tx)就可以完成通信過程,因此也稱為異步串行通信。
全雙工異步通信。
小數波特率發生器系統,提供精確的波特率。
可配置的16倍過采樣或8倍過采樣,因而為速度容差與時鍾容差的靈活配置提供了可能。
可編程的數據字長度(8位或者9位);
可配置的停止位(支持1或者2位停止位);
可配置的使用DMA多緩沖器通信。
單獨的發送器和接收器使能位。
檢測標志:① 接受緩沖器 ②發送緩沖器空 ③傳輸結束標志
多個帶標志的中斷源。觸發中斷。
其他:校驗控制,四個錯誤檢測標志。
通信結構
02、USART簡介
2.1、數據傳輸模型
2.2、幀結構
串口異步通信需要定義的參數
① 起始位
② 數據位(8位或者9位)
③ 奇偶校驗位(第9位)
④ 停止位(1,15,2位)
⑤ 波特率設置
帶奇偶校驗的數據為就是9位
1.數據包
串口通訊的數據包由發送設備通過自身的TXD接口傳輸到接收設備得RXD接口,在協議層中規定了數據包的內容,具體包括起始位、主體數據(8位或9位)、校驗位以及停止位,通訊的雙方必須將數據包的格式約定一致才能正常收發數據。
2.波特率
由於異步通信中沒有時鍾信號,所以接收雙方要約定好波特率,即每秒傳輸的碼元個數,以便對信號進行解碼,常見的波特率有4800、9600、115200等。STM32中波特率的設置通過串口初始化結構體來實現。
3.起始和停止信號
數據包的首尾分別是起始位和停止位,數據包的起始信號由一個邏輯0的數據位表示,停止位信號可由0.5、1、1.5、2個邏輯1的數據位表示,雙方需約定一致。STM32中起始和停止信號的設置也是通過串口初始化結構體來實現。
4.有效數據
有效數據規定了主題數據的長度,一般為8或9位,其在STM32中也是通過串口初始化結構體來實現的。
5.數據校驗
在有效數據之后,有一個可選的數據校驗位。由於數據通信相對更容易受到外部干擾導致傳輸數據出現偏差,可以在傳輸過程加上校驗位來解決這個問題。校驗方法有奇校驗(odd)、偶校驗(even)、0 校驗(space)、1 校驗(mark)以及無(noparity)。這些也都可以在串口初始化結構體中實現的。
2.3、波特率
OVER8,用於配置過采樣,通常情況下,OVER8設置為0。
如果時鍾時84M
USARTDIV = 84000000/(115200*16) = 45.572
那么得到:
DIV_Fraction = 16*0.572 = 0x09;
DIV_Mantissa = 45 = 0x2D;
03、STM32的USART
根據STM32F207數據手冊,STM32F207一共6個串口
下文我們以USART1為例講解
從STM32F207數據手冊的Table10. Alternate functionmapping圖中看到USART1的對應管腳,下文我們選擇PA9和PA10作為USART1的管腳。
04、代碼配置
配置中斷優先級。
/* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
打開串口與相應的GPIO引腳,配置好相應串口信息與GPIO引腳的工作模式。
/* Enable GPIO clock */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* Enable UART1 clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* Connect PXx to USARTx_Tx*/ GPIO_PinAFConfig(GPIOA, 9, GPIO_AF_USART1); /* Connect PXx to USARTx_Rx*/ GPIO_PinAFConfig(GPIOA, 10, GPIO_AF_USART1); /* Configure USART Tx as alternate function */ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART Rx as alternate function */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_Init(GPIOA, &GPIO_InitStructure);
配置USART1。
USART_InitStructure.USART_BaudRate = 115200;//配置波特率 USART_InitStructure.USART_WordLength = USART_WordLength_8b;//配置數據字長 USART_InitStructure.USART_StopBits = USART_StopBits_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 configuration */ USART_Init(USART1, &USART_InitStructure);// 完成串口的初始化配置
使能中斷配置。
USART_ITConfig(USART1, USART_IT_TC, ENABLE);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE)
我們配置了發送傳輸完成中斷和接收數據寄存器非空中斷。我們可以配置很多類型中斷,在ST提供的標准庫函數中看到。
/** * @brief Enables or disables the specified USART interrupts. * @param USARTx: where x can be 1, 2, 3, 4, 5 or 6 to select the USART or * UART peripheral. * @param USART_IT: specifies the USART interrupt sources to be enabled or disabled. * This parameter can be one of the following values: * @arg USART_IT_CTS: CTS change interrupt * @arg USART_IT_LBD: LIN Break detection interrupt * @arg USART_IT_TXE: Transmit Data Register empty interrupt * @arg USART_IT_TC: Transmission complete interrupt * @arg USART_IT_RXNE: Receive Data register not empty interrupt * @arg USART_IT_IDLE: Idle line detection interrupt * @arg USART_IT_PE: Parity Error interrupt * @arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error) * @param NewState: new state of the specified USARTx interrupts. * This parameter can be: ENABLE or DISABLE. * @retval None */
最后使能串口。
/* Enable USART */ USART_Cmd(USART1, ENABLE);
main主函數,功能是LCD顯示串口接收的10個字符(如果不是ascii碼則不顯示),串口倒序返回接收到的10個字節。
int main(void) { /*省略初始化部分代碼*/ while (1) { if(LCD_refresh_flg){ LCD_refresh_flg = 0; LCD_ShowString(0,16,receive_data); receive_num--; USART_SendData(USART1, receive_data[receive_num--]); send_flg = 1; } } }
因為使能了中斷,我們還需要編寫中斷函數。
void USART1_IRQHandler(void) { if(USART_GetFlagStatus(USART1, USART_FLAG_TC)) { if(send_flg == 1){ if(receive_num==0){ USART_SendData(USART1, receive_data[receive_num]); send_flg = 0; receive_flg = 1; }else{ USART_SendData(USART1, receive_data[receive_num--]); } } USART_ClearFlag(USART1, USART_FLAG_TC); } if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) { if((receive_flg)&&(send_flg == 0)){ receive_data[receive_num++] = USART_ReceiveData(USART1); if(receive_num==10){ receive_flg = 0; LCD_refresh_flg = 1; } } USART_ClearFlag(USART1, USART_FLAG_RXNE); } }
下載驗證
LCD顯示屏可以顯示接收的10個字符,且PC以100ms為間隔發送數據,發送977包收到977包回復,測試demo就夠健壯,沒有出現丟包。
keil和IAR工程代碼和硬件PCB開源地址:
https://github.com/strongercjd/STM32F207VCT6
點擊查看本文所在的專輯,STM32F207教程