51单片机中断原理(AT89C51)
(1)中断技术
AT89C51单片机中断原理是指单片机在执行程序时,可以根据外部事件的发生情况来中断当前程序的执行,转而执行相应的中断服务程序。AT89C51单片机中断原理包括以下几个方面:
1. 中断源:AT89C51单片机具有多个中断源,如外部中断、定时器/计数器中断、串行通信中断等。当某个中断源满足触发条件时,会向单片机发送中断请求信号。
2. 中断向量表:AT89C51单片机中断向量表存储了每个中断源对应的中断服务程序的入口地址。当中断发生时,单片机会根据中断源的优先级找到相应的中断向量表项,跳转到对应的中断服务程序执行。
3. 中断优先级:AT89C51单片机支持不同中断源的优先级设置,可以通过设置相关寄存器来确定各个中断源的优先级,以确保在多个中断同时发生时,能够按照设定的优先级顺序进行中断处理。
4. 中断服务程序:中断服务程序是处理中断事件的具体代码,包括保存现场、执行相应的处理逻辑、恢复现场等步骤。在中断结束后,单片机会返回到被中断前的程序继续执行。
总的来说,AT89C51单片机中断原理通过中断源、中断向量表、中断优先级和中断服务程序等组成部分,实现了对外部事件的及时响应和处理。
(2)单双外中断
(1)单
原理介绍::在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接一只按钮开关K1。要求将外部中断0设置为电平触发。程序启动时,P1口上的8只LED全亮。每按一次按钮开关K1,使引脚接地,产生一个低电平触发的外中断请求,在中断服务程序中,让低4位的LED与高4位的LED交替闪烁5次。然后从中断返回,控制8只LED再次全亮。
C语言代码
#include <reg51.h>
#define uchar unsigned char
// 延时函数Delay( ),i形式参数,不能赋初值
void Delay(unsigned int 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为跳沿触发方式
while(1) // 循环
{
P1 = 0; // P1口的8只LED全亮
}
}
// 外中断0的中断服务函数
void int0() interrupt 0 using 0
{
uchar m;
EX0 = 0; // 禁止外部中断0中断
for(m = 0; m < 5; m++) // 交替闪烁5次
{
P1 = 0x0F; // 低4位LED灭,高4位LED亮
Delay(400); // 延时
P1 = 0xF0; // 高4位LED灭,低4位LED亮
Delay(400); // 延时
}
EX0 = 1; // 中断返回前,打开外部中断0中断
}
WeChat_20240407210525
(2)双
原理介绍:在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接有一只按钮开关K1。在外部中断1输入引脚(P3.3)接有一只按钮开关K2。要求K1和K2都未按下时,P1口的8只LED呈流水灯显示,仅K1(P3.2)按下再松开时,上下各4只LED交替闪烁10次,然后再回到流水灯显示。如果按下再松开K2(P3.3)时,P1口的8只LED全部闪烁10次,然后再回到流水灯显示。
C语言代码
#include <reg51.h>
#define uchar unsigned char
void Delay(unsigned int i) // 延时函数Delay( ), i为形式参数,不能赋初值
{
uchar j;
for (; i > 0; i--)
for (j = 0; j < 125; j++)
; // 空函数
}
void main() // 主函数
{
uchar display[9] = {0xff, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; // 流水灯显示数据数组
unsigned int a;
for (;;)
{
EA = 1; // 总中断允许
EX0 = 1; // 允许外部中断0中断
EX1 = 1; // 允许外部中断1中断
IT0 = 1; // 选择外部中断0为跳沿触发方式
IT1 = 1; // 选择外部中断1为跳沿触发方式
IP = 0; // 两个外部中断均为低优先级
for (a = 0; a < 9; a++)
{
Delay(500); // 延时
P1 = display[a]; // 将已经定义的流水灯显示数据送到P1口
}
}
}
void int0_isr(void) interrupt 0 using 1 // 外中断0的中断服务函数
{
uchar n;
for (n = 0; n < 10; n++) // 高、低4位显示10次
{
P1 = 0x0f; // 低4位LED灭,高4位LED亮
Delay(500); // 延时
P1 = 0xf0; // 高4位LED灭,低4位LED亮
Delay(500); // 延时
}
}
void int1_isr(void) interrupt 2 using 2 // 外中断1中断服务函数
{
uchar m;
for (m = 0; m < 10; m++) // 闪烁显示10次
{
P1 = 0xff; // 全灭
Delay(500); // 延时
P1 = 0; // 全亮
Delay(500); // 延时
}
}
(3)两个按键实现中断嵌套
原理介绍:中断嵌套只发生正执行一个低优先级中断,此时又有一高优先级中断产生,就会去执行高优先级中断服务程序。高优先级中断服务程序完成后,再继续执行低优先级中断程序。
设计一中断嵌套程序:要求K1和K2都未按下时,P1口8只LED呈流水灯显示,当按一下K1时,产生一个低优先级外中断0请求(跳沿触发),进入外中断0中断服务程序,上下4只LED交替闪烁。此时按一下K2时,产生一个高优先级的外中断1请求(跳沿触发),进入外中断1中断服务程序,使8只LED全部闪烁。当显示5次后,再从外中断1返回继续执行外中断0中断服务程序,即P1口控制8只LED,上、下4只LED交替闪烁。设置外中断0为低优先级,外中断1为高优先级。
C语言代码:
#include <reg51.h>
#define uchar unsigned char
// 延时函数
void Delay(unsigned int i) // Delay function
{
unsigned int j;
for(; i > 0; i--)
for(j = 0; j < 125; j++)
; // 空函数
}
// 主函数
void main( )
{
uchar display[9]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
// 流水灯显示数据组
uchar a;
for(;;)
{
EA=1; // 总中断允许
EX0=1; // 允许外部中断0中断
EX1=1; // 允许外部中断1中断
IT0=1; // 选择外部中断0为跳沿触发方式
IT1=1; // 选择外部中断1为跳沿触发方式
PX0=0; // 外部中断0为低优先级
PX1=1; // 外部中断1为高优先级
for(a=0; a<9; a++)
{
Delay(500); // 延时
P1=display[a]; // 流水灯显示数据送到P1口驱动LED显示
}
}
}
// 外中断0中断函数
void int0_isr(void) interrupt 0 using 0
{
for(;;)
{
P1=0x0f; // 低4位LED灭,高4位LED亮
Delay(400); // 延时
P1=0xf0; // 高4位LED灭,低4位LED亮
Delay(400); // 延时
}
}
// 外中断1中断函数
void int1_isr (void) interrupt 2 using 1
{
uchar m;
for(m=0; m<5; m++) // 8位LED全亮全灭5次
{
P1=0; // 8位LED全亮
Delay(500); // 延时
P1=0xff; // 8位LED全灭
Delay(500); // 延时
}
}
(4)定时器/计数器
内容介绍:定时器控制LED灯每隔1s周期性亮灭,并用Keil仿真中的虚拟逻辑仪对LED管脚进行波形观察,测量真实的周期数,并与上次采用软件循环进行周期定时的精度进行对比,看哪一种方式更加精准。
C语言代码:
#include<reg51.h>
char i = 100;
void main ()
{
TMOD = 0x01; // 定时器T0为方式1
TH0 = 0xee; // 设置定时器初值
TL0 = 0x00;
P1 = 0x00; // P1口8个LED点亮
EA = 1; // 总中断开
ET0 = 1; // 开T0中断
TR0 = 1; // 启动T0
while (1) // 循环等待
{
;
}
}
void timer0 () interrupt 1 // T0中断程序
{
TH0 = 0xee; // 重新赋初值
TL0 = 0x00;
i--; // 循环次数减1
if (i <= 0)
{
P1 = ~P1; // P1口按位取反
i = 100; // 重置循环次数
}
}
Keil软件,使用Keil软件自带的虚拟逻辑示波器功能可以得到P1端口波形变化效果图如下:
(5)计数器控制
内容介绍:T1采用计数模式,方式1中断,计数输入引脚T1(P3.5)上外接按钮开关,作为计数信号输入。按4次按钮开关后,P1口的8只LED闪烁不停。
C语言代码:
#include <reg51.h>
void Delay(unsigned int i) //定义延时函数Delay( ),i是形 //式参数,不能赋初值
{
unsigned int j;
for(;i>0;i--) //变量i由实际参数传入一个值 //因此i不能赋初值
for(j=0;j<125;j++)
{;} //空函数
}
void main( ) //主函数
{
TMOD=0x50; //设置定时器T1为方式1计数
TH1=0xff; //向TH1写入初值的高8位
TL1=0xfc; //向TL1写入初值的低8位
EA=1; //总中断允许
ET1=1; //定时器T1中断允许
TR1=1; //启动定时器T1
while(1); //无穷循环,等待计数中断
}
void T1_int(void) interrupt 3 //T1中断函数
{
for(;;) //无限循环
{
P1=0xff; //8位LED全灭
Delay(500); //延时500ms
P1=0; //8位LED全亮
Delay(500); //延时500ms
}
}