title: HAL-DMA中断空闲接受不定长数据
tags:
- STM32
- Hal
- Cubemax
面对无规律长度的数据帧如何处理?
- 不定长数据接收可以使用每帧数据发送完成后会有一定的空闲时间"帧的时间间隔?"
如果你想每帧都要可以采用dma加空闲中断的方式空闲中断一次就是一帧数据接受完成再去做其它数据解析和其他业务出来不过需要我们注意的是这里面有个小坑
__HAL_UART_CLEAR_IDLEFLAG(&huart1);
我先说下如何处理:
if (__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)== SET)
{uint16_t temp = 0;__HAL_UART_CLEAR_IDLEFLAG(&huart1);HAL_UART_DMAStop(&huart1);temp = huart1.Instance->SR;temp = huart1.Instance->DR;temp = hdma_usart1_rx.Instance->CNDTR;Usart1type.UsartDMARecLen = USART1_DMA_REC_SIE - temp;HAL_UART_RxCpltCallback(&huart1);
}
这个函数网上说什么有bug还是啥
-
temp = huart1.Instance->SR;
-
temp = huart1.Instance->DR;
-
还要读一下这两寄存器
原理很简单就是打开空闲中断函数
触发中断后dma接收
接收完后搬到接收数组里面清除dma数组
做业务逻辑处理 处理完就全部数组清除
操作步骤如下:
1.开启中断函数
void EnableUsart_IT(void){__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);__HAL_UART_CLEAR_IDLEFLAG(&huart1);HAL_UART_Receive_DMA(&huart1,Usart1type.Usart1DMARecBuffer,USART1_DMA_REC_SIE);}
2.触发中断后dma接收
void USART1_IRQHandler(void)
{/* USER CODE BEGIN USART1_IRQn 0 */if (__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE)== SET){uint16_t temp = 0;__HAL_UART_CLEAR_IDLEFLAG(&huart1);HAL_UART_DMAStop(&huart1);temp = huart1.Instance->SR;temp = huart1.Instance->DR;temp = hdma_usart1_rx.Instance->CNDTR;Usart1type.UsartDMARecLen = USART1_DMA_REC_SIE - temp;HAL_UART_RxCpltCallback(&huart1);}/* USER CODE END USART1_IRQn 0 */HAL_UART_IRQHandler(&huart1);/* USER CODE BEGIN USART1_IRQn 1 */HAL_UART_Receive_DMA(&huart1,Usart1type.Usart1DMARecBuffer,USART1_DMA_REC_SIE); //再次打开DMA接收/* USER CODE END USART1_IRQn 1 */}
3.接收完后搬到接收数组里面清除dma数组
/* USER CODE BEGIN 1 */void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if (huart->Instance==USART1){memcpy(&Usart1type.Usart1RecBuffer[Usart1type.UsartRecLen],Usart1type.Usart1DMARecBuffer,Usart1type.UsartDMARecLen);Usart1type.UsartRecLen=Usart1type.UsartDMARecLen;memset(Usart1type.Usart1DMARecBuffer,0x00,sizeof(Usart1type.Usart1DMARecBuffer));Usart1type.UsartRecFlag=1;}}
4.业务逻辑处理
我就简单的串口打印测试
/* Infinite loop *//* USER CODE BEGIN WHILE */while (1){if (Usart1type.UsartRecFlag==1 ){ printf("re:%s,len%d\r\n",Usart1type.Usart1RecBuffer,Usart1type.UsartDMARecLen); memset(Usart1type.Usart1RecBuffer,0x00,sizeof(Usart1type.Usart1RecBuffer)); Usart1type.UsartRecFlag=0; Usart1type.UsartRecLen=0;}/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */}
参考代码:就一积分 给我点