[STM32] 19-UART

Morgan Ting
閱益如美
Published in
13 min readNov 12, 2022
Photo by Fede Fream on Unsplash

Universal Asynchronous Receiver/Transmitter , UART 是一種非同步串列傳輸介面,提供單工、半雙工與全雙工傳輸模式常應用於電腦與工業設備之間的資料傳輸。本文章介紹 STM32 的 UART 傳輸,開發環境使用 STM32CubeIDE 並搭配 Hardware Abstraction Layer, HAL 函式庫進行實作。

文章內容

  1. UART 簡介
  2. STM32 的 UART
  3. 實作
  4. 成果展示

工具與材料

  1. STM32CubeIDE
  2. Blue Pill ( STM32F103C8T6 ) 開發板
  3. ST-LINK v2
  4. USB to TTL 模組
  5. Hercules SETUP utility 串列埠監控軟體

UART 簡介

UART通用非同步收發傳輸介面已發展許久衍生出許多傳輸規格如 RS-232、RS448… 等,差別在於電氣規格相異而原理是一樣的。

UART 由二條資料線分別負責收發訊息,結構相當簡單。

UART Connection

UART 的資料格式

UART 資料格式包含以下內容:

  • 1 個起始位元。拉低線路電位表示將發起傳輸。
  • 資料位元。可以是 5 ~ 8 位元資料,從 LSB 開始發送。
  • 校驗位元。奇偶同位校正,依資料內容進行奇偶同位元校正。
  • 停止位元。 1 ~ 2 位元停止位元表示資料尾端。

UART 線路處於空閒狀態時保持在高電位,因此若有任一裝置拉低電位即表示要傳輸資料。由於資 料是串列傳輸因此傳輸速率使用鮑率 ( Baud rates ) 其單位是 bit per second, bps 衡量每秒鐘能傳輸多少位元數量。

STM32 的 UART

STM32 依晶片型號配有多組 UART 硬體電路,除了非同步式傳輸之外也能進行同步式傳輸 Universal Synchronous/Asynchronous Receiver/Transmitter, USART。

STM32 的 USART / UART 特性如下:

  • 單工、半雙工與全雙工傳輸。
  • 傳輸速率最高可達 4.5 M bps。
  • 8 或 9 位元資料長度。
  • 1 到 2 個停止位元。
  • 支援 DMA 傳輸。
  • 可發送校驗位元以及對接收資料進行校驗檢查。

系統方塊圖

Ref : datasheet

操作方式

操作 UART / USART 有三種方式:

  • 阻斷式 ( Block ) ,程序使用輪詢法等待傳輸完成,操作簡單但是會消耗時間。
  • 中斷式 ( Interrupt ) ,利用中斷進行資料傳輸,每傳輸 1 Byte 會觸發一次中斷。
  • 直接記憶體存取 ( DMA ),由 DMA 進行資料傳輸,CPU 不介入傳輸過程。

由系統方塊圖可以了解從底層操作 STM32 的 UART 很費神,有多個暫存器需要設定。好在我們可以利用 HAL 函式庫來簡化操作,以下介紹 UART相關 APIs 。

一、進行阻斷式操作時

1. 傳送資料

HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

當中的參數 huart 表示所使用的 UART 模組,通常後面會帶有數字,例如 huart1 表示使用 UART 1 。pData 是待傳輸的資料,Size 是該筆資料長度,Timeout 逾時時間,單位是毫秒,若傳輸逾時就會放棄避免陷入無限等待。

2. 接收資料

HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)

參數同傳送函式,這裡的 pData 是存放所接收到的資料。

二、使用中斷方式

1. 傳送資料

HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

回調函數 ( call back function )

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)

2. 接收資料

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

回調函數

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

三、使用 DMA

1. 傳輸資料

HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

回調函數

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)

2. 接收資料

HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

回調函數

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

電路圖

實作

本次實作利用 STM32 Blue Pill 開發板上的 UART 3 與透過 USB to TTL 模組與電腦連接,電腦端使用串列埠監控軟體 hercules 進行訊息收發。訊息從 hercules 發給 STM32 後 STM32 會將原訊息發給電腦端。

UART 3 的 發送端 TxD 位於 PB10 ,接收端 RxD 位於 PB11 腳位。

USB to TTL 模組搭載 CP2102 轉換晶片,其中 TxD 連接到 STM32 的 RxD、模組的 RxD 連接到 STM32 的 TxD,模組的 5v 與 GND 分別連接到 Blue Pill 開發板的 5v 與 GND。

須注意先用 ST-Link 將程式燒錄到開發板後,移除 ST-Link 再接上 USB to TTL 模組避免電源問題造成損壞。

一、開啟 STM32CubeIDE 開發環境,建立一個新的專案。

start a project

二、選擇微處理器型號,輸入F103C8 可以快速找到,選擇該型號後按下 「Next」鍵。

target selection

三、輸入專案名稱後按下「Finish」鍵。

project name

四、設定 SYS ,Debug 選項選擇 「Serial Wire」。

SYS

五、RCC 時脈源,HSE 選擇 「Crystal / Ceramic Resonator」,其中 HSE 是連接開發板上的 8 MHz 震盪器提供系統使用。

RCC

六、 Clock Configuration 設定系統時脈為 72 MHz 。

Clock Configuration

七、點開 「Connectivity 」可以看到各項通訊界面,選擇 USART 3。

  • Mode 選擇 「Asynchronous 」。非同步模式。
  • Baud Rate 選擇 「 9600 」。鮑率越大速度越快但容易丟失資料。
  • Word Length 選擇 「 8 」位元。
  • Parity 選擇 「 None 」不使用奇偶同位校正碼。
  • Stop Bit 選擇 「 1 」,使用 1 個停止位元。
USART 3 Configuration

在 NVIC Setting 中斷控制頁面,將 「 USART 3 global interrupt 」打勾,啟用中斷功能。

Enable Interrupt

八、完成後可以看到 Pin 腳的設定狀況,PB10 與 PB11 自動設定成 Tx 與 Rx。

pin

九、project manager 確認專案名稱等是否需要更改。

project manager

十、完成設定後,按下儲存鍵或是上方功能列 「 Project 」==> 「 Generate code 」產生程式碼。

Generate Code

十一、進入程式碼編輯畫面後開始撰寫程式碼。

首先,定義一個陣列變數用來存放接收到的資料,在 /* USER CODE BEGIN PV */ 區段宣告變數。

/* USER CODE BEGIN PV */
uint8_t Rx_data[12] = {0}; // 宣告長度 12 Byte 陣列變數
/* USER CODE END PV */

再來尋找中斷 call back 回調函數,從左方檔案路徑找到 「 Core 」==> 「 Src 」==> 「 stm32f1xx_it.c 」展開可以看到 「 USART3_IRQHandler 」即是中斷進入點,滑鼠雙擊可以打開該檔案,將 「 HAL_UART_IRQHandler 」圈選起來後按滑鼠右鍵選擇 「 Open Declaration」。

最後,往下找到 「void HAL_UART_RxCpltCallback 」回調函式將其複製並貼到 「 main.c 」主程式下方的 /* USER CODE BEGIN 4 */ 區段內。

接下來就是啟動帶有中斷功能的 UART 並在 call back 函式內寫下我們要的功能。

在 /* USER CODE BEGIN 2 */ 區段內啟動 UART 接收功能。

/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart3, Rx_data, 12);
/* USER CODE END 2 */

在下方 /* USER CODE BEGIN 4 */ 區段內寫下收到資料後再傳送出去。

/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART3)
{
HAL_UART_Transmit_IT(&huart3, Rx_data, 12); // 送出 Rx_data 內容
HAL_UART_Receive_IT(&huart3, Rx_data, 12); // 再次啟動 UART 接收功能
}
}
/* USER CODE END 4 */

十二、按下綠色撥放鍵進行編譯與程式上傳。

十三、在 Debugger 項目將 「ST-LINK S/N 」打勾並點擊右方 「SCAN」按鈕。

此時會顯示 ST-Link v2 編號,沒問題後按下 「OK 」按鈕即開始編譯並上傳程式到開發板。

十四、移除 ST-Link v2 燒錄器並接上 USB to TTL 模組後,開啟 Hercules SETUP utility 串列埠監控軟體。須注意參數設定必須與先前在 STM32CubeIDE 中設定的參數一樣,串列埠名稱可從裝置管理員找到。

輸入一些文字按下 「 Send 」鈕後可觀察到成果。

成果展示

本次實驗使用 USART 與電腦端進行訊息傳送,藉由串列埠監控軟體觀察到功能運行無礙。圖中的紅色字體是電腦端發送出去的訊息,黑色字體是 STM32 送給電腦端的訊息。

由於程式中設定存放資料長度是 12 Byte ,而 1 個字元占用 1 Byte ,以 「 HELLO WORLD! 」剛好是 12 Byte 塞好塞滿,如果送出少於 12 Byte 的訊息會保留等到塞滿 12 Byte 時 STM32 才會有回應。這是因為 HAL_UART_Receive_IT 函式只能固定資料長度,參數中的 Size 大小塞好塞滿才算圓滿。

此外,若不想使用 Hercules SETUP utility,那麼 Arduino 的串列埠監控功能也可以達到相同監控功能。

Result

總結

UART / USART 串列通訊是常見的資料傳輸媒介,可用在機器之間互通訊息。關於 STM32 的 UART總結如下:

  • UART / USART 是一種串列傳輸介面。實務上較常用 UART 非同步式傳輸。
  • 資料格式包含 1 個起始位元、8 或 9 位資料位元、1 個奇/偶同位校正位元、1 到 2 個停止位元。線路閒置時呈現高電位。
  • 實作傳輸功能可採用阻斷式、中斷式與 DMA 等三種方式。
  • 使用 USB to TTL 模組與 Blue Pill 電源連接用 5v 。

參考資料

  1. STM32F103 手冊 [ 連結 ]
  2. STM32F1 HAL and Low-layer drivers [ 連結 ]
  3. STM32F103 電器特性 [ 連結 ]
  4. Hercules SETUP utility [ 連結 ]
  5. 網路教學,非固定長度也能響應中斷 [ 連結 ]
  6. 網路教學,關於 UART 接收中斷的解析 [ 連結 ]

感謝讀者

若文章有幫助到您可以拍手給我鼓勵,免費支持我。

相關文章

  • [STM32] 00-Install STM32CubeIDE [連結]
  • [STM32] 01-ST-LINK [連結]
  • [STM32] 02-STM32F103C8T6 [連結]
  • [STM32] 03-GPIO-Output [連結]
  • [STM32] 04-GPIO-Input [連結]
  • [STM32] 05-Ext-Interrupt [連結]
  • [STM32] 06-Timer-Basic [連結]
  • [STM32] 07-Timer-Interrupt [連結]
  • [STM32] 08-Timer-Output_Compare [連結]
  • [STM32] 09-Timer-PWM [連結]
  • [STM32] 10-Timer-Input_Capture [連結]
  • [STM32] 11-RTC-Second-Interrupt [連結]
  • [STM32] 12-RTC-Alarm_Interrupt [連結]
  • [STM32] 13-Independent_Watch_Dog [連結]
  • [STM32] 14-Windows_Watch_Dog [連結]
  • [STM32] 15-ADC_Conversion [連結]
  • [STM32] 16-ADC_Conversion_Temperature_Sensor [連結]
  • [STM32] 17-ADC_Convversion_DMA [連結]
  • [STM32] 18-SPI [連結]
  • [STM32] 19-UART [連結]
  • [STM32] 20-I2C [連結]

--

--

Morgan Ting
閱益如美

用好奇心探索世界。喜愛學習樂於分享。