1.1. 实验目的
图1 数码管显示按键次数
本实例中我们来了解并学习51单片机的外部中断的原理,通过按键触发外部中断,并在数码管上显示按键按下的次数,从而了解51单片机的外部中断的电路设计、编程实现。
1.2. 设计思路
本实例基于proteus的51单片机开发实例(8)--一位数码管显示的基础上,增加了按键触发中断部分,当按键被按下,触发外部中断,程序中识别到外部中断发生一次,就让数码管的显示数字加“1”;当外部中断触发次数超过9次后,再从0开始重新计数。本例中采用共阳极数码管。按键连接在单片机外部中断0引脚P3.2上。
1.3. 基础知识
本例涉及到51单片机的中断系统以及外部中断的使用方法。
1.3.1. 51单片机的中断系统
51单片机内部有一个中断系统,这个中断系统包括了这几种中断:外部中断、定时器/计数器中断、窗口中断等。在之前的学习中,我们已经学习了定时器中断。
51单片机的中断系统由控制寄存器和外部中断引脚组成。这些外部中断引脚包括:定时器/计数器中断引脚T0、T1、T2、T2EX;外部中断引脚INT0、INT1;串口中断引脚TXD、RXD。
51单片机执行一次中断需经过以下5步:中断寄存器初始化、中断源请求中断、CPU中断响应、执行中断服务程序、中断返回。
1、中断寄存器初始化
如果单片机在应用中要用到中断模块,必须先对相关寄存器进行初始化,比如要使用哪种类型的中断源,触发该中断源的信号要求等。
2、中断源请求
中断条件满足后,中断源发出中断请求信号,相应的中断标志位置位(标志位位于中断允许控制寄存器IE中)置1.需要说明的是,当中断发生时,对应的中断标志位是由单片机自动置1的。
3、中断响应
CPU查询(或检测)到中断允许控制器中某个中断标志位置1后,在满足中断响应条件下响应该中断。中断响应条件为:该中断已被允许,并且单片机系统中此时没有响应同级或更高级的中断;当前正处于所执行指令的最后一个机器周期,正在执行的指令不是中断返回指令或者是访问IE、IP的指令,否则必须在另外执行一条指令后才能响应。
CPU响应中断后,进行下列操作:保护断点地址,撤除该中断源的中断请求标志,关闭同级中断,将相应中断的入口地址送入PC。
4、执行中断服务程序
中断服务程序必须包括这些内容:保护现场,执行中断服务程序内容,完成相应操作;恢复现场。
5、中断返回
在中断服务程序最后,必须有一条中断返回指令RETI,当CPU执行RETI指令后,自动完成如下操作:恢复断点地址,开放同级中断,以允许同级中断源请求的中断。
我们看着这几个步骤会感觉好复杂啊,不过这些是用汇编语言编写中断函数时必须要做的,而我们现在使用C语言的话,只需要按照一定的格式设置中断寄存器,编写中断服务程序就行了,不必要关心断点保护,中断返回指令这些,因为C编译器已经帮我们做好了。
1.3.2. 51单片机中断系统的寄存器
51单片机中断系统中涉及中断控制的寄存器有三类:中断请求寄存器(包括两个寄存器,定时和外部中断控制寄存器TCON),串行控制寄存器SCON,中断允许控制寄存器IE,中断优先级寄存器IP。
前面学习定时器的时候,我们已经学过TCON寄存器了,下面来了解一下IE寄存器和IP寄存器。
中断允许控制寄存器IE
下图所示是IE寄存器中各位的含义。中断允许寄存器用来设定各个中断源的打开和关闭。
图2 IE寄存器
中断优先级寄存器IP
中断优先级寄存器IP用来设定各个中断源的优先级。
下图是IP寄存器各位含义。
图3 IP寄存器
1.3.3. 51单片机的中断服务子程序
51单片机C语言的中断服务子程序需要使用关键字interrupt来定义,interrupt后面的参数0~4表明了中断源,在实际使用中常使用using来定义在中断服务子程序中使用的寄存器组,其参数可以为0~3,分别对应通用寄存器组0~3.这样做的好处是可以减少压入堆栈的变量内容,从而简化中断服务程序的内容,以加快程序执行速度。中断服务程序的标准结构如下:
void 函数名 (void) interrupt中断标号 using 寄存器组编号
{
中断函数代码;
}
1.3.4. 51单片机的外部中断
51单片机的外部中断模块由中断系统和外部引脚组成,它使用端口P3的P3.2和P3.3(分别对应于INT0和INT1)引脚来作为外部信号的输入引脚。
51单片机的外部中断INT0和INT1有两种中断触发方式:下降沿触发和低电平触发。可以根据需要自由选择哪种触发方式。通过对定时器/计数器控制寄存器TCON的相关位进行设置。
IT1/IT0-外部中断触发方式控制位。置1-设置为下降沿触发方式,置0设置为低电平触发方式。
1.4. 电路设计
本实例的电路图如图1所示。51单片机的P1口接一个共阳极数码管,外部中断引脚P3.2连接一个按键,按键一端连到单片机P3.2引脚,另一端通过电阻连到VCC,这样当按键被按下时,会在外部中断引脚产生一个下降沿脉冲,以此触发外部中断事件。
1.5. 程序设计
在keil c51中编写如下程序代码,编译生成hex文件。
#include<AT89x52.h>
//共阳极数码管0~9数字
unsigned char code DSY_CODE[]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90
};
unsigned int Counter=0; //计数器
void EX_INT0() interrupt 0using 1 //外部中断0服务函数
{
Counter ;//当检测到外部中断0时,计数器加1
if(Counter>9)
{
Counter=0;//计数到9则返回
}
}
//外部中断0初始化函数
voidinitINT0(void)
{
IT0=1;//设置外部中断0为边沿触发方式
EX0=1; //使能外部中断0
EA=1; //使能中断事件
}
int main(void)
{
initINT0(); //初始化外部中断
Counter=0; //清零计数器
while(1)
{
P1=DSY_CODE[Counter];
}
}
1.6. 实例仿真
将hex文件装入proteus的单片机中,点击仿真按钮,开始仿真,可以看到,当按键按下,数码管显示的数字会随着按键按下次数而变化。
下面视频演示了执行结果。
1.7. 总结
通过本实例,我们了解和学习了51单片机的处理流程以及中断的程序设计方法。