1、前言
- 最近在使用STM32的HAL庫的時候,發現居然沒有集成IDLE中斷處理,自己寫的HAL庫處理邏輯就挺繁瑣,效率又不高,還缺胳膊少腿的。平時項目中的串口接收數據都是不定長的,而IDLE中斷在這一塊做用是很是大的,能夠大大簡化數據接收過程的判斷。本文將介紹基於HAL庫IDLE中斷接收不定長數據。
2、代碼實現
- 首先串口的初始化工做,在初始化過程當中,咱們須要開啓兩個中斷,一個是UART_IT_RXNE接收中斷,此中斷是沒接收到一個字節的數據接收產生一次中斷,另外一個是UART_IT_IDLE空閒中斷,也就是咱們今天的主角。每幀數據發送完成就會有空閒時期,一幀數據接收完成就會產生空閒中斷。這裏咱們不使用 HAL_UART_Receive_IT()函數來初始化了,由於咱們不用HAL庫的那一套,直接進行中斷開啓。
void USART1_Init(uint32_t Bound)
{
UART1_HandleStructure.Instance = USART1;
UART1_HandleStructure.Init.BaudRate = Bound;
UART1_HandleStructure.Init.WordLength = UART_WORDLENGTH_8B;
UART1_HandleStructure.Init.StopBits = UART_STOPBITS_1;
UART1_HandleStructure.Init.Parity = UART_PARITY_NONE;
UART1_HandleStructure.Init.Mode = UART_MODE_TX_RX;
UART1_HandleStructure.Init.HwFlowCtl = UART_HWCONTROL_NONE;
HAL_UART_Init(&UART1_HandleStructure);
HAL_NVIC_EnableIRQ(USART1_IRQn);
HAL_NVIC_SetPriority(USART1_IRQn,3,3);
__HAL_UART_ENABLE_IT(&UART1_HandleStructure,UART_IT_RXNE);//接收中斷
__HAL_UART_ENABLE_IT(&UART1_HandleStructure,UART_IT_IDLE);//空閒中斷
}
- 下來是寫咱們的中斷服務函數,咱們直接在USART1_IRQHandler()裏寫咱們的處理邏輯,不須要再調用HAL_UART_IRQHandler()函數。若是進入的是接收中斷,咱們把接收到的字節放入到緩衝區,若是接收長度超過了緩衝區字節就再也不處理直接丟棄。若是進入的是空閒中斷,則表示一幀數據接收完成,這時候調用咱們的回調函數進行數據處理便可,通常是放到中斷外進行處理,我這裏爲了簡化因此直接寫到中斷裏面了。注意清除IDLE的中斷標誌要使用__HAL_UART_CLEAR_IDLEFLAG()進行,否則會一直進入中斷。
void USART1_IRQHandler(void)
{
uint8_t res = 0;
//接收中斷
if(__HAL_UART_GET_FLAG(&UART1_HandleStructure,UART_FLAG_RXNE) != RESET)
{
HAL_UART_Receive(&UART1_HandleStructure,&res,1,1000);
//將數據放入緩衝區
if(rxConut < RX_BUFFER_SIZE)
{
aRxBuffer[rxConut] = res;
rxConut++;
}
__HAL_UART_CLEAR_FLAG(&UART1_HandleStructure,UART_FLAG_RXNE);
}
//空閒中斷
if(__HAL_UART_GET_FLAG(&UART1_HandleStructure,UART_FLAG_IDLE) != RESET)
{
//一幀數據接收完成
USART1_IdleCallback(aRxBuffer,rxConut);
rxConut = 0;
__HAL_UART_CLEAR_IDLEFLAG(&UART1_HandleStructure);
}
}
//回調函數
void USART1_IdleCallback(uint8_t *pData,uint16_t len)
{
while(__HAL_UART_GET_FLAG(&UART1_HandleStructure,UART_FLAG_TC) != SET);
HAL_UART_Transmit(&UART1_HandleStructure,pData,len,1000);
}
3、測試結果
- 我設置的波特率爲115200,數據發送間隔10ms,附上測試圖。