• STM32 HAL库关于串口中断烧录程序后可以正常运行,断电重启后无法进入中断的问题分析以及解决方法


    1、情景描述:

      最近在做一个项目,X86的上位机通过串口控制MCU,使用串口中断接收上位机数据时,MCU在上电的情况下烧录程序,可以正常接收上位机的数据,在断电重启后,一直进入不了中断回调函数,上电的情况是X86上电,MCU也同时上电。

    2、原因分析:

      造成这个的原因是因为硬件上电的时候,因为X86跟MCU是同时上电的,上电后会把串口的电平拉高,这个高电平触发了MCU的串口中断,导致MCU的串口中断误以为接收到了一个数据,例如 HAL_UART_Receive_IT(&huart1, (uint8_t *)Rx_buff, 5) 这里,上电后MCU误以为接收了一个数据,还剩下4个数据没有接收,然后上位机每次发送5个数据过来后MCU中断数据接收个数错误,所以一直无法进入中断回调函数。

      我们看到 HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) ,里面的 RxXferCount  是告诉我们中断要接收的剩余数据量大小,根据上面举例子的话,上电时因为那个高电平的原因导致 RxXferCount 变成了4,如下图打印信息所示

      

       接着我们重新看回 HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) 函数里的调用回调函数部分,下图所示,发现 RxXferCount  要为0的时候才会调用中断回调函数,依旧以上面例子说明,当MCU误以为上电时的高电平为数据时,上位机再发送5个数据下来,RxXferCount  就永远无法变成0,所以导致一直进入不了中断回调函数。

      

     3、解决方法:

      3.1软件解决方法

        软件解决的时候,我们要知道导致这个问题的根源是 RxXferCount 这个值被误判了,所以我们只需要在上电的时候,对这个值进行修正即可;

        首先我们定义一个标志位,用来标志MCU的状态是刚上电的状态  

    char uart_error_flag=0;

        接着我们编写函数对 RxXferCoun 值进行处理

    /***
     函数名:void uart_error(void)
     说  明:解决刚上电时,由于串口电平拉高,导致串口中断误以为接收到了一个字节,
            导致后面接收数据个数一直错误,无法进入中断回调函数问题
     传入值:无
     传出值:无
    **/
    void uart_error(void)
    {
          if( (huart1.RxXferCount < Rxdsize) && (uart_error_flag==0) )
            { 
                /*RxXferCount 告诉我们剩余空间大小,如果剩余空间和总空间不一样,则说明中断收到数据了*/
                printf("huart1.RxXferCount = %d
    ",huart1.RxXferCount);    
                uart_error_flag = 1;
                huart1.RxXferCount = 5; //修改剩余空间,防止无法进入回调        
            }
    }

        最后我们在 main 函数里的 while 循环前调用即可

    int main(void)
    {
    
      HAL_Init();
      SystemClock_Config();
      MX_GPIO_Init();
      MX_USART2_UART_Init(); //初始化打印信息串口
      MX_USART1_UART_Init(); //初始化中断接收串口  
      HAL_UART_Receive_IT(&huart1, (uint8_t *)Rx_buff, Rxdsize); //打开串口中断接收
      uart_error(); //处理上电时串口中断误判的问题
      while (1)
      {
       /* 注意要在中断回调函数里重新打开串口中断接收,否则串口中断接收只能接收一次 */
      }
    }

      3.2 硬件解决方法

        硬件解决方法比较粗暴,就是做一个电源延时电路,等X86重新上电后,再给MCU上电。

    补充说明:

      使用DMA接收时候不会出现这种情况,不过使用DMA接收,如果上位机发送数据过快,会出现数据粘包现象,例如上位机发送是数据一包是5个数据,如果上位机发送数据过快(20ms以内),MCU就好会把接收到的好几包数据当做一包数据来处理,例如把3包数据当做1包数据来处理,这样MCU就会误以为一包数据的15个了,出现误判的情况,不过它接收的数据是准确的,就是分包能力没有串口中断强。

  • 相关阅读:
    MyEclipse中的几种查找方法
    WebLogic初学笔记
    CountDownLatch源码分析
    linux--句柄相关
    linux命令--wc
    Spring源码解析(九)--再来说说三级缓存
    定位JVM内存泄漏常用命令和方法
    Mybatis整合Spring之MapperFactoryBean怎么拿到的SqlSessionFactory
    Mybatis3.3.0 Po类有LocalDateTime字段报错
    时间范围查询优化技巧
  • 原文地址:https://www.cnblogs.com/xingboy/p/11753769.html
Copyright © 2020-2023  润新知