本帖最后由 yonko 于 2019-9-13 19:16 编辑
单片机里面有很多中断资源,例如外部中断、定时器中断、串口中断等,这些中断资源应当用于处理相应的紧急事件,而不是顺序执行的常规事件,所以在编写中断子程序的时候应当十分注意。 具体的事务处理语句不应放在中断函数里面,中断子程序中的语句应当简洁明了,不应当有太多的语句。假如你在编写中断子程序的时候像在main函数中那样写一大串处理具体事务的指令的话,会在此中断中占用太多的时间,假如当有其他低优先级的中断信号来临的时候也可能导致中断丢失,发生程序的逻辑错误。所以,在中断子程序中的指令语句应当做到最短。 中断子程序中的语句不应当使用延时函数,不使用while、do-while、do-until等有等待延时功能的指令。在中断子程序中使用while、do-while、do-until等指令也会导致单片机在执行过程中在该位置延时或者等待太长的时间,当其他中断信号来临的时候同样也可能导致中断丢失。 那么应该怎么做呢? 在编写中断子程序的时候,应当巧用全局状态变量,在中断子程序中只改变状态变量值,在main函数中while(1)程序段内部判断该状态变量的值,根据状态变量的值再分别执行对应的事务处理语句。这就像你接到一个电话要你办某事,你也不能在一直接着电话把这件事做完吧,你需要把事情记下来,挂了电话再安排时间处理。 举个例子,一个串口触摸屏需要根据触屏中按键来执行对应的操作,需要使用到串口中断。假设触屏在触摸按键1时会发送数据A,触摸到按键2时会发送数据B,那么我们可以定义一个全局状态变量command: unsigned char command; 在串口中断子程序中,根据接收到的不同串口数据改变command的值: void 串口1中断函数() { switch (收到的串口数据) {case A: //假如收到按键1的动作,command赋值x1 {command=x1; break; } case B: //假如收到按键2的动作,command赋值x2 {command=x2; break; } … default: break; } } 在上面这个串口1的中断子程序中,switch是一个条件选择指令,当串口收到数据A,那么给command赋值x1, 当串口收到数据B,那么给command赋值x2。当然,上面的程序段只是一个说明的示意,不能直接复制编译到单片机中运行,在实际工程中需要根据不同单片机程序的编写规则进行开发。 接着在main函数中根据command的值执行不同的事务处理语句: main函数() { … while(1) { Switch(command) {case x1: //假如收到按键1的动作,执行事务处理1的程序 {事务处理1; break; } case x2: //假如收到按键2的动作,执行事务处理2的程序 {事务处理2; break; } default: break; } } } 按照这样的程序,单片机在接收到触屏发出的代表不同按键的串口数据时,在串口中断子程序中改变全局状态变量的值command,这个语句很少,执行时间也短。再到main函数中根据command的不同值分别执行非常耗时间的具体事务处理程序。这样的程序分配,将使单片机运行高效而且合理。 更多精彩,微信公众号:yonkotech 中秋快乐! 沙鸥 2019.9.13
|