一、外部中断介绍
在前面文章中,我们对中断的概念进行了介绍。STC89C516单片机内部有6个中断源,它们分别为:
INT0—外部中断0,由P32端口线引入,低电平或下降沿触发中断。
INT1—外部中断1,由P33端口线引入,低电平或下降沿触发中断。
T0—定时器/计数器0中断,由T0计数器计满回零引起。
T1—定时器/计数器1中断,由T1计数器计满回零引起。
T2—定时器/计数器2中断,由T2计数器计满回零引起。
TI/RI—串行口中断,串行端口完成一帧字符发送/接收后引起。
在定时器实验中,我们已经对T0、T1、T2中断进行了学习,本文我们对INT0和INT1这两个外部中断进行学习。与这两个外部中断有关的寄存器是中断允许寄存器IE和定时器/计数器控制寄存器TCON。
IE用来设定各个中断源的打开和关闭,IE在特殊功能寄存器中字节地址为A8H,位地址(由低位到高位)分别为A8H~AFH,该寄存器可进行位寻址,即可以对这个寄存器的每一位进行操作。单片机复位时IE寄存器全部被清0,这个寄存器的各位如下表所示。
中断允许寄存器IE
位序号 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
位符号 |
EA |
-- |
ET2 |
ES |
ET1 |
EX1 |
ET0 |
EX0 |
位地址 |
AFH |
-- |
ADH |
ACH |
ABH |
AAH |
A9H |
A8H |
EA—全局中断允许位。
EA=1,打开全局中断控制,在此条件下,由各个中断控制位确定相应中断的打开和关闭。
EA=0,关闭全部中断。
--—无效位。
ET2—定时器/计数器2中断允许位。
ET2=1,打开T2中断。
ET2=0,关闭T2中断。
ES—串行口中断允许位。
ES=1,打开串行口中断。
ES=0,关闭串行口中断。
ET1—定时器/计数器1中断允许位。
ET1=1,打开T1中断。
ET1=0,关闭T1中断。
EX1—外部中断1中断允许位。
EX1=1,打开外部中断1中断。
EX1=0,关闭外部中断1中断。
ET0—定时器/计数器0中断允许位。
ET0=1,打开T0中断。
ET0=0,关闭T0中断。
EX0—外部中断0中断允许位。
EX0=1,打开外部中断0中断。
EX0=0,关闭外部中断0中断。
TCON在特殊功能寄存器中,字节地址为88H,位地址(由低位到高位)分别为88H~8FH,该寄存器可以进行位寻址。TCON寄存器用来控制定时器的启、停,标志定时器的溢出和中断情况。单片机复位时TCON全部清0。这个寄存器的给位定义如下表所示。其中TF1、TR1、TF0和TR0位用于定时器/计数器的设置。IE1、IT1、IE0和IT0位用于外部中断的设置。
定时器/计数器控制寄存器TCON
位序号 |
D7 |
D6 |
D5 |
D4 |
D3 |
D2 |
D1 |
D0 |
位符号 |
TF1 |
TR1 |
TF0 |
TR0 |
IE1 |
IT1 |
IE0 |
IT0 |
位地址 |
8FH |
8EH |
8DH |
8CH |
8BH |
8AH |
89H |
88H |
TF1—定时器1溢出标志位。
当定时器1计满溢出时,由硬件使TF1置1,并且申请中断。进入中断服务程序后,由硬件自动清0。需要注意的是,如果使用定时器的中断,那么该位完全不用人为去操作,但是如果使用软件查询的方式的话,当查询到该位置1后,就必须用软件清0。
TR1—定时器1运行控制位。
由软件清0关闭定时器1。当GATE=1时,INT1为高电平且TR1置1启动定时器1;当GATE=0时,TR1置1启动定时器1。
TF0—定时器0溢出标志位。
该位与TF1功能和操作方法相同。
TR0—定时器0运行控制位。
该位与TR1功能和操作方法相同。
IE1—外部中断1请求标志。
当IT1=0时,外部中断INT1为电平触发方式,每个机器周期采用INT1引脚,若INT1引脚为低电平,则置1,否则IE1清0。
当IT1=1时,外部中断INT1为边沿触发方式,当采集到INT1由高电平向低电平的跳变时则将IE1置1。IE1=1表示外部中断1正向CPU申请中断。当CPU响应中断转向中断服务程序时,该位由硬件清0。
IT1—外部中断1触发方式选择位。
IT1=0,电平触发方式,引脚INT1上低电平触发中断。
IT0=1,边沿触发方式,引脚INT1上由高电平向低电平的跳变触发中断。
IE0—外部中断0请求标志。
这一位的用法与IE1相同。
IT0—外部中断0触发方式选择位。
这一位的用法与IT1相同。
二、实验例程
实验1:电平触发外部中断
在这个实验中,我们把按键F1与外部中断的0通道连接在一起。用F1作为外部触发的信号源。这里例程的代码如下所示。
main()
{
LED=0x55;
EA=1; //打开全局中断
EX0=1; //打开外部中断0
IT0=0; //外部中断采用电平触发
for(;;);
}
void int0_ISR(void) interrupt 0 using 1
{
LED=~LED; //按位取反
}
在主函数中,首先给LED赋初值,然后开启外部中断,设置外部中断为电平触发方式,之后for循环使程序处于等待状态。在外部中断的处理函数中,将LED的每一位取反。
将程序烧写之后可以看到实验现象,发光管中有4个点亮,按下F1按键则发光管全部点亮,松开F1按键,则4个发光管点亮。
INT0和INT1分别与P32和P33口复用,将按键接到P32口上后,按下按键之后,INT0口输入低电平。则触发中断。在中断中,对LED按位取反。由于采用电平触发中断,因此只要按键按下,就会一直进入中断,对LED一直取反。因此,看到的现象是8个发光管都发光。
实验2:边沿触发外部中断
这个实验与上一个实验不同,这个实验我们采用边沿触发的方式采集外部中断,并对LED进行控制,实验代码如下所示。
main()
{
LED=0;
EA=1; //打开全局中断
EX0=1; //打开外部中断0
IT0=1; //外部中断采用边沿触发
for(;;);
}
void int0_ISR(void) interrupt 0 using 1
{
delay1ms(10); //去抖
if(INT0==0)
LED=!LED; //改变灯的状态
}
这个实验用外部中断0的下降沿来触发中断。在中断中进行去抖后,将LED1的状态改变。将按键接到P32口上后,按下按键之后,则LED1状态改变。