目录
一、AT89S51中断技术概述
AT89S51是一款8位单片机,具有丰富的中断技术功能。中断技术是一种能够提高系统灵活性和响应速度的关键技术,它允许单片机在执行程序的过程中,根据外部或内部事件的发生而中断当前的程序执行,去执行相应的中断服务程序。
二、AT89S51中断系统结构
![](https://i-blog.csdnimg.cn/direct/fe9f615430d1433bb75f73b070ab8585.png)
AT89S51的中断系统结构图
2.1 中断请求源
AT89S51是一种8位微控制器,具有5个中断请求源。这些中断请求源是:外部中断0(INT0)、外部中断1(INT1)、定时器0中断请求(TF0)、定时器1中断请求(TF1)和串行口中断请求(RI/TI)。
外部中断0和外部中断1是外部引脚的中断请求源,可以通过设置和清除相关的寄存器来使能和禁用这些中断。
定时器0和定时器1中断请求是由定时器/计数器模块产生的。当定时器/计数器溢出时,会触发相应的中断请求。
串行口中断请求是由串行通信口接收和发送数据时产生的。当接收到数据时,会触发接收中断请求(RI);当发送完数据后,会触发发送中断请求(TI)。
2.2 中断请求标志寄存器
5个中断请求源的中断请求标志分别由特殊功能寄存器TCON和SCON的相应位锁存。
2.2.1 TCON 寄存器
TCON寄存器(Timer/Counter Control Register)是8051系列微控制器中的一个特殊功能寄存器,用于控制定时器、计数器以及外部中断的相关设置。
TCON寄存器是一个8位寄存器,其位的含义如下:
- TF1 (定时器1溢出标志位):当定时器1计数溢出时,TF1位会被设置为1。在中断服务程序中,可以通过清除TF1位来复位溢出标志。
- TR1 (定时器1启动/停止控制位):当TR1位为1时,定时器1启动;当TR1位为0时,定时器1停止。
- TF0 (定时器0溢出标志位):当定时器0计数溢出时,TF0位会被设置为1。在中断服务程序中,可以通过清除TF0位来复位溢出标志。
- TR0 (定时器0启动/停止控制位):当TR0位为1时,定时器0启动;当TR0位为0时,定时器0停止。
- IE1 (外部中断1边沿触发标志位):当外部中断1检测到边沿触发时,IE1位会被设置为1。
- IT1 (外部中断1触发类型控制位):用于设置外部中断1的触发类型。当IT1位为0时,外部中断1为低电平触发;当IT1位为1时,外部中断1为下降沿触发。
- IE0 (外部中断0边沿触发标志位):当外部中断0检测到边沿触发时,IE0位会被设置为1。
- IT0 (外部中断0触发类型控制位):用于设置外部中断0的触发类型。当IT0位为0时,外部中断0为低电平触发;当IT0位为1时,外部中断0为下降沿触发。
2.2.2 SCON 寄存器
SCON(Serial Control Register)寄存器是8051系列微控制器中的一个特殊功能寄存器,用于控制串行通信的相关设置。
SCON寄存器是一个8位寄存器,其位的含义如下:
- SM0/FE(串行通信模式选择/帧错误标志位):当SM0为0时,串行通信使用8位数据位;当SM0为1时,串行通信使用9位数据位;当FE为1时,表示接收到的数据帧中有错误。
- SM1(串行通信模式选择):当SM1为0时,串行通信使用异步模式(波特率可变);当SM1为1时,串行通信使用同步模式(波特率固定)。
- SM2(多机通信模式选择):当SM2为0时,串行通信使用单机模式(无多机通信);当SM2为1时,串行通信使用多机模式。
- REN(串行通信接收使能):当REN为1时,允许串行接收器接收数据;当REN为0时,禁止串行接收器接收数据。
- TB8(发送数据的第9位):当SM0为1时,TB8表示发送数据的最高位。
- RB8(接收数据的第9位):当SM0为1时,RB8表示接收数据的最高位。
- TI(发送中断标志):当发送数据完成时,TI将被置位为1。
- RI(接收中断标志):当接收到数据时,RI将被置位为1。
注意:
- TI和RI均需要手动清除。
三、中断允许与中断优先级的控制
3.1 中断允许寄存器 IE
IE(Interrupt Enable)寄存器是8051系列微控制器中的一个特殊功能寄存器,用于控制中断的相关设置。
IE寄存器是一个8位寄存器,其位的含义如下:
- EA(全局中断使能):当EA为1时,允许所有中断;当EA为0时,禁止所有中断。
- ET2(定时器2中断使能):当ET2为1时,允许定时器2中断;当ET2为0时,禁止定时器2中断。
- ES(串行口中断使能):当ES为1时,允许串行口中断;当ES为0时,禁止串行口中断。
- ET1(定时器1中断使能):当ET1为1时,允许定时器1中断;当ET1为0时,禁止定时器1中断。
- EX1(外部中断1使能):当EX1为1时,允许外部中断1;当EX1为0时,禁止外部中断1。
- ET0(定时器0中断使能):当ET0为1时,允许定时器0中断;当ET0为0时,禁止定时器0中断。
- EX0(外部中断0使能):当EX0为1时,允许外部中断0;当EX0为0时,禁止外部中断0。
3.2 中断优先级寄存器 IP
在AT89S51微控制器中,中断优先级关系的两条基本规则如下:
-
低优先级可被高优先级中断,高优先级不能被低优先级中断。
-
任何一种中断(不管是高级还是低级)一旦得到响应,不会再被它的同级中断源所中断。如果某一中断源被设置为高优先级中断,在执行该中断源的中断服务程序时,则不能被任何其他中断源的中断请求所中断。
中断优先级寄存器(Interrupt Priority Register,IP)是一个8位寄存器,用于设置和存储中断的优先级。IP的各位的含义如下:
- PX0(外部中断0中断优先级控制位):1——高优先级;0——低优先级。
- PX1(外部中断1中断优先级控制位):1——高优先级;0——低优先级。
- PS(串行口中断优先级控制位):1——高优先级;0——低优先级。
- PT1(定时器T1中断优先级控制位):1——高优先级;0——低优先级。
- PT0(定时器T0中断优先级控制位):1——高优先级;0——低优先级。
在同时收到几个同一优先级的中断请求时,哪一个中断请求能优先得到响应,取决于内部的查询顺序。这相当于在同一个优先级内还同时存在另一个辅助优先级结构,其查询顺序如下表所示。
四、响应中断请求的条件
-
总中断允许开关接通,即IE寄存器中的中断总允许位EA=1。
-
该中断源发出中断请求,即该中断源对应的中断请求标志为“1”。
-
该中断源的中断允许位=1,即该中断被允许。
-
无同级或更高级中断正在被服务。
满足以上条件后,中断控制器会将中断请求转发给CPU,CPU暂停当前任务的执行,保存现场信息后执行中断服务程序来处理中断请求。
五、外部中断的触发方式选择
外部中断的触发方式选择包括电平触发和负跳变触发。
电平触发:在电平触发方式下,中断源的中断请求只要保持在特定电平上,中断就会被触发。通常,电平触发可以分为高电平触发和低电平触发两种方式。
- 高电平触发:当中断源的信号电平保持高电平时,中断触发。
- 低电平触发:当中断源的信号电平保持低电平时,中断触发。
负跳变触发:负跳变触发方式也称为边沿触发,是在中断源的信号发生负跳变(从高电平到低电平)时才触发中断。负跳变触发方式具有以下两种方式:
- 负跳变上升沿触发(Falling-Edge Triggered):当中断源的信号从高电平变为低电平时,中断触发。
- 负跳变下降沿触发(Rising-Edge Triggered):当中断源的信号从低电平变为高电平时,中断触发。
六、中断函数
在C51中,中断函数是用来处理中断事件的特殊函数。当发生中断时,CPU会暂时中止当前的程序执行,转而执行中断函数。中断函数完成后,CPU会返回到原来的位置继续执行。
C51中,中断函数的定义方式如下:
void interrupt_function() interrupt [interrupt_number]
{
// 中断处理逻辑
// ...
}
其中,interrupt_function
是中断函数的名称,interrupt_number
是中断的编号。
常见的中断编号包括:
例如,下面的代码定义了一个外部中断0的中断函数:
void ext_interrupt0() interrupt 0
{
// 外部中断0处理逻辑
// ...
}
在使用中断函数前,需要进行中断的初始化设置。例如,开启中断、设置中断优先级等。
下面是一个简单的示例,展示了如何使用定时器0中断函数进行定时操作:
#include <reg51.h>
void timer0_interrupt() interrupt 1
{
// 定时器0中断处理逻辑
// ...
}
void main()
{
// 初始化定时器0
TMOD = 0x01; // 设置定时器0为模式1
TH0 = 0xFC; // 定时器0高字节初值
TL0 = 0x66; // 定时器0低字节初值
ET0 = 1; // 允许定时器0中断
EA = 1; // 允许总中断
// 启动定时器0
TR0 = 1;
while (1)
{
// 主循环逻辑
// ...
}
}
在上面的代码中,首先定义了一个定时器0中断函数timer0_interrupt
。然后,在main
函数中进行了定时器的初始化设置,包括设置定时器模式、初值等。最后,通过ET0 = 1
开启了定时器0中断,并通过EA = 1
开启了总中断。在主循环中处理其他逻辑。
当定时器0中断发生时,C51会自动跳转到timer0_interrupt
函数执行中断处理逻辑,完成后返回到原来的执行位置继续执行主循环。
6.1 中断系统应用举例
在AT89S51单片机的P1口上接有8只LED。在外部中断0输入引脚INTO (P3.2)接有一只按钮开关k1。要求将外部中断0设置为电平触发。程序启动时,P1口上的8只LED全亮。每按一次按钮开关kl,使引脚INTO接地,产生一个低电平触发的外中断请求,在中断服务程序中,让低4位的LED与高4位的LED交替闪烁5次。然后从中断返回,控制8只LED再次全亮,其原理电路如下图所示。
利用中断控制8只LED交替闪烁一次的电路示意图
程序代码:
#include <reg51.h>
#define uchar unsigned char
void Delay (unsigned int i){ //延时函数Delay(),i为形式参数,不能赋初值
unsigned int j;
for(;i > 0;i--)
for (j=0;j<333;j++) //晶体振荡器为12MHz,j的选择与晶体振荡器频率有关
{;} //空函数
}
void main( ){
EA=1; //总中断允许
EX0=1; //允许外部中断0中断
IT0=1; //选择外部中断0为跳沿触发方式
Wh1le(1){
P1=0;
}
void int0( ) interrupt 0 using 1{ //外中断0的中断服务函数
uchar m;
EX0=0; //禁止外部中断0中断
for(m=0;m<5;m++){
P1=0xf0;
Delay(400);
P1=0x0f;
Delay(400);
}
EX0=1; //中断返回前,打开外部中断0中断
}