项目文件
关于项目的内容知识点可以见专栏单片机原理及应用 的第五章,中断
根据下原理图,编程验证二级外部中断嵌套效果。其中K0定为低优先级中断源,K1为高优先级中断源。此外,利用发光二极管D1验证外部中断请求标志IE0在脉冲触发中断时候的硬件置位与撤销过程
- 先实现LED0:3只数码管可分别进行字符19的循环计数显示,其中主函数采用无限计数显示,KO和K1的中断函数则采用单圈计数显示。
- 由于K0的自然优先级(接INTO引脚)高于K1(接INT1引脚),故需要将K1的中断级别设为高优先级,即PX1=1,PX0=0
- 高级中断运行时,若有低级中断请求,则D1点亮;高级中断结束后,低级中断才能运行。
- 由于IEO 的撤销过程发生在 K0 响应中断的瞬间,故在 KO中断函数里将IEO值送 P3.0输出可验证这一过程。
而IEO 的置位信息较难捕捉,可以利用“低级中断请求虽不能中止高级中断响应过程,但可保留中断请求信息”的原理进行,即在K1中断函数里设置输出IEO语句。
一步一步写
先定义好字模和D1和延时函数
#include "reg51.h"
char led_mod[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //led字模
0x7f,0x6f}; //显示字模
sbit D1=P3^0; //原理图D1接P3_0
void delay(unsigned int time){//延时
unsigned char j=255;
for(;time>0;time--)
for(;j>0;j--);
}
先写主函数:
void main(){
unsigned char i;
TCON = 0x05; //脉冲触发方式
0x05是0000 0101 ——对应TCON寄存器的位
这样IT1和IT0为1,脉冲触发
上面说的
K0接INT0引脚,K1接INT1引脚,K1高级中断,优先级要设置高,即
PX1=1 ,PX0=0;
PX0=0;PX1=1; //INT1优先
然后继续
D1=1;P1=P2=0x40; //输出初值
D1=1 刚开始时候这样电平,D1灯是灭的,等于初始化
P1=P2=0x40;
这里用的 晶体管竟然还是共阴极的动态数码管
由他们各自连接的端口控制
0x40=0100 0000
这样就是P1和P2等于0 100 0000
显示是 -
对应LED1 2
LED0开始端口P0为高电压
继续写:
IE=0x85; //开中断
这里是IE寄存器 为1000 0101
EA=1;EX1=1;EX0=1;
总中断允许;INT1中断允许;INT0允许
继续写:
while(1){
for(i=0;i<=9;i++){ //字符0-9无限循环
P0=led_mod[i];
delay(35000);
}
}
}
主函数中的循环, P0=led_mod[i]; led_mode是共阴极数码管0~9
所以LED0从0到9无限循环
主函数代码:
void main(){
unsigned char i;
TCON = 0x05; //脉冲触发方式
PX0=0;PX1=1; //INT1优先
D1=1;P1=P2=0x40; //输出初值
IE=0x85; //开中断
while(1){
for(i=0;i<=9;i++){ //字符0-9无限循环
P0=led_mod[i];
delay(35000);
}
}
}
下面写中断函数
key0() interrupt 0 { //K0中断函数
unsigned char i;
D1=!IE0; //IE0状态输出
for(i=0;i<=9;i++){ //字符0-9循环1圈
P2=led_mod[i];
delay(35000);
}P2=0x40; //结束符“-”
}
key0() interrupt 0 { //K0中断函数
定义中断服务函数
这里的0是中断号
这样才能对应是哪个中断
unsigned char i;
D1=!IE0; //IE0状态输出
for(i=0;i<=9;i++){ //字符0-9循环1圈
P2=led_mod[i];
delay(35000);
}P2=0x40; //结束符“-”
D1=!IE0; D1初始值为1,D1对应着INT0的中断请求标志IE0的非
这里为啥取非?
因为D1对应的灯D1端口为0时候亮
所以IE0=1中断开始,D1亮可以作为一个判断v
然后单圈灯
for(i=0;i<=9;i++){ //字符0-9循环1圈
P2=led_mod[i];
delay(35000);
}P2=0x40; //结束符“-”
就亮了循环一圈
‼️‼️ 总体看:
按下K0后
INT0端口变为低电压,传给INT0非为低电压
这里要看IE0是哪种模式(脉冲还是电平)
TCON = 0x05; //脉冲触发方式
所以为1变0为负跳变脉冲所以为1变0为负跳变脉冲
IE0置1,中断开始
中断服务函数
流程图:
如果错误请指出,大致总结下
K1也是这样,但是K1是优先级为高在这个例子中
因为项目总代码:
#include "reg51.h"
char led_mod[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, //led字模
0x7f,0x6f}; //显示字模
sbit D1=P3^0;
void delay(unsigned int time){//延时
unsigned char j=255;
for(;time>0;time--)
for(;j>0;j--);
}
key0() interrupt 0 { //K0中断函数
unsigned char i;
D1=!IE0; //IE0状态输出
for(i=0;i<=9;i++){ //字符0-9循环1圈
P2=led_mod[i];
delay(35000);
}P2=0x40; //结束符“-”
}
key1() interrupt 2 { //K1中断函数
unsigned char i;
for(i=0;i<=9;i++){ //字符0-9循环1圈
D1=!IE0; //IE0状态输出
P1=led_mod[i];
delay(35000);
}P1=0x40; //结束符“-”
}
void main(){
unsigned char i;
TCON = 0x05; //脉冲触发方式
PX0=0;PX1=1; //INT1优先
D1=1;P1=P2=0x40; //输出初值
IE=0x85; //开中断
while(1){
for(i=0;i<=9;i++){ //字符0-9无限循环
P0=led_mod[i];
delay(35000);
}
}
}
现象:
LED0无限循环
按下K0,INT0中断开始,进入中断函数key0,len1循环一圈
按下K1,INT1中断开始,进入中断函数key1,len2循环一圈
因为K1的定义的中断优先级高,所以如果K0中断运行的时候
点击K1,K1中断优先,等K1结束才能到K0中断
最终,中断时候中断函数下面的LED0的循环亮暂时没到中止
观察D1的信息
D1开始为1.灭的
中断函数中定义D1=!IE0
IE0是INT0的中断标志,当INT0中断运行时候
IE0=1
所以D1=0; 亮
在K1中断中也有这个
但是它是在for内部
D1一直在变
结果:
视频: