串口DMA空闲中断接收数据,放在数组uart1_buffer[23]里。
用stlink调试,观测uart1_buffer[],以及串口的SR,CR1寄存器。
PC通过串口助手自动向单片机发送数据,一开始时,接收正常,接收到的数据到会更新到uart1_buffer[]数组里。
然后我不不断的修改串口助手里发送的数据内容,结果过一段时间后,串口接收到的数据,却存放到了uart1_buffer[]数组的后面位置,以此放置。好像没有进入空闲中断了。在空闲中断回调函数里放断点,也没有被触发。
但是SR寄存器的IDLE标志位,确实能看到被置位了,然后又被清空了。
如果不是空闲回调函数里清除IDLE标志位的话,还能有哪些地方能清掉IDLE标志?来了新数据以后自动清掉?
翻手册看到如下介绍,应该只能软件清除IDLE标志位吧?
DLE:监测到总线空闲 (IDLE line detected)
位4
当检测到总线空闲时,该位被硬件置位。如果USART_CR1中的IDLEIE为’1’,则产生中断。由软件序列清除该位(先读USART_SR,然后读USART_DR)。
0:没有检测到空闲总线;
1:检测到空闲总线。
注意:IDLE位不会再次被置高直到RXNE位被置起(即又检测到一次空闲总线)
空闲回调函数如下:
- void IdleCallback(UART_HandleTypeDef *huart)
- {
- if (huart == &huart1)
- {
- if (RESET != __HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
- {
- recvLen = huart1.RxXferCount - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
- // __HAL_UART_DISABLE_IT(&huart1, UART_IT_IDLE);
- __HAL_UART_CLEAR_IDLEFLAG(&huart1);
- HAL_UART_DMAStop(&huart1);
- HAL_UART_Receive_DMA(&huart1, uart1_buffer, UART1_BUFF_SIZE);
- }
- }
- }
复制代码
在串口初始化时使能了IDLE中断:
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
复制代码
主函数里先调用一次DMA接收:
- HAL_UART_Receive_DMA(&huart1, uart1_buffer, UART1_BUFF_SIZE);
复制代码
串口中断部分:
- void USART1_IRQHandler(void)
- {
- /* USER CODE BEGIN USART1_IRQn 0 */
- IdleCallback(&huart1);
- /* USER CODE END USART1_IRQn 0 */
- HAL_UART_IRQHandler(&huart1);
- /* USER CODE BEGIN USART1_IRQn 1 */
- // IdleCallback(&huart1);
- /* USER CODE END USART1_IRQn 1 */
- }
复制代码
奇怪的是,刚开始能正常接收的时候,SR寄存器的ILDE标志位是看不到闪烁的,也许是太快了。这时是可以进到空闲回调函数的断点的。
出现错误后,能看到SR寄存器的IDLE标志位闪烁,进不到回调函数的断点。
或者在空闲中断回调函数里加入断点,触发断点后,再点继续运行,如果点的晚一点的话,也会出现这种现象。
|
已解决,用HAL_UART_AbortReceve()代替HAL_DMA_STOP();
参考:
https://www.stmcu.org.cn/module/forum/thread-606385-1-1.html
评分
查看全部评分
直接调用 HAL_UART_Receive_DMA(&huart1, uart1_buffer, UART1_BUFF_SIZE) 这个函数,其它函数没有涉及到uart1_buffer[]这个数组。
评分
查看全部评分
调试跟进去看看,这个函数的代码有没有做边界检查?