最近在忙一个项目,使用了STM32F030的单片机,定时器用系统定时器,每10us中断一次。在程序少的时候,没有发现死机情况,但是随着功能的丰富,经常出现死机问题,具体表现为while(1)循环无法执行,但是中断函数正常或者按键不起作用,程序直接跑分。这时我认为是死机,即程序跑分,但是有时中断正常,这就证明程序依然正常运行,可能是其它原因造成。
首先,我怀疑是I2C读写DSP出错,于是屏蔽掉DSP初始化,刚开始正常,多开机几次就又不正常了,所以排除写DSP。
接着,我怀疑读Flash出错,也发现仿真时,有时读Flash,就假死在那儿,于是就又把读Flash屏蔽掉,发现程序又正常了许多,但是多开机几次就又出现假死,所以又排除写Flash。但是仿真时,却说发现程序假死在一些初始化时的延时函数里。于是我仔细检查延时函数是否出错,发现没有错误,这就导致很奇怪了。
然后,我把优化等级调到-O3,发现出现了局部变量没有初始化就被使用和数组越界的情况(程序是拷贝别人的,没有仔细检查),以为这次可以解决了,在修改掉Bug后,程序假死改善了许多,但是很不幸,多级开关机后,发现程序又假死了,问题还不在这里,不过顺便解决了两个Bug。
最后,在同事的帮助下,开始检查系统定时器的中断函数,发现中断是每10us触发一次,并且在10us的中断函数里有调用了好几个函数,并且还有对IO口的操作,所以很有可能是由于中断过于频繁,系统被拖死了,导致不停的进入中断(这次中断还没有执行完成,下一次中断事件就产生了),导致while(1)循环根本没有时间执行,就出现了之前的假死现象。于是,在把中断时间改为1ms后,并把函数的操作放在了50ms的中断函数里处理,假死问题得以解决。
总结:
1、单片机不能把中断设置的太频繁,否则可能会消耗掉过多的MCU资源,导致while(1)执行的很慢,系统运行出现问题。
单片机会随着温度的升高,速度回稍微变慢,这也是为什么程序在中断太频繁时,有时运行正常,有时又不正常的原因。
中断函数里最好不要放函数调用,比较耗费时间,如果确实要用,就快进快出,并且不能在低于1ms的中断函数里调用函数。
中断函数里最好不要操作IO口,检测IO口的状态可以,但是最好不要写IO口,否则可能会消耗掉过多的MCU资源,导致系统假死。
局部变量一定要记得在定义时初始化,否则可能会出现不初始化就使用,导致系统异常;数组一定要仔细检查是否可能会出现越界,如果越界了怎么处理,要有保护措施。
2、从发现问题,到解决问题,用了将近两天的时间,不能不说这是一种浪费。首先,在发现问题后,没有先做深入的分析,而是不停的怀疑这里有问题,而没有用“证据”来证明其一定有问题,这不说一种好的解决问题的思路。其次,在没有串口打印时,没有第一时间把串口焊好,又是自己独自摸索怀疑,增加了调试的难度。最后,对单片机的执行速度没有大致的概念,以为8M晶振倍频到48M,单片机速度非常快了,但是没有考虑到多周期指令和C代码翻译成汇编再翻译成机器码后,会增加20%~30%的代码量,综合考虑,跑一次while(1)循环大概需要几毫秒的时间(中等规模代码,且没有任何延时)。
---------------------
作者:飞鱼湾
来源:CSDN
原文:https://blog.csdn.net/kelvinflying/article/details/46674339
版权声明:本文为博主原创文章,转载请附上博文链接!