基於STM32之UART串口通信協議(一)詳解

来源:https://www.cnblogs.com/ChurF-Lin/archive/2019/05/04/10793111.html
-Advertisement-
Play Games

一、前言 1、簡介 寫的這篇博客,是為了簡單講解一下UART通信協議,以及UART能夠實現的一些功能,還有有關使用STM32CubeMX來配置晶元的一些操作,在後面我會以我使用的STM32F429開發板來舉例講解(其他STM32系列晶元大多數都可以按照這些步驟來操作的),如有不足請多多指教。 2、U ...


一、前言

1、簡介

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

2、UART簡介

  嵌入式開發中,UART串口通信協議是我們常用的通信協議(UART、I2C、SPI等)之一,全稱叫做通用非同步收發傳輸器(Universal Asynchronous Receiver/Transmitter)。

3、準備工作

1)Keil5

  鏈接:點擊下載
  提取碼:wrt9

2)STMCubeMX5.1.0版本

  鏈接:點擊下載
  提取碼:20xs

3)STMF429開發板

  

註:

  只要是stm32的開發板都可以用到的,在STM32CubeMx里選對型號、配置好就行了。

二、UART詳解

1、UART簡介

  嵌入式開發中,UART串口通信協議是我們常用的通信協議(UART、I2C、SPI等)之一,全稱叫做通用非同步收發傳輸器(Universal Asynchronous Receiver/Transmitter),是非同步串口通信協議的一種,工作原理是將傳輸數據的每個字元一位接一位地傳輸,它能將要傳輸的資料在串列通信與並行通信之間加以轉換,能夠靈活地與外部設備進行全雙工數據交換。

註:

  在此開發板中,是有USART(Universal Synchronous Asynchronous Receiver and Transmitter通用同步非同步收發器)串口的,USART相當於UART的升級版,USART支持同步模式,因此USART 需要同步始終信號USART_CK(如STM32 單片機),通常情況同步信號很少使用,因此一般的單片機UART和USART使用方式是一樣的,都使用非同步模式。因為USART的使用方法上跟UART基本相同,所以在此就以UART來講該通信協議了。

2、UART通信協議

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。

3、UART功能說明

  介面通過三個引腳從外部連接到其它設備。任何 USART 雙向通信均需要 至少兩個引腳:接收數據輸入引腳 (RX) 和發送數據引腳輸出 (TX):
  RX:接收數據輸入引腳就是串列數據輸入引腳。過採樣技術可區分有效輸入數據和雜訊,從而用於恢複數據。
  TX:發送數據輸出引腳。如果關閉發送器,該輸出引腳模式由其 I/O 埠配置決定。如果使 能了發送器但沒有待發送的數據,則 TX 引腳處於高電平。在單線和智能卡模式下,該 I/O 用於發送和接收數據(USART 電平下,隨後在 SW_RX 上接收數據)。

1)正常 USART 模式下,通過這些引腳以幀的形式發送和接收串列數據:

  • 發送或接收前保持空閑線路
  • 起始位
  • 數據(字長 8 位或 9 位),最低有效位在前
  • 用於指示幀傳輸已完成的 0.5 個、1 個、1.5 個、2 個停止位
  • 該介面使用小數波特率發生器 - 帶 12 位尾數和 4 位小數
  • 狀態寄存器 (USART_SR)
  • 數據寄存器 (USART_DR)
  • 波特率寄存器 (USART_BRR) - 12 位尾數和 4 位小數。
  • 智能卡模式下的保護時間寄存器 (USART_GTPR)。

2)在同步模式下連接時需要以下引腳:

  • SCLK:發送器時鐘輸出。該引腳用於輸出發送器數據時鐘,以便按照 SPI 主模式進行同步發送(起始位和結束位上無時鐘脈衝,可通過軟體向最後一個數據位發送時鐘脈衝)。RX 上可同步接收並行數據。這一點可用於控制帶移位寄存器的外設(如 LCD 驅動器)。時鐘相位和極性可通過軟體編程。在智能卡模式下,SCLK 可向智能卡提供時鐘。在硬體流控制模式下需要以下引腳:
  • nCTS:“清除以發送”用於在當前傳輸結束時阻止數據發送(高電平時)。
  • nRTS:“請求以發送”用於指示 USART 已準備好接收數據(低電平時)。

USART框圖如下:

4、UART工作原理

1)發送接收

  發送邏輯對從發送FIFO 讀取的數據執行“並→串”轉換。控制邏輯輸出起始位在先的串列位流,並且根據控制寄存器中已編程的配置,後面緊跟著數據位(註意:最低位 LSB 先輸出)、奇偶校驗位和停止位。   在檢測到一個有效的起始脈衝後,接收邏輯對接收到的位流執行“串→並”轉換。此外還會對溢出錯誤、奇偶校驗錯誤、幀錯誤和線中止(line-break)錯誤進行檢測,並將檢測到的狀態附加到被寫入接收FIFO 的數據中。

2)波特率產生

  波特率除數(baud-rate divisor)是一個22 位數,它由16 位整數和6 位小數組成。波特率發生器使用這兩個值組成的數字來決定位周期。通過帶有小數波特率的除法器,在足夠高的系統時鐘速率下,UART 可以產生所有標準的波特率,而誤差很小。

3)數據收發

  發送時,數據被寫入發送FIFO。如果UART 被使能,則會按照預先設置好的參數(波特率、數據位、停止位、校驗位等)開始發送數據,一直到發送FIFO 中沒有數據。一旦向發送FIFO 寫數據(如果FIFO 未空),UART 的忙標誌位BUSY 就有效,並且在發送數據期間一直保持有效。BUSY 位僅在發送FIFO 為空,且已從移位寄存器發送最後一個字元,包括停止位時才變無效。即 UART 不再使能,它也可以指示忙狀態。

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

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

4)中斷控制

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

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

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

 5)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 和中斷常式會自動搞定一切。

6)迴環操作

  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庫是如何使用的。

2、後續

1)UART發送

2)待續未完……

~

~

~

~

最後~最後~最後~

 歡迎大家關註我的博客,一起分享嵌入式知識~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • v4.2.5更新內容:1.修複服務實例設置ClearSocketSession參數時,可能出現資源無法釋放而造成異常的情況。2.修複關閉宿主程式後進程仍然無法退出的問題。2.增加機器學習框架。3.優化核心代碼。下載地址:官方下載 7.增加機器學習演算法,通訊採集數據與演算法相結合 7.1概述 Serve ...
  • 輕簡級的ORM既要支持強類型編碼,又要有執行效率,還要通俗易懂給開發者友好提示,結合Expression可輕鬆定製自己所需要功能。 ...
  • 1、Chinese Language 簡體中文漢化插件,和我一樣英文不好的童鞋可以安裝這個插件進行漢化。這個插件重載之後還沒有漢化成功的話,把編輯器關閉重新打開就行了。 2、vscode icons 讓 vscode 資源樹目錄加上圖標,有利於我們進行文件格式的判斷。 3、HTML Snippets ...
  • 前言 在之前的博客中我介紹瞭如何實現生產現場的條碼列印,我們的生活中到處都是條碼,一維碼、二維碼隨處可見,更別說一家從事生產製造加工的工廠了,而條碼種類繁多、離線列印等情況就直接導致了條碼管控上的難度,甚至會出現較為嚴重的品質事件,上一個版本中我是通過Web應用程式調用 WinForm 中的函數進行 ...
  • 前言: 如果讓大家說出一款國內比較熱門的社交軟體,那無疑就是QQ和微信了,說到微信,無不例外的會想到微信公眾號和小程式,所以現在它們已經是很多企業流量及品牌推廣的主要途徑, 而作為一個開發者而言呢,如果想要開發打造一款屬於自己或企業的公眾號,就是需要對微信公眾號平臺API文檔的熟悉。 你可以花上半天 ...
  • [20190502]給顯示輸出加入時間戳.txt--//有別人問我執行腳本中timestamp.pl的代碼,實際上有些文章裡面有源代碼,有一些忘記寫上了。--//貼上:$ cat /usr/local/bin/timestamp.pl#!/usr/bin/perlwhile (<>) {($sec, ...
  • python2.7 setuptools pip 建立軟鏈接 virtualenv virtualenvwrapper ...
  • 筆者經常需要做網路實驗,GNS3就是筆者最喜歡用的模擬器,為了便於實驗,需要能從macos上直接ssh登陸模擬出來的vm,並且vm需要上公網。經過研究,已解決此問題,並以此分享出來 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...