STM32F407-串口學習1(UART協議簡介)


一、前言

1、簡介

  寫的這篇博客,是為了學習UART通信協議,以及UART能夠實現的一些功能,還有有關使用STM32CubeMX來配置芯片的一些操作,在后面我會以我使用的STM32F407開發板來舉例講解(其他STM32系列芯片大多數都可以按照這些步驟來操作的),如有不足請多多指教。

2、UART簡介

  嵌入式開發中,UART串口通信協議是我們常用的通信協議(UART、I2C、SPI等)之一,全稱叫做通用異步收發傳輸器(Universal Asynchronous Receiver/Transmitter)。只要是stm32的開發板都可以用到的,在STM32CubeMx里選對型號、配置好就行了。工作原理是將傳輸的數據一位接一位的傳輸,它能將要傳輸的資料在串行通信與並行通信之間加以轉換,能夠靈活地與外部設備進行全雙工數據交換。

傳輸檢測標志:
— 接收緩沖區已滿
— 發送緩沖區為空
— 傳輸結束標志

      

二、UART通信協議

一般的單片機UART和USART使用方式是一樣的,都使用異步模式(依靠啟動位和停止位來同步數據)。

1)起始位

  當未有數據發送時,數據線處於邏輯“1”狀態;先發出一個邏輯“0”信號,表示開始傳輸字符。

2)數據位

  緊接着起始位之后。資料位的個數可以是4、5、6、7、8等,構成一個字符。通常采用ASCII碼。從最低位開始傳送,靠時鍾定位。

3)奇偶校驗位

  資料為加上這一位后,使得“1”的位數應為偶數(偶校驗)或奇數(奇校驗),以此來校驗資料傳送的正確性。

4)停止位

  它是一個字符數據的結束標志。可以是1位、1.5位、2位的高電平。 由於數據是在傳輸線上定時的,並且每一個設備有其自己的時鍾,很可能在通信中兩台設備間出現了小小的不同步。因此停止位不僅僅是表示傳輸的結束,並且提供計算機校正時鍾同步的機會。適用於停止位的位數越多,不同時鍾同步的容忍程度越大,但是數據傳輸率同時也越慢。

5)空閑位或起始位

  處於邏輯“1”狀態,表示當前線路上沒有資料傳送,進入空閑狀態。

  處於邏輯“0”狀態,表示開始傳送下一數據段。

6)波特率

  表示每秒鍾傳送的碼元符號的個數,是衡量數據傳送速率的指標,它用單位時間內載波調制狀態改變的次數來表示。

  常用的波特率有:9600、115200……

  時間間隔計算:1秒除以波特率得出的時間,例如,波特率為9600的時間間隔為1s / 9600(波特率) = 104us。

三、UART工作原理

1)數據收發原理

發送時,數據首先被寫入發送數據寄存器FIFO中,如果UART被使能,則會按照預先設置好的參數(啟動位、數據位、校驗位、停止位)發送數據到發送移位寄存器中,直到發送數據寄存器FIFO的數據發送完成。一                           旦向發送數據寄存器中寫數據,UART的BUSY位開始有效,BUSY 位僅在發送數據寄存器FIFO 為空,且已從發送移位寄存器發送最后一個字符,包括停止位時才變無效。

在UART 接收器空閑時,如果數據輸入變成“低電平”,即接收到了起始位,則接收計數器開始運行,並且數據在Baud16 的第8 個周期被采樣。如果Rx 在Baud16 的第8 周期仍然為低電平,則起始位有效,否則會被認                            為是錯誤的起始位並將其忽略。

 如果起始位有效,則根據數據字符被編程的長度,在 Baud16 的每第 16 個周期(即一個位周期之后)對連續的數據位進行采樣。如果奇偶校驗模式使能,則還會檢測奇偶校驗位。
   最后,如果Rx 為高電平,則有效的停止位被確認,否則發生幀錯誤。當接收到一個完整的字符時,將數據存放在接收FIFO 中。

USART框圖如下:

 

 

2)中斷控制

  出現以下情況時,可使UART 產生中斷:

  • FIFO 溢出錯誤
  • 線中止錯誤(line-break,即Rx 信號一直為0 的狀態,包括校驗位和停止位在內)
  • 奇偶校驗錯誤
  • 幀錯誤(停止位不為1)
  • 接收超時(接收FIFO 已有數據但未滿,而后續數據長時間不來)
  • 發送
  • 接收

  由於所有中斷事件在發送到中斷控制器之前會一起進行“或運算”操作,所以任意時刻 UART 只能向中斷產生一個中斷請求。通過查詢中斷狀態函數,軟件可以在同一個中斷服務函數里處理多個中斷事件(多個並列的if 語句)。

 

3)FIFO 操作

  FIFO 是“First-In First-Out”的縮寫,意為“先進先出”,是一種常見的隊列操作。 Stellaris 系列ARM 的UART 模塊包含有2 個16 字節的FIFO:一個用於發送,另一個用於接收。可以將兩個FIFO 分別配置為以不同深度觸發中斷。可供選擇的配置包括:1/8、 1/4、1/2、3/4 和7/8 深度。例如,如果接收FIFO 選擇1/4,則在UART 接收到4 個數據時產生接收中斷。

   發送FIFO的基本工作過程: 只要有數據填充到發送FIFO 里,就會立即啟動發送過程。由於發送本身是個相對緩慢的過程,因此在發送的同時其它需要發送的數據還可以繼續填充到發送 FIFO 里。當發送 FIFO 被填滿時就不能再繼續填充了,否則會造成數據丟失,此時只能等待。這個等待並不會很久,以9600 的波特率為例,等待出現一個空位的時間在1ms 上下。發送 FIFO 會按照填入數據的先后順序把數據一個個發送出去,直到發送 FIFO 全空時為止。已發送完畢的數據會被自動清除,在發送FIFO 里同時會多出一個空位。
   接收FIFO的基本工作過程: 當硬件邏輯接收到數據時,就會往接收FIFO 里填充接收到的數據。程序應當及時取走這些數據,數據被取走也是在接收FIFO 里被自動刪除的過程,因此在接收 FIFO 里同時會多出一個空位。如果在接收 FIFO 里的數據未被及時取走而造成接收FIFO 已滿,則以后再接收到數據時因無空位可以填充而造成數據丟失。
  收發FIFO 主要是為了解決UART 收發中斷過於頻繁而導致CPU 效率不高的問題而引入的。在進行 UART 通信時,中斷方式比輪詢方式要簡便且效率高。但是,如果沒有收發 FIFO,則每收發一個數據都要中斷處理一次,效率仍然不夠高。如果有了收發FIFO,則可以在連續收發若干個數據(可多至14 個)后才產生一次中斷然后一並處理,這就大大提高了收發效率。
  完全不必要擔心FIFO 機制可能帶來的數據丟失或得不到及時處理的問題,因為它已經幫你想到了收發過程中存在的任何問題,只要在初始化配置UART 后,就可以放心收發了, FIFO 和中斷例程會自動搞定一切。

 

4)回環操作

  UART 可以進入一個內部回環(Loopback)模式,用於診斷或調試。在回環模式下,從Tx 上發送的數據將被Rx 輸入端接收。

 

 

四、CubeMx配置

說明:

  在使用STM32CubeMx配置的時候,首先要選擇正在使用的芯片的型號,再配置芯片的時鍾,然后才去配置所需要用到的功能。

1、新建項目

1)選擇新建

2)選擇芯片型號

2、時鍾配置

1)配置界面

2)時鍾模式配置

3)設置調試接口

 

4)時鍾配置(盡量將下面方框內的值設成最高值即可)

3、功能配置

 1)啟用串口

 

2)配置串口(默認即可,波特率為115200)

4、生成工程

1)項目信息設置

2)選擇生成必要的代碼

3)生成代碼

4)打開項目(生成代碼成功后會彈出窗口,可以直接打開工程)

注:

  因為STM32CubeMX自動生成的代碼中,沒有設置把每次下載燒寫都重置一下,所以生成代碼后,我們需要自己選上該功能,步驟如下:

1)功能界面

 2)選擇小錘子

3)選擇Debug->Settings

4)選擇Flash Download->勾選Reset and Run

  完成上面的操作后,在每次燒寫都會重置,並運行新下載燒寫的程序了。

 

五、HAL庫關鍵函數說明

 1、初始化/還原初始化函數

復制代碼
1 /* Initialization/de-initialization functions  **********************************/
2 HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart);                                                    //根據UART_InitTypeDef中指定的參數初始化UART模式,並創建關聯的句柄。
3 HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart);                                              //根據UART_InitTypeDef中指定的參數初始化半雙工模式並創建關聯句柄。
4 HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength);                         //根據UART_InitTypeDef中指定的參數初始化LIN模式,並創建關聯的句柄。
5 HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod);  //根據UART_InitTypeDef中指定的參數初始化多處理器模式,並創建關聯的句柄。
6 HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart);                                                  //非初始化UART外圍設備。
7 void HAL_UART_MspInit(UART_HandleTypeDef *huart);                                                              //弱函數UART MSP初始化
8 void HAL_UART_MspDeInit(UART_HandleTypeDef *huart);                                                            //弱函數UART MSP初始化還原
復制代碼

2、IO口操作函數

復制代碼
 1 /* IO operation functions *******************************************************/
 2 HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);//以阻塞模式發送大量數據。
 3 HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); //在阻塞模式下接收大量數據。
 4 HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);               //以非阻塞模式發送大量數據。
 5 HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);                //在非阻塞模式下接收大量數據。
 6 HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);              //以非阻塞模式發送大量數據。
 7 HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);               //在非阻塞模式下接收大量數據。
 8 HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart);                                                 //暫停DMA傳輸。
 9 HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart);                                                //恢復DMA傳輸。
10 HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart);                                                  //停止DMA傳輸。
復制代碼

3、傳輸中斷函數

復制代碼
1 /* Transfer Abort functions */
2 HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart);            //中止正在進行的傳輸(阻塞模式)。
3 HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart);    //中止正在進行的傳輸傳輸(阻塞模式)。
4 HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart);     //中止正在進行的接收傳輸(阻塞模式)。
5 HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart);         //中止正在進行的傳輸(中斷模式)。
6 HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart); //中止正在進行的傳輸(中斷模式)。
7 HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart);  //中止正在進行的接收傳輸(中斷模式)。
復制代碼

4、中斷處理及回調函數

復制代碼
1 void HAL_UART_IRQHandler(UART_HandleTypeDef *huart);                    //函數處理UART中斷請求。
2 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);                //Tx傳輸完成回調函數。
3 void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);            //Tx半傳輸完成回調函數。
4 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);                //Rx傳輸完成回調函數。
5 void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);            //Rx完成一半傳輸回調函數。
6 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);                 //UART錯誤回調函數。
7 void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart);             //UART中止完成回調函數。
8 void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart);     //UART中止完成回調函數。
9 void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart);      //UART中止接收完整的回調函數。
復制代碼

 六、結尾

1、總結

  這篇博客主要是講解一下UART串口通信協議的時序、功能以及工作原理,還有使用STM32CubeMX來配置USART。簡單介紹HAL庫函數的函數調用,有了STM32CubeMX生成的這個HAL庫函數,我們基本不用管協議上的事情了,可以直接調用里面的發送或接收函數來實現UART通信。而我也會在后續繼續編寫有關HAL庫的調用說明,詳細說一下HAL庫是如何使用的。

 

 


免責聲明!

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



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