STM32 串口接收大量数据导致死机
http://blog.csdn.net/origin333/article/details/49992383
以下文章出自上面的链接。感谢原创作者的分享。
在一项目中,使用STM32作为主控,程序运行一段时间后概率出现主循环卡死现象。
问题分析如下:
1、程序USART2不停接收并处理串口数据,波特率115200;
2、主循环卡死;
3、USART1中断及TIM2中断响应函数运行正常;(USART1及TIM2中断优先级均比USART2高)
4、出现现象后,拔掉USART2的接收数据线,现象不能回复正常;
5、出现现象后,拔掉后再插入USART2的接收数据线,现象不能回复正常;
6、并未出现HardFault现象;
基于以上4点,可能原因如下:
1、USART2接收中断标志没有清除;
2、堆栈数据溢出,导致程序异常;
3、USART2中断重入导致异常;
4、USART2中断函数被异常响应;
5、USART2中断ERR;
对于以上可能原因一一分析:
1、中断接收标志清楚问题:
(1)USART2接收中断响应函数如下:
1 void USART2_Istr(void)
2 {
3 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
4 {
5 USART_ClearFlag(USART2, USART_FLAG_RXNE);
6 USART_ClearITPendingBit(USART2, USART_IT_RXNE);
7 Data = USART_ReceiveData(USART2);
8 //Process Data
9 }
10 }
(2)出现现象后,通过Usart1中断获取到如下信息:
a. USART_GetITStatus(USART2, USART_IT_RXNE) == RESET
b. USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET
c. 执行USART_ClearFlag(USART2, USART_FLAG_RXNE)及 USART_ClearITPendingBit(USART2, USART_IT_RXNE)后无法恢复正常;
结论:与USART2 RXNE中断标志无关。
2、堆栈数据溢出,导致程序异常;
(1)使用2倍栈空间,问题存在,概率不会降低;
(2)使用0.5倍栈空间,问题存在,概率不会提高;
(3)使用0.25倍栈空间,程序运行进入HardFault;
结论:与堆栈无关。
3、USART2中断重入导致异常;
(1)使用标志法,确认出现问题时,中断响应函数没有重入;
结论:中断响应函数没有重入。
4、USART2中断函数被异常响应;
(1)USART2中断函数可以被正常调用,只是不停进入中断响应函数,卡死主循环;
(2)检查程序Map,没发现与中断响应函数地址相同的函数;
(3)检查中断向量表,没发现异常;
结论:中断函数没有被异常调用;
5、USART2中断ERR;
(1)关闭USART2中断,主循环恢复正常;
(2)启动USART2中断,主循环卡死;
(3)获取到DR=0x0000;
(4)USART_GetITStatus取到:RXNE=0,PE=0,TXE=0,TC=0,IDLE=0,LBD=0,CTS=0,ERR=0,ORE=0,NE=0,FE=0;
(5)通过USART_ClearITPendingBit清除CTS,LBD,TXE,TC,RXNE,IDLE,ORE,NE,FE,PE均无法恢复正常;
(6)通过USART_GetFlagStatus:
a.第一次:CTS=0,LBD=0,TXE=1,TC=1,RXNE=0,IDLE=1,ORE=1,NE=0,FE=0,PE=0
b.第二次:CTS=0,LBD=0,TXE=1,TC=1,RXNE=0,IDLE=0,ORE=0,NE=0,FE=0,PE=0
c.第三次:CTS=0,LBD=0,TXE=1,TC=1,RXNE=0,IDLE=0,ORE=0,NE=0,FE=0,PE=0
(7)通过USART_ClearFlag清除CTS,LBD,TXE,TC,RXNE,IDLE,ORE,NE,FE,PE均无法恢复正常;
分析:
(1)为什么通过USART_GetITStatus获取了所有中断标志,均为RESET(TC、TXE中断没开),还会进中断?
(2)为什么通过USART_ClearITPendingBit清除了所有中断标志,还会进入中断?
(3)为什么关闭USART2中断后再次启动它还会进入卡死状态?
(4)为什么通过USART_GetFlagStatus第一次和第二次读的不一样?而且USART_ClearFlag清掉所有Flag,也没法恢复正常?
带着以上几个疑问,查看了参考手册,才恍然大悟!如下:
(1)打开RXNEIE,默认会同时打开RXNE和ORE中断。
(2)必须第一时间清零RXNE,如没及时清零,下一帧数据过来时就会产生Overrun error!
(3)错误就是ORE导致的
出现错误时,读了RXNE=0,出错应该是上图打勾的情况,如下
(4)如文档说明,要清除ORE中断需要按顺序读取USART_SR和USART_DR寄存器!
那就是说USART_ClearFlag清掉所有Flag后,还必须读一遍USART_DR寄存器!
经过测试出现问题后依次读读取USART_SR和USART_DR,程序回复正常!
(5)那还有一个问题,为什么USART_GetITStatus读不到ORE中断标志?
读USART_GetITStatus函数就知道了,只有CR3的EIE置1且SR的ORE置1,读出来USART_GetITStatus(USART2, USART_IT_ORE) 才是 SET。
见CR3的EIE位说明。
解决办法,出现通过接收时,通过USART_GetFlagStatus读取ORE,若不为RESET,则读取DR数据丢弃。
修改如下:
1 void USART2_NewIstr(void)
2 {
3 if (USART_GetFlagStatus(USART2, USART_FLAG_PE) != RESET)
4 {
5 USART_ReceiveData(USART2);
6 USART_ClearFlag(USART2, USART_FLAG_PE);
7 }
8
9 if (USART_GetFlagStatus(USART2, USART_FLAG_ORE) != RESET)
10 {
11 USART_ReceiveData(USART2);
12 USART_ClearFlag(USART2, USART_FLAG_ORE);
13 }
14
15 if (USART_GetFlagStatus(USART2, USART_FLAG_FE) != RESET)
16 {
17 USART_ReceiveData(USART2);
18 USART_ClearFlag(USART2, USART_FLAG_FE);
19 }
20
21 if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
22 {
23 USART_ClearFlag(USART2, USART_FLAG_RXNE);
24 USART_ClearITPendingBit(USART2, USART_IT_RXNE);
25 Data = USART_ReceiveData(USART2);
26 }
27 }
总结:
1、看文档!看文档!还是看文档!(重要的事情要说3遍)
2、库函数用的时候,也要注意其实现,稍有不慎就可能用错。
3、注意USART_GetFlagStatus与USART_GetITStatus的区别,还有中断响应机制。
4、任意时候都要考虑出错处理。
查了一下 ,也有人遇到了相同的情况,可参考:
http://blog.csdn.net/love_maomao/article/details/8234039
STM32 串口接收大量数据导致死机的更多相关文章
- STM32串口接收不定长数据原理与源程序(转)
今天说一下STM32单片机的接收不定长度字节数据的方法.由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的A ...
- stm32串口接收完整的数据包
参考了文章:<stm32串口中断接收方式详细比较> 文章地址:http://bbs.elecfans.com/jishu_357017_1_1.html 借鉴了第四种中断方式 串口的配置这 ...
- STM32串口usart发送数据
主函数请直接关注41行到47行代码!! #include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h> #include ...
- stm32 串口接收一次后再也无法接受,接受都为0
经检测为串口接受后进入别的程序,开辟了2048的临时数组,因为堆栈溢出.stm32总共堆栈为
- Win10 的微软输入法输入稍快竟然会导致死机
一周前,新装机器一次,竟然死机两三次,多发生在敲字时,最近逐步排查发现的这个问题,查阅了一下网上方案,果断采用了第三方输入法,至今没再死机过. 不过第三方输入法也不安分,是不是推送点头条新闻过来,和驱 ...
- stm32串口接收发送数据处理
/************************************************************* Function Name : Uart1_Send_Byte* Desc ...
- STM32移植RT-Thread后的串口在调试助手上出现:(mq != RT_NULL) assert failed at rt_mq_recv:2085和串口只发送数据不能接收数据问题
STM32移植RT-Thread后的串口在调试助手上出现:(mq != RT_NULL) assert failed at rt_mq_recv:2085的问题讨论:http://www.rt-thr ...
- STM32 ~ USART接收不定长数据
IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断.什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据. ...
- 018_STM32程序移植之_串口接收中文
(一)在平时数据传输中很少用到接收中文的情况,但是最近需要用到就花了半天时间来弄弄 (二)接收原理,从现在接收情况分析:一个中文占两个数据的空间,也就是两个十六进制可以转化成为一个中文 (三)示例情况 ...
随机推荐
- Linux递归压缩图片脚本
1 压缩图片 使用ImageMagick的convert命令进行压缩图片,一般只需要一个指定压缩质量的参数,比如: convert -quality 75 1.jpg 1_compress.jpg 可 ...
- (十一)Docker-DinD
1. Docker in Docker Step 1. Start a daemon instance $ docker run --privileged --name some-docker -d ...
- 获取全局描述符表GDT的内容
/stdfx.h文件 //Ring0环的程序 //测试环境VS2005 #ifndef _WIN32_WINNT // Allow use of features specific to Window ...
- hdu3329 二分+搜索
题意: 给你一个岛,然后岛的外侧开始涨水(内侧不涨只有外侧,也就是里面的0永远是0),问最少涨水多少才能把岛分成两个或者两个以上. 思路: 可以二分枚举水的高度(数据不大估计暴 ...
- IDAPython类库---idautils.py的源码
#--------------------------------------------------------------------- # IDAPython - Python plugin f ...
- UVA11464偶数矩阵
题意: 给你一个n*n的01矩阵,你的你的任务是吧尽量少的0变成1,使得每个元素的上下左右之和均为偶数(如果有的话),比如 0 0 0 0 1 0 1 0 0 ---&g ...
- Access+Mssql+Oracle数据库注入
Access数据库注入 前言:在常见的注入测试中,由于每个数据库内置架构和应用不同,导致数据库类型将决定注入的手法,Access数据库是小型数据库类型,普遍用于小型WEB应用,其中Access注入手法 ...
- MetInfo Password Reset Poisoning By Host Header Attack
if we know some user's email, the we will can reset the user's email by host header attack. The atta ...
- Day003 位运算
位运算 & 按位与,全1才为1,否则为0 | 按位或,全0才为0,否则为1 ^ 按位异或,相同则为0,不通则为1 ~按位取反 <<左移,相当于*2 >>右移,相当于/2 ...
- 第四部分 数据搜索之使用HBASE的API实现条件查询
因为数据清洗部分需要用到Mapreduce,所以先解决hbase的问题,可以用命令先在hbase存一下简单的数据进行查询,之后只要替换数据就可以实现了原本功能 在看该部分前,确保Hase API看了, ...