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程序移植之_串口接收中文
(一)在平时数据传输中很少用到接收中文的情况,但是最近需要用到就花了半天时间来弄弄 (二)接收原理,从现在接收情况分析:一个中文占两个数据的空间,也就是两个十六进制可以转化成为一个中文 (三)示例情况 ...
随机推荐
- PAT B1038 统计同成绩学生
读入N名同学的成绩,然后将获得某一给定分数的学生人数输出第一行给出不超过10^5的正整数,即学生总数:第二行给出N名学生的百分制的成绩,中间以空格分隔:第三行给出要查寻的分数个数K,随后是K个分数,中 ...
- Java刷题-list
一.打印两个有序链表的公共部分 补充一个关于节点的链表构造方法 Node next是设置指针域 import java.io.IOException;这个是报错信息 这是两个lO流 import ja ...
- 了解什么是redis的雪崩和穿透?redis崩溃之后会怎么样?系统该如何应对这种情况?如何处理redis的穿透?
缓存雪崩发生的现象 缓存雪崩的事前事中事后的解决方案 事前:redis高可用,主从+哨兵,redis cluster,避免全盘崩溃 事中:本地ehcache缓存 + hystrix限流&降级, ...
- Day13_64_线程的优先级
线程的调度 * 单核CPU在某一时刻只能执行一条指令,线程只有得到CPU的时间片,也就是使用权,才可以执行指令 * 在单核CPU的机器上线程不是并行运行的,而是频繁切换运行的,只有在多个CPU上线程才 ...
- 测试工具PerfDog的使用
使用操作:https://www.jianshu.com/p/cc04c710e643下载地址:https://perfdog.qq.com/
- 【Jwt】JSON Web Token
一.什么是JSON Web Token: 首先要明确的是JSON Web Token:是一个开放标准,这个标准定义了一种用于简洁,自包含的用于通信双方之间以JSON对象的形式安全传递信息的方法 而我们 ...
- hdu4665 DFS
题意: 给你一个字符串,问你能不能拆成两个相同的字符串,顺序不能改变. 思路: 咋一看数据有点大,搜索过不去,但想想优化的地方很多,而且每个字母最多出现四次,所以多几个剪纸应该 ...
- hdu1530 最大团简单题目
题意: 给你一个无向图,让你找到这个图里面的最大团是多少. 思路: 最大图案是NP问题,直接暴力搜索,如果当前的这个点可以加入当前最大团,那么就选择加入或者舍去,如果不能加入, ...
- Bugku-flag.php
flag.php 目录 flag.php 题目描述 解题过程 题目描述 点了login咋没反应 提示:hint 解题过程 fuzz 打开发现是个登录页面,点击login没反应,看了源码,action= ...
- 3-5年以上的Android原生开发如何深入进阶?高级工程师必须要掌握哪些?
前言 曾听过很多人说Android学习很简单,做个App就上手了,工作机会多,毕业后也比较容易找工作.这种观点可能是很多Android开发者最开始入行的原因之一. 在工作初期,工作主要是按照业务需求实 ...