51单片机的中断系统 && 外部中断
中断系统是为使CPU具有外界紧急事件的
实时处理
能力而设置的。
一、中断概念
对于单片机来说,中断是指CPU在处理某一事件A时,发生另外一事件B,请求CPU迅速取处理(中断发生);CPU暂时停止当前的工作(中断响应),转去处理事件B(中断服务);待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一完整过程被称为中断。
二、中断结构及相关的寄存器
51单片机开发板(主控芯片:STC89C52RC
)提供8个中断请求源,分别是:
◼ 外部中断0(INT0)
◼ 外部中断1(INT1)
◼ 外部中断2(INT2)
◼ 外部中断3(INT3)
◼ 定时器0中断
◼ 定时器1中断
◼ 定时器2中断
◼ 串口(UART)中断
一般的51单片机都会拥有至少5个中断请求源,中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等
2-1 51单片机中断引脚以及中断控制
-
INT0
对应的是P3^2
口的附加功能,可由IT0(TCON^0)
选择其为低电平有效,还是下降沿有效。当CPU检测到
P3^2
引脚上出现有效的中断信号时,中断标志位IE0(TCON^1)
置1,向CPU申请中断。 -
INT1
对应的是P3^3
口的附加功能,可由IT1(TCON^2)
选择其为低电平有效,还是下降沿有效。当CPU检测到
P3^3
引脚上出现有效的中断信号时,中断标志位IE1(TCON^3)
置1,向CPU申请中断。 -
T0
对应的是P3^4
口的附加功能,TF0(TCON^5)
是片内定时器/计数器T0
溢出中断请求标志。当定时/计数器T0发生溢出时,
TF0
置为1,并向CPU申请中断。 -
T1
对应的是P3^5
口的附加功能,TF1(TCON^7)
是片内定时器/计数器T1
溢出中断请求标志。当定时/计数器T1发生溢出时,
TF1
置为1,并向CPU申请中断。 -
RXD
和TXD
对应的是P3^0
和P3^1
口的附加功能,RI(SCON^0)
或TI(SCON^1)
是串行口中断请求标志位。当串行口接收完一帧串行数据时,RI置为1,向CPU申请中断;或当串行口发送完一帧串行数据时,TI置为1,向CPU申请中断。
2-2 中断相关的寄存器
❤ 中断允许控制寄存器IE
CPU对终端系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE控制的。
EX0(IE^0):外部中断0允许位
ET0(IE^1):定时/计数器T0中断允许位
EX1(IE^2):外部中断1允许位
ET1(IE^3):定时/计数器T1中断允许位
ES(IE^4):串行口中断允许位
EA(IE^7):CPU中断允许位(即总允许位)
❤ 中断请求标志寄存器TCON
-
IT0(TCON^0),外部中断0触发方式控制位
当IT0=0时,为电平触发方式
当IT0=1时,为边沿触发方式(下降沿有效)
-
IE0(TCON^1),外部中断0中断请求标志位
-
IT1(TCON^2),外部中断1触发方式控制位
当IT0=0时,为电平触发方式
当IT0=1时,为边沿触发方式(下降沿有效)
-
IE1(TCON^3),外部中断1中断请求标志位
-
TF0(TCON^5),定时/计数器T0溢出中断请求标志位
-
TF1(TCON^7),定时/计数器T1溢出中断请求标志位
❤ 中断优先级(多个中断源需要)
中断号(中断函数需要)
❤ 中断响应条件
1.中断源有中断请求(触发标志位)
2.此中断源的中断允许位为1
3.CPU开中断(即总允许位EA为1)
以上三个条件同时满足时,CPU才有可能响应中断。
❤ 中断服务函数
int function_name(形参列表) interrupt 中断号
{
//函数实现的功能语句
return 0;
}
三、外部中断实验
❤ 实验目的:使用外部中断0控制编号:D1的LED灯的亮灭
❤ 思路:
外部中断0的引脚:P3^2
,然后P3^2
也连接到独立按键模块的第三个按键K3
因为独立按键一端是共地的,当按键按下后,对应单片机的I/O口电平被拉低,而默认单片机的I/O口是高电平,这样就有一个下降沿过程,因此通常使用外部中断都是设置下降沿触发,即IT0=1或IT1=1
❤ 实验代码:
#include<REG52.h>
//定义LED模块编号D1的LED灯(即第一个LED灯)
sbit LED1=P2^0;
//定义独立按键模块编号K3的按键(即第三个按键)
//独立按键K3连接的IO口也是外部中断0
sbit K3=P3^2;
//延时函数,单位:10us
int delay_10us(unsigned int i)
{
while(i--);
return 0;
}
//外部中断0函数
void light_led_of_int0() interrupt 0
{
delay_10us(1000);
if(K3 == 0)
LED1=~LED1;
}
// 外部中断INT0初始化
void int0_init()
{
IT0=1; //外部中断0采用边沿触发,下降沿有效
EX0=1; //开启外部中断0
EA=1; //开启总中断
}
int main(void)
{
int0_init();
while(1)
{
}
return 0;
}
❤ 实验结果
按下开发板上独立按键模块K3按键
![](/i/l/?n=22&i=blog/2823710/202211/2823710-20221112104332361-30382686.png)
再次按下K3按键
![](/i/l/?n=22&i=blog/2823710/202211/2823710-20221112104412692-1634915234.png)