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=;

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

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

    最后我们在 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 ()
{
/* 注意要在中断回调函数里重新打开串口中断接收,否则串口中断接收只能接收一次 */
}
}

  3.2 硬件解决方法

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

补充说明:

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

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

  1. STM32 HAL库 UART 串口读写功能笔记

    https://www.cnblogs.com/Mysterious/p/4804188.html STM32L0 HAL库 UART 串口读写功能 串口发送功能: uint8_t TxData[10 ...

  2. (4)STM32使用HAL库实现串口通讯——理论讲解

    一.查询模式 1. 二.中断模式 1.中断接收. 1.1先看中断接收的流程(以 USART2 为例) 在启动文件中找到中断向量 USART2_IRQHandler 找到USART2_IRQHandle ...

  3. stm32 hal库串口通信资料汇集

    串口的发送接收函数:HAL_UART_Transmit();串口轮询模式发送,使用超时管理机制.HAL_UART_Receive();串口轮询模式发送,使用超时管理机制.HAL_UART_Transm ...

  4. stm32 HAL库笔记(零)

    最近在设计四旋翼飞行器,用stm32f407,有三种开发方式可以选择:一.寄存器开发.二:库函数开发.三:HAL库开发,考虑了一下,选择了HAL库,原因如下: 1. 寄存器开发相对较慢,寄存器很多,配 ...

  5. STM32 HAL库详解 及 手动移植

    源: STM32 HAL库详解 及 手动移植

  6. 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章

    从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章  如何使用本书 1.1  本书的参考资料 本书参考资料为:<STM32 ...

  7. STM32 HAL库使用中断实现串口接收不定长数据

    以前用DMA实现接收不定长数据,DMA的方法接收串口助手的数据,全部没问题,不过如果接收模块返回的数据,而这些数据如果包含回车换行的话就会停止接收,例如接收:AT\r\nOK\r\n,就只能接收到AT ...

  8. STM32 HAL库利用DMA实现串口不定长度接收方法

    参考:https://blog.csdn.net/u014470361/article/details/79206352 我这里使用的芯片是 F1 系列的,主要是利用 DMA 数据传输方式实现的,在配 ...

  9. STM32F072从零配置工程-基于HAL库的串口UART中断配置

    先上一个采用串口直接传输的Demo: 此处的思路是完全采用HAL库来实现的,核心是运用HAL_UART_Transmit_IT和HAL_UART_Receive_IT两个函数来实现的,可以作为一个De ...

随机推荐

  1. jqgrid(转载)

    一.主要API接口getGridParam.setGridParam: getGridParam方法: getGridParam("url"): 获取当前的AJAX的URL get ...

  2. 创建多个Oracle数据库及相应的实例

    转 http://blog.csdn.net/luiseradl/article/details/6972217 对于使用过SQL Server数据库的用户可以会对Oracle中的数据库的实例的概念理 ...

  3. HDU 1506 Largest Rectangle in a Histogram (dp左右处理边界的矩形问题)

    E - Largest Rectangle in a Histogram Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format: ...

  4. bash shell 合并文件

    # 按列合并文件 paste file1 file2 file3 > file4 # 要先 sort, 再 file1 file2 paste格式为: paste -d -s -file1 fi ...

  5. linux下建立无线wifi------简单实用!

    一 安装必要软件安装hostapd :    sudo apt-get install hostapd安装DHCP:    sudo apt-get install dhcp3-server 二 配置 ...

  6. mysql性能优化学习笔记(2)如何发现有问题的sql

    一.使用mysql慢查询日志对有效率问题的sql进行监控      1)开启慢查询       show variables like ‘slow_query_log’;//查看是否开启慢查询日志   ...

  7. 树莓派安装 dig命令

     apt-get install  dnsutils

  8. Android服务端的设计

    1.创建自己的MyServletContextListener.java: package yybwb; import java.net.ServerSocket; import javax.serv ...

  9. MongoDB,分组,聚合

    使用聚合,db.集合名.aggregate- 而不是find 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数.MongoDB的聚合管道将MongoDB文档在一个管道处理完 ...

  10. 使用time+dd测试硬盘读写速度

    命令:time dd if=/dev/zero bs=1M count=2048 of=direct_2G   此命令为在当前目录下新建一个2G的文件 Demo如下: 写速度: time dd if= ...