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 串口接收大量数据导致死机的更多相关文章

  1. STM32串口接收不定长数据原理与源程序(转)

    今天说一下STM32单片机的接收不定长度字节数据的方法.由于STM32单片机带IDLE中断,所以利用这个中断,可以接收不定长字节的数据,由于STM32属于ARM单片机,所以这篇文章的方法也适合其他的A ...

  2. stm32串口接收完整的数据包

    参考了文章:<stm32串口中断接收方式详细比较> 文章地址:http://bbs.elecfans.com/jishu_357017_1_1.html 借鉴了第四种中断方式 串口的配置这 ...

  3. STM32串口usart发送数据

    主函数请直接关注41行到47行代码!! #include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h> #include ...

  4. stm32 串口接收一次后再也无法接受,接受都为0

    经检测为串口接受后进入别的程序,开辟了2048的临时数组,因为堆栈溢出.stm32总共堆栈为

  5. Win10 的微软输入法输入稍快竟然会导致死机

    一周前,新装机器一次,竟然死机两三次,多发生在敲字时,最近逐步排查发现的这个问题,查阅了一下网上方案,果断采用了第三方输入法,至今没再死机过. 不过第三方输入法也不安分,是不是推送点头条新闻过来,和驱 ...

  6. stm32串口接收发送数据处理

    /************************************************************* Function Name : Uart1_Send_Byte* Desc ...

  7. 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 ...

  8. STM32 ~ USART接收不定长数据

    IDLE中断什么时候发生? IDLE就是串口收到一帧数据后,发生的中断.什么是一帧数据呢?比如说给单片机一次发来1个字节,或者一次发来8个字节,这些一次发来的数据,就称为一帧数据,也可以叫做一包数据. ...

  9. 018_STM32程序移植之_串口接收中文

    (一)在平时数据传输中很少用到接收中文的情况,但是最近需要用到就花了半天时间来弄弄 (二)接收原理,从现在接收情况分析:一个中文占两个数据的空间,也就是两个十六进制可以转化成为一个中文 (三)示例情况 ...

随机推荐

  1. 会议更流畅,表情更生动!视频生成编码 VS 国际最新 VVC 标准

    阿里云视频云的标准与实现团队与香港城市大学联合开发了基于 AI 生成的人脸视频压缩体系,相比于 VVC 标准,两者质量相当时可以取得 40%-65% 的码率节省,旨在用最前沿的技术,普惠视频通话.视频 ...

  2. JDBC_09_Statement 和 PreparedStatement

    Statement 和 PreparedStatement * Statement数据库操作对象存在SQL注入问题,而PreparedStatement预编译数据库操作对象解决了SQL注入问题. * ...

  3. 听说你买的基金又“绿了”,手把手教你用 Python选出好基金

    打工人打工魂打工都是人上人,红基金绿基金绿了又绿你基金.今天教大家一招不再被(基金)绿. 01 开发环境 Windows10 Python3 Pycharm 一些必要的库 02 步骤 1. 获取基金排 ...

  4. 【python】Leetcode每日一题-前缀树(Trie)

    [python]Leetcode每日一题-前缀树(Trie) [题目描述] Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的 ...

  5. 栈(Stack) --- C# 自定义和微软官方的区别

    最近在学习算法基础,本篇文章作为一个记录,也算是一次实践和总结.(顺便也深入C#运行时学习一下) 目录 1. 栈是什么 2. Stack 自定义实现 3. Stack C#官方实现 4. 区别 5. ...

  6. 解决docker镜像无法删除的问题

    发现问题 来自守护进程的错误响应:冲突:无法删除050f26b6caca(必须强制) - 映像在多个存储库中被引用 Error response from daemon: conflict: unab ...

  7. ES常用查询语法

    1.query string search GET /index/type/_search?q=name:zhangsan&sort=age:desc 2.query DSL(Domain S ...

  8. Java筑基 - JNI到底是个啥

    在前面介绍Unsafe的文章中,简单的提到了java中的本地方法(Native Method),它可以通过JNI(Java Native Interface)调用其他语言中的函数来实现一些相对底层的功 ...

  9. DevEco Device Tool 2.1 Beta1在Hi3861开发板上可视化分析的体验

    DevEco Device Tool迎来了2.1 Beta1,新版本有很多亮点.在上次"DevEco Device Tool 2.1 Beta1 的Hi3861在Windows平台的编译体验 ...

  10. spring源码解析之属性编辑器propertyEditor

    异常信息造成此异常的原因bean配置文件调用代码特别说明:异常解决注册springt自带的属性编辑器 CustomDateEditor控制台输出属性编辑器是何时并如何被注册到spring容器中的?查看 ...