单片机的中断使用一般遵循如下步骤:
1、按中断号(C语言)或者中断入口地址(汇编)别写中断服务程序。如果是编写汇编中断服务程序,如果中断程序中用到了寄存器或者有可能影响程序状态字的指令,应注意现场保护(C语言会自动保护)。对不能硬件清除中断标志的中断响应,退出中断前要软件清除中断标志。对复合中断(如串口收发中断)服务程序,要判断中断具体来源执行对应程序。
2、使能相应的中断。
3、开启总中断。
定时器一旦启动,除非你写命令让它停下,否则是一直在运行的。定时器的计数器一旦溢出,就会发生中断,程序就开始执行中断函数中的程序。而计数器依旧开始累加,直到下一次溢出,不断往复,永无休止。注意的是,当你的中断服务程序耗费时间过长的时候,意思是,CPU执行你的中断服务程序的时间大于中断计时时间的话。那么,CPU将在这段中断服务程序还没有还没有执行完就会收到下一次中断请求,此时CPU将不再执行之后的中断服务程序,转而重新从第一条中断服务程序开始执行。
我来帮你写一个,程序太简单了,下面是我帮你写的程序我测试过能满足你的要求,希望我的回答对你有帮助! /* * * * * * * * * * * * * * * * **/ #include "REG52.H" /* * */ sbit LED_A = P1^0; sbit LED_B = P1^1; sbit LED_C = P1^2; unsigned char TIME_BASE; unsigned char MACT_ENDB; unsigned char Rece_Errp; /* * 定时器初始化 */ void SystemInit(void) { TMOD = 0x01; TH0 = (65536 - 45872) / 256; // 定时50ms //晶振:11.0592MHZ TL0 = (65536 - 45872) % 256; ET0 = 1; TR0 = 1; EA = 1; } int main(void) { SystemInit(); while(1) { /* 程序一开始上电Rece_Errp = 0 定时器5秒加一次 */ if(Rece_Errp == 0) { LED_A = 0; // A亮5秒 LED_B = 1; // B是灭 LED_C = 1; // C是灭 } /* 判断是否5秒时间到 */ else if(Rece_Errp ==1) { LED_A = 1; // A是灭 LED_B = 0; // B亮5秒 LED_C = 1; // C是灭 } else if(Rece_Errp == 2) { LED_A = 1; // A是灭 LED_B = 1; // B是灭 LED_C = 0; // C亮5秒 } else { LED_A = 1; // A是灭 LED_B = 1; // B是灭 LED_C = 1; // C是灭 while(1); // 程序运行到这里停止 } } } void Timer0_IRQ(void) interrupt 1 { TH0 = (655365 - 45872) / 256; TL0 = (655365 - 45872) % 256; /* 进入中断50ms +1次 */ TIME_BASE++; if(TIME_BASE == 20) // 20ms * 50ms = 刚好等于1000ms 也就是1秒 { TIME_BASE = 0; MACT_ENDB++; // 一秒加一次 if(MACT_ENDB == 5) // 等于刚好5秒时间到 { MACT_ENDB = 0; Rece_Errp++; // 用来切换LED A、B、C5秒灭 } } }
晕,你不会这样设计你的程序吧?你不会在中断中停留1S的时间吧?
教你个方法,你的中断应该是设置的20ms吧?即T0的溢出时间设置为20ms,在T0中断程序里设一个计数器,从1自增到50后归0,也就是用设计标记的方法来计时1S,到了1S就执行你要的内容就行了.
中断程序不用你设置退出,执行完了它自己退出的.
只要定时中断里没有死循环这样的程序,在完全执行好中断程序后就可以使用RETI退出(如果是C语言,这条语句也省掉了)。
但不能退回到主程序开始时,而是退回到你中断前瞬间在执行的程序附近。
如果你要进行初始化什么的,就把初始化信息加在中断服务程序中。在中断时候,把定时初值之类的信息直接重装了。
单片机定时中断触发与退出的介绍到此就结束了,感谢您耐心阅读,谢谢。
本文标签:单片机定时中断触发与退出