中断——是指不得不中断手上正在做的事情去处理一些突发事件,处理完这个突发事情后再接着做刚才被打断的事,这个过程不能太长,讲究一个快进快出。
比如你正在炒菜,结果电话铃响了,这时候你不得不中断炒菜的动作,洗手去接电话,但是锅里的菜又不能停,离开的时间长了菜容易炒糊,所以必须快速处理电话里的事情,然后接着去炒菜。
所谓的中断嵌套是在处理中断时又来一个中断,接上面的例子,你在接电话时快递员突然给你送来重要文件需要你签收,这时候你可能不得不先把电话放一边,好腾出手来签收快递。
这个连续的中断过程可能会造成你的很多失误,比如忽略了电话的内容,耽误了炒菜的进度导致菜炒焦了等等,在程序中则会造成一些不可预知的错误。
中断的嵌套不常发生,我工作这么多年也没遇到过,但在程序中却很容易造成中断嵌套,最近我同事就遇到这样一个问题。
单片机程序中最常用的中断有两个,一个是串口中断,一个是定时器中断。
串口中断主要用于接收其它设备发来的命令,接着根据不同的命令类型做不同的处理;定时器中断更简单,就是单纯的计数或定时。
如果遵循快进快出原则,按理这两个中断不太可能会发生中断,但事情却真真正正的发生了。
我看了同事写的代码,发现他在这两个中断中都没遵守快进快出原则,而是在中断中做了一些数据处理。
首先是串口中断,他在接收完一串完整的数据后没有退出中断,而是直接做了数据分析,判断接收数据的类型,并根据不同的数据类型做进一步处理。
这里调用了一些IIC的读写、数据的滤波、AD的读写等函数,这些函数中不乏一些有较短的延时需求。
在定时器中断中,同样做了一些数据处理,比如定时时间到了后驱动一些芯片工作,手动输出PWM波形等。
关键是这两个中断的频率很高,定时器中断每隔50微秒进一次,串口中断每隔一秒进一次,如此高的进中断频率很容易造成中断嵌套,不是串口中断中发生定时器中断,就是定时器中断中发生串口中断,接着就是程序跑飞。
我看过同事代码后建议他在中断处理函数中遵循快进快出原则,串口中断只负责接收数据,一旦数据接收完成,直接置位相关标志位,接着清中断标志位,退出中断。
定时器中断也一样,计时任务完成,置位相关标志位后直接退出中断,至于其它的数据分析及后续的处理都放在主循环中完成,现在的单片机主频都很高,运行速度都很快,只要程序编写合理,不至于耽误事。
同事说他以前的程序都是这样写,也没出现过问题,我猜应该是他运气好,以前没有这么高频率的进出中断,但是这样写肯定会有中断嵌套的可能,这不就遇到了吗!