如题:实验现象是用CUBE配置好的代码,HAL库,修改中断函数,增加空闲中断处理不定长数据接收,在使用串口助手进行调试时发现,连续快速点击发送按钮,串口会卡死,为了确认卡死的地方,在所有异常中断中都加了LED指示,最后发现在接收数据时LED指示常亮,证明是卡死在数据接收中。为了验证,在串口助手中设置1MS自动发送,程序不会卡死。但只要在单次发送模式用手连续快速点击发送,100%卡死。怀疑串口助手有问题,换助手后一样。在出现卡死后,程序也不知道跑在哪里了,按复位能恢复;但在用STLINK进入DEBUG模式下跑代码测试,不会出现卡死现象。 
中断部分处理代码如下: 
- void LPUART1_IRQHandler(void)
 
 - {
 
 - //        uint8_t  RCVBUF;
 
 -   /* USER CODE BEGIN LPUART1_IRQn 0 */
 
 -   /* USER CODE END LPUART1_IRQn 0 */
 
 - //  HAL_UART_IRQHandler(&hlpuart1);
 
 -   /* USER CODE BEGIN LPUART1_IRQn 1 */
 
 -   HAL_GPIO_WritePin(led1_GPIO_Port,led1_Pin,GPIO_PIN_SET);        
 
 - //        HAL_UART_Receive_IT(&hlpuart1,&RCVBUF,1);
 
 - //        LPUart1_RX_BUF[LPUart1_REC_Cnt++] = RCVBUF; 
 
 - //        if(LPUart1_REC_Cnt > LPUart1_BUF_SIZE) 
 
 - //                                        LPUart1_REC_Cnt =0;        
 
 -         
 
 - if(__HAL_UART_GET_FLAG(&hlpuart1, UART_FLAG_RXNE) != RESET)  
 
 -     { 
 
 -                         __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_ORE | UART_FLAG_NE | UART_FLAG_PE | UART_FLAG_FE);
 
 -       __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);
 
 -                         if(LPUart1_End_flage == 0)
 
 -                         {
 
 -                           LPUart1_RX_BUF[LPUart1_REC_Cnt] = LPUART1->ISR;    
 
 -         LPUart1_RX_BUF[LPUart1_REC_Cnt] = LPUART1->RDR;    
 
 -         LPUart1_REC_Cnt++;
 
 -                                 if(LPUart1_REC_Cnt > LPUart1_BUF_SIZE) 
 
 -                                         LPUart1_REC_Cnt =0;        
 
 -                         }
 
 -   }
 
 -  else if(__HAL_UART_GET_FLAG(&hlpuart1,UART_FLAG_IDLE) == SET)
 
 -     {
 
 -                          __HAL_UART_CLEAR_IDLEFLAG(&hlpuart1);
 
 -                         __HAL_UART_CLEAR_FLAG(&hlpuart1, UART_FLAG_ORE | UART_FLAG_NE | UART_FLAG_PE | UART_FLAG_FE);
 
 -                printf("UART IT For IDEL \r\n");
 
 -         LPUart1_End_flage = 1;
 
 -         LPUart1_REC_SIZE = LPUart1_REC_Cnt;
 
 -         LPUart1_REC_Cnt = 0;
 
 -    }
 
 - HAL_GPIO_WritePin(led1_GPIO_Port,led1_Pin,GPIO_PIN_RESET);        
 
 -   /* USER CODE END LPUART1_IRQn 1 */
 
 - }
 
 
  复制代码 工程原文件如下,大家有兴趣可以测试验证。 
 
 
 
stm32l051_stop.rar
(5.19 MB, 下载次数: 12)
 | 
评分
查看全部评分
读取SR寄存器的ISR和RDR方可清零状态寄存器,
temp = huart1.Instance->ISR;
temp = huart1.Instance->RDR;
评分
查看全部评分
打印函数是为了确认问题位置才加上去的,实际应用当然没有,否则,打印这个的意义在哪里?包括灯的控制也是为了找问题。
而且,它的HAL库也是这样执行的:
所以修改代码如下,将读ISR和读RDR放到条件上面,屏蔽软件清中断语句,再进行测试验证:
神奇的现象出现了,接收不会卡死了。但因为少了包条件判断,回传数据丢包很严重,空闲中断乱来了?
从这个事件看,ST的M0,软件清串口中断完全是没用的。
这个清中断功能是通过读ISR和RDR寄存器实现了,反而软件写ICR寄存器无效。