当前位置:文档之家› 中断原理应用程序设计

中断原理应用程序设计

第六章中断原理应用程序设计6.1 中断系统的基本概念CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。

中断源引起CPU中断的根源,称为中断源。

中断源向CPU提出的中断请求。

CPU暂时中断原来的事务A,转去处理事件B。

对事件B处理完毕后,再回到原来被中断的地方(即断点),称为中断返回。

实现上述中断功能的部件称为中断系统(中断机构)。

MCS-51单片机提供了5个中断源,其中两个为外部中断请求源(P3.2)和(P3.3),两个片内定时器/计数器T0和T1的溢出请求中断源TF0(TCON的第5位)和TF1(TCON的第7位),1个片内串口发送或接收中断请求源TI(SCON的第1位)和RI(SCON的第0位)。

中断优先级同一优先级中的中断申请不止一个时,则有中断优先权排队问题。

同一优先级的中断优先权排队,由中断系统硬件确定的自然优先级形成,其排列如所示:表6-4 MCS-51单片机中断源的自然优先级及入口地址需要说明的是,为了便于用C语言编写单片机中断程序,C51编译器也支持51单片机的中断服务程序,而且用C语言编写中断服务程序,比用汇编语言方便的多。

C语言编写中断服务函数的格式如下:函数类型函数名(形式参数列表)[interrupt n] [using m]其中,interrupt后面的n是中断编号,取值范围0~4,;using中的m表示使用的工作寄存器组号(如不声明,则默认用第0组)。

例如,定时器T0的中断函数可用如下方法编写:void Timer(void) interrupt 1 using 0//定时器T0的中断服务函数,T0的中断编号为1,使用第0组工作寄存器{........//中断服务程序}6.2 中断系统的控制定时器/计数器控制寄存器TCONTCON的功能是接收外部中断源(、)和定时器(T0、T1)送来的中断请求信号。

字节地址为88H,可以进行位操作。

表5-5列出了TCON的格式。

8FH 8EH 8DH 8CH 8BH 8AH 89H 88H TF1 TR1 TF0 TR0 IT0 IT1 IE0 IT0表6-5 定时器/计数器控制寄存器TCON的格式•IT0和IT1分别为外部中断和的触发方式控制位,可以进行置位和复位。

•IE0和IE1分别为外部中断和的中断请求标志位。

•TF0和TF1分别为定时器/计数器T0和T1的中断请求标志。

•TR0和TR1分别为定时器/计数器T0和T1的启动/停止位。

中断允许控制寄存器IECPU对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制。

表6-6 中断允许控制寄存器IE的格式§ EX0(IE.0),外部中断0允许位;§ ET0(IE.1),定时/计数器T0中断允许位;§ EX1(IE.2),外部中断0允许位;§ ET1(IE.3),定时/计数器T1中断允许位;§ ES(IE.4),串行口中断允许位;§ EA (IE.7),CPU中断允许(总允许)位。

中断优先级控制寄存器IPMCS-51单片机有两个中断优先级,即可实现二级中断服务嵌套。

每个中断源的中断优先级都是由中断优先级寄存器IP中的相应位的状态来规定的。

表6-7 中断优先级控制寄存器IP的格式PX0(IP.0),外部中断0优先级设定位;PT0(IP.1),定时/计数器T0优先级设定位;PX1(IP.2),外部中断0优先级设定位;PT1(IP.3),定时/计数器T1优先级设定位;PS (IP.4),串行口优先级设定位;PT2 (IP.5) , 定时/计数器T2优先级设定位。

串行通信控制寄存器SCONSCON的功能主要是接收串行通信口送到的中断请求信号,具体格式见串口通信有关章节。

MCS-51单片机的中断优先级有三条原则:CPU同时接收到几个中断时,首先响应优先级别最高的中断请求。

正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。

正在进行的低优先级中断服务,能被高优先级中断请求所中断。

为了实现上述后两条原则,中断系统内部设有两个用户不能寻址的优先级状态触发器。

其中一个置1,表示正在响应高优先级的中断,它将阻断后来所有的中断请求;另一个置1,表示正在响应低优先级中断,它将阻断后来所有的低优先级中断请求。

一个中断源的中断请求被响应,需满足以下必要条件。

(1)CPU开中断,即IE寄存器中的中断总允许位EA=1。

(2)中断源发出中断请求,即该中断源对应的中断请求标志位为1。

(3)中断源的中断允许位=1,即该中断没有被屏蔽。

(4)无同级或更高级的中断正在被服务。

6.3中断嵌套中断嵌套的概念是指终端系统正在执行一个中断服务时,有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行,这个过程就是中断嵌套。

6.4中断程序设计例1:外部中断0的应用举例本实例中LED灯依次点亮,形成流水灯,同时伴有蜂鸣器发声。

当按住时,8位LED全部点亮,蜂鸣器停止发声。

当松开时,程序恢复到原来的状态。

图6—8 外部中断应用原理图#include<reg52.h> //包含头文件#include <intrins.h> //包含_crol_()函数所在头文件unsigned char temp,num; //声明临时变量unsigned int x,y,z;sbit beep=P2^3; //蜂鸣器位声明sbit duan=P1^6; //数码管段控制位声明sbit wei=P1^7; //数码管位控制位声明void delay(uint); //声明延时子函数void main(){EA=1; //开总中断EX0=1; //开外部中断duan=0; //关闭数码管的段选wei=0; //关闭数码管的位选temp=0xfe; //临时变量赋值while(1) //程序无限循环{for(num=0;num<8;num++) //8位LED依次点亮{P0=temp;beep=0; //蜂鸣器发声delay(100); //延时100mstemp=_crol_(temp,1); //循环左移函数P0=0xff;beep=1; //蜂鸣器关闭delay(100); //延时100ms}}}void delay(z){for(x=z;x>0;x--)for(y=110;y>0;y--);}void ex0() interrupt 0{P0=0x00; //点亮8位LEDbeep=1; //关闭蜂鸣器}程序解析:(1)本程序的一大特点是用_crol_()函数实现了8位LED的依次点亮。

简单明了,让同学们知道了在编写程序时调用一些函数会使程序的编写大为简化,但要注意在程序开头包含该函数所在的头文件。

(2)在编写中断服务子函数时,一定要注意函数的标号(即中断的优先级),该程序用的是,在所有中断中优先级最高,所以标号为0。

(3)在主函数的函数初始化中一定要依次开总中断,外部中断。

这样外部中断才能够被触发。

(4)注意延时子函数的编写,这个会经常用到。

例2:用定时器T0的中断控制8位LED闪烁本实例要求用定时器T0中断方式控制P0口8位LED以100ms周期性闪烁。

图6-9 定时器T0的中断控制8位LED原理图#include<reg52.h> // 包含51单片机寄存器定义的头文件void main(void){EA=1; //开总中断ET0=1; //定时器T0中断允许TMOD=0x01; //使用定时器T0的模式2TH0=(65536-46083)/256; //定时器T0的高8位赋初值TL0=(65536-46083)%256; //定时器T0的高8位赋初值TR0=1; //启动定时器T0while(1)//无限循环等待中断;}void Time0(void) interrupt 1 using 0 //“interrupt”声明函数为中断服务函数//其后的1为定时器T0的中断编号;0表示使用第0组工作寄存器{P0=~P0;TH0=(65536-50000)/256; //定时器T0的高8位重新赋初值TL0=(65536-50000)%256; //定时器T0的高8位重新赋初值}程序解析:(1)本程序首先要注意初始化定时器的程序编写方法。

具体见定时器有关章节。

(2)注意中断服务子函数中的中断标号和定时器初值重装问题。

例3:用定时器T0的方式控制播放《好人一生平安》本实例要求定时器T0的中断控制播放《好人一生平安》,T0工作于方式0。

硬件电路图如下。

图6-10 用定时器T0的方式控制播放《好人一生平安》电路图#include<reg52.h> //包含51单片机寄存器定义的头文件sbit sound=P2^3; //将sound位定义为P2.3unsigned int C; //储存定时器的定时常数//以下是C调低音的音频宏定义#define l_dao 262 //将“l_dao”宏定义为低音“1”的频率262Hz#define l_re 286 //将“l_re”宏定义为低音“2”的频率286Hz#define l_mi 311 //将“l_mi”宏定义为低音“3”的频率311Hz#define l_fa 349 //将“l_fa”宏定义为低音“4”的频率349Hz#define l_sao 392 //将“l_sao”宏定义为低音“5”的频率392Hz#define l_la 440 //将“l_a”宏定义为低音“6”的频率440Hz#define l_xi 494 //将“l_xi”宏定义为低音“7”的频率494Hz//以下是C调中音的音频宏定义#define dao 523 //将“dao”宏定义为中音“1”的频率523Hz#define re 587 //将“re”宏定义为中音“2”的频率587Hz#define mi 659 //将“mi”宏定义为中音“3”的频率659Hz#define fa 698 //将“fa”宏定义为中音“4”的频率698Hz#define sao 784 //将“sao”宏定义为中音“5”的频率784Hz#define la 880 //将“la”宏定义为中音“6”的频率880Hz#define xi 987 //将“xi”宏定义为中音“7”的频率523H//以下是C调高音的音频宏定义#define h_dao 1046 //将“h_dao”宏定义为高音“1”的频率1046Hz#define h_re 1174 //将“h_re”宏定义为高音“2”的频率1174Hz#define h_mi 1318 //将“h_mi”宏定义为高音“3”的频率1318Hz#define h_fa 1396 //将“h_fa”宏定义为高音“4”的频率1396Hz#define h_sao 1567 //将“h_sao”宏定义为高音“5”的频率1567Hz#define h_la 1760 //将“h_la”宏定义为高音“6”的频率1760Hz#define h_xi 1975 //将“h_xi”宏定义为高音“7”的频率1975Hzvoid delay(){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++);}void main(void){unsigned char i,j;//以下是《渴望》片头曲的一段简谱unsigned int code f[]={re,mi,re,dao,l_la,dao,l_la, //每行对应一小节音符l_sao,l_mi,l_sao,l_la,dao,l_la,dao,sao,la,mi,sao,re,mi,re,mi,sao,mi,l_sao,l_mi,l_sao,l_la,dao,l_la,l_la,dao,l_la,l_sao,l_re,l_mi,l_sao,re,re,sao,la,sao,fa,mi,sao,mi,la,sao,mi,re,mi,l_la,dao,re,mi,re,mi,sao,mi,l_sao,l_mi,l_sao,l_la,dao,l_la,dao,re,l_la,dao,re,mi,re,l_la,dao,re,l_la,dao,re,mi,re,0xff}; //以0xff作为音符的结束标志//以下是简谱中每个音符的节拍//"4"对应4个延时单位,"2"对应2个延时单位,"1"对应1个延时单位unsigned char code JP[ ]={4,1,1,4,1,1,2,2,2,2,2,8,4,2,3,1,2,2,10,4,2,2,4,4,2,2,2,2,4,2,2,2,2,2,2,2,10,4,4,4,2,2,4,2,4,4,4,2,2,2,2,2,2,10,4,2,2,4,4,2,2,2,2,6,4,2,2,4,1,1,4,10,4,2,2,4,1,1,4,10};EA=1; //开总中断ET0=1; //定时器T0中断允许TMOD=0x00; // 使用定时器T0的模式1(13位计数器)while(1) //无限循环{i=0; //从第1个音符f[0]开始播放while(f[i]!=0xff) //只要没有读到结束标志就继续播放{C=460830/f[i];TH0=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法TL0=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法TR0=1; //启动定时器T0for(j=0;j<JP[i];j++) //控制节拍数delay(); //延时1个节拍单位TR0=0; //关闭定时器T0i++; //播放下一个音符}}}void Time0(void ) interrupt 1 using 1{sound=!sound; //将P2.3引脚输出电平取反,形成方波TH0=(8192-C)/32; //可证明这是13位计数器TH0高8位的赋初值方法TL0=(8192-C)%32; //可证明这是13位计数器TL0低5位的赋初值方法}程序解析:(1)首先,给出本实例的目的是让大家能够更好的理解定时器中断的用途,大家没有必要对程序中的每一条语句都了解的特别清楚,而主要抓住程序最后的定时器T0的中断服务函数即可。

相关主题