1.前言
使用串口接收不定長數據時,可以有多種方法,比如最常見的有額外使能一個定時器,在超過定時範圍未收到後續的字節時,認為此幀結束;或者利用IDLE中斷,當數據空閒時,自動產生中斷;亦或每接收到一個字節後都通過應用程序進行一次處理。這次我們介紹另外一種方法,在DMA方式下利用硬體接收超時中斷(Receiver timeout interrupt)實現不定長數據的接收。
2.實現原理
首先,並非所有的STM32系列的MCU,也並非所有的USART/UART外設都支持Receiver timeout(RTO)特性,具體的支持情況,可以通過對應晶片的參考手冊去查詢。對於MCU的配置,可以通過USART_RTOR寄存器的RTOEN位使能接收超時功能,通過RTO位域配置超時時間,時間單位為傳輸一個數據位的時間(即波特率)。接收超時在停止位設置不同的情況下,計時的起始位置不同:
- 如果 stop = ' 00 '或 stop = ' 11 ',從停止位的末尾開始。
- 如果 stop = ' 10 ',則從第二個停止位的末尾開始。
- 如果 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為例,配置一個測試工程。
- 系統時鐘配置為 160MHz
- 配置USART1為Asynchrones,管腳配置為 PA9,PA10
- USART1參數:115200bits/s,8bit,None,1Stop
- 使能USART1中斷
- 配置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是否支持這個特性要確認好。
評論