STM32-高速串口,基於DMA的空閒中斷

STM32發送,接收說明

串口接收數據的方式,有兩種,
1,poll
2,int

中斷又分爲一次接收一個數據,和DMA一次接收多個數據。
考慮到數據的高速情況,我們這裏當然是選擇DMA了,

但是DMA有一個不好的點就是中斷觸發機制,要麼是half,要麼是接收完畢,
那麼就有一個很難受的問題,一幀數據,基本上會被切斷,所以對於那些對幀的完整性有較高要求的場景,DMA的這種中斷就很難使用。

常用的解決辦法就是實現一個判空機制,判斷上一次中斷和當前時間是否timeout,如果timeout,就認爲一幀結束,把DMA的數據獲取並拼包之後使用。

但是這個辦法沒辦法準確判定timeout的時間,因爲poll的時間差,或者是幀與幀時間的時間差,導致很難判定成功。

這個時候,STM32的一個牛掰的機制就來了,中斷有一個IDLE中斷源,就是串口進入空閒時,觸發一箇中斷。那DMA+IDLE結合, 就可以很完美的實現快速接受和幀數據分離。

下面是代碼

void UsartReceive_IDLE(UART_HandleTypeDef *huart)
{
stuUartRevFifo *revinfo;
for(int32_t i = 0 ; i < ZQ_UARTINFO_COUNT ; i ++)
{
if(huart == sg_uartRevFifoBuff[i].uart && sg_uartRevFifoBuff[i].revCmd == UART_REV_DMA)
{
// is you
revinfo = &(sg_uartRevFifoBuff[i]);
}
}
uint32_t temp = 0;
if((__HAL_UART_GET_FLAG(revinfo->uart,UART_FLAG_IDLE) != RESET))
{
__HAL_UART_CLEAR_IDLEFLAG(revinfo->uart);
HAL_UART_DMAStop(revinfo->uart);
temp = revinfo->uart->hdmarx->Instance->NDTR;
//rev data count
if(revinfo->revFunc != NULL)
{
revinfo->revFunc(revinfo->revBuff,ZQ_UARTINFO_SIZE - temp);
}
//memset(revinfo->revBuff,0,ZQ_UARTINFO_SIZE);
HAL_UART_Receive_DMA(revinfo->uart,revinfo->revBuff,ZQ_UARTINFO_SIZE);
}
}

這是中斷代碼,這個代碼放在it.c文件的串口中斷中執行。

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	UsartReceive_IDLE(&huart1);
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章