STM32串口 DMA 接收不定長數據的一種方法

1.前言

使用串口接收不定長數據時,可以有多種方法,比如最常見的有額外使能一個定時器,在超過定時範圍未收到後續的字節時,認為此幀結束;或者利用IDLE中斷,當數據空閒時,自動產生中斷;亦或每接收到一個字節後都通過應用程序進行一次處理。這次我們介紹另外一種方法,在DMA方式下利用硬體接收超時中斷(Receiver timeout interrupt)實現不定長數據的接收。

 

2.實現原理

首先,並非所有的STM32系列的MCU,也並非所有的USART/UART外設都支持Receiver timeout(RTO)特性,具體的支持情況,可以通過對應晶片的參考手冊去查詢。對於MCU的配置,可以通過USART_RTOR寄存器的RTOEN位使能接收超時功能,通過RTO位域配置超時時間,時間單位為傳輸一個數據位的時間(即波特率)。接收超時在停止位設置不同的情況下,計時的起始位置不同:

  1. 如果 stop = ' 00 '或 stop = ' 11 ',從停止位的末尾開始。
  2. 如果 stop = ' 10 ',則從第二個停止位的末尾開始。
  3. 如果 stop = ' 01 ',則從停止位的起始開始。

當計數超過 RTO 位域的設定值時,且使能了 RTOIE 位,就會產生一個錯誤中斷,此時我 們就可以認為此幀結束,進而進行處理。


3.應用示例

HAL 庫已經為我們提供了操作 RTO 相關的 API,應用開發過程,我們直接調用即可。

void HAL_UART_ReceiverTimeout_Config(UART_HandleTypeDef *huart, uint32_t TimeoutValue);

HAL_StatusTypeDef HAL_UART_EnableReceiverTimeout(UART_HandleTypeDef *huart);

HAL_StatusTypeDef HAL_UART_DisableReceiverTimeout(UART_HandleTypeDef *huart);



以STM32U575ZIT6為例,配置一個測試工程。

  1. 系統時鐘配置為 160MHz
  2. 配置USART1為Asynchrones,管腳配置為 PA9,PA10
  3. USART1參數:115200bits/s,8bit,None,1Stop
  4. 使能USART1中斷
  5. 配置USART1_RX GPDMA






生成工程後,配置超時時間,使能接收超時功能,使能串口的DMA接收,處理串口的錯誤回調函數(接收超時後,HAL庫中經HAL_UART_ErrorCallback()回調)。

/* USER CODE BEGIN 2 */

HAL_UART_ReceiverTimeout_Config(&huart1, huart1.Init.BaudRate/100); //10ms BaudRate = 115200

HAL_UART_EnableReceiverTimeout(&huart1);

HAL_UART_Receive_DMA(&huart1, Uart_RcvBuf, MAX_UART_RCV_LEN);

/* USER CODE END 2 */




#define MAX_UART_RCV_LEN 10 //config the max receive data length

uint8_t Uart_RcvBuf[MAX_UART_RCV_LEN];

uint16_t Uart_RcvLen;

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)

{

if(huart == &huart1)

{

/* Check if DMA mode is enabled in UART */

if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))

{

if((huart->ErrorCode & HAL_UART_ERROR_RTO) == HAL_UART_ERROR_RTO)

{

uint16_t nb_remaining_rx_data = (uint16_t)

__HAL_DMA_GET_COUNTER(huart->hdmarx);

Uart_RcvLen = MAX_UART_RCV_LEN - nb_remaining_rx_data;

}

HAL_UART_Receive_DMA(&huart1, Uart_RcvBuf, MAX_UART_RCV_LEN);

}

}

}


HAL_UART_ErrorCallback 是一個支持所有錯誤中斷的回調函數,在處理RTO錯誤引起的中斷響應時,可以通過 ErrorCode 增加相應的判斷。通過調用__HAL_DMA_GET_COUNTER(huart->hdmarx)可以得到DMA未搬移完的字節數,從而得到已搬移完成的字節數。

 

4.總結

利用RTO方式接收不定長串口數據,相比用定時器計時,可以節省一個硬體定時器資源,同時減少了定時器每次進入中斷處理的運行時間;相比IDLE的方式,可以更靈活的配置超時時間。但需注意的是,所選用的MCU以及所使用的USART/UART是否支持這個特性要確認好。

★博文內容參考自 網站,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★文明上網,請理性發言。內容一周內被舉報5次,發文人進小黑屋喔~

參考來源

false: https://www.stmcu.com.cn/Designresource/detail/LAT/712020

評論