关键词:中断系统;外部中断的基本应用;定时器中断;小蜜蜂;江科大
一、知识点:
1.中断;中断服务函数;中断向量;中断源;中断响应;中断返回;现场保护;现场恢复;中断嵌套;中断优先级
2.5个中断源以及其优先级排序、中断号
3.6个引脚:INT0/1(外部中断0/1)、T0/T1(计数器输入端)、RX/TX(串口输入输出端)
4.外部中断信号触发(IT0/IT1):1下降沿触发,0低电平触发
5.IE(中断控制寄存器),理解为中断的开关,其中EA为总开关,只有总开关接上,而且相应开关(eg.EX0)(小开关)也接上,外部中断才能通知内核,内核才能响应
6.中断相关寄存器(IE、IP、TCON、SCON)及其各个位对应的含义
7.中断服务函数程序的编写(中断初始化函数、中断服务函数)及其格式
8.TMOD:
高四位定时器1,低四位定时器0。四位分别为Gate(Gate=0,TRX=1,定时器/计数器启动;Gate=1,TRX=1,INTX=1定时器/计数器启动)、C/T(C/T=1计数器;C/T=0定时器)、M1&M0(工作模式选择,一般选01,串口一般选10),不可位寻址,只能进行与和或操作进行赋值
9.TCON:(X取1/0)
TFX:定时器/计数器X溢出标志,最高位溢出硬件置1,直到响应中断,才清零(也可由程序清零)
TRX:定时器运行控制位,与8中相对应,控制其启动计数与否
IEX:外部中断X请求中断源,IEX=1请求中断,CPU响应清零
ITX:外部中断X触发控制位,ITX=0低电平触发,ITX=1下降沿触发
10.IE:(x可取0/1)
EA:总闸
ETx:定时器/计数器x溢出中断允许位
EXx:外部中断x中断允许位
ES:串行口1中断允许位
详细知识点参考:
1.【蓝桥杯单片机07】彻底理解51单片机的中断系统 https://bbs.21ic.com/icview-2477100-1-1.html?fromuser=%E9%9B%B6%E5%9F%BA%E7%A1%80%E5%B0%8F%E5%A4%95
(出处: 21ic电子技术开发论坛)
2.http://t.csdnimg.cn/W0Nhk51单片机学习笔记(中断系统)http://t.csdnimg.cn/W0Nhk
二、实验
实验目的:
实验步骤:
S1:完成主函数部分(让L1不断闪烁)
需要部件:
1.L1对应引脚(位声明)
2.HC573锁存器让信道4打开,LED使能端打开,LED才能亮
3.闪烁需要中间搭配延时函数(长延时):unsigned int以及多个while循环
4.working函数放在main的while循环中
代码:
#include <REGX52.H>
sbit L1=P0^0;
sbit L8=P0^7;//用到LED灯,对其进行位声明
void SelectHC573(void)
{
P2=(P2&0x1F)|0x80;//只需要打开与LED相关的锁存器开关
}
void Delay(unsigned int t)
{
while(t--);
while(t--);
while(t--);//较长的延时
}
void working()
{
SelectHC573();//只有先调用该函数才能让LED有机会亮起来(使能端)
L1=0;
Delay(60000);
L1=1;
Delay(60000);
}
void main()
{
while(1)
{
working();
}
}
实验现象:L1不断闪烁,但按S5没有反应,未编写中断函数
S2:编写中断初始化函数(启动中断)
void Init_INT0()//中断初始化函数
{
IT0=1;//下降沿触发
EA=1;//IE总开关
EX0=1;//IE对应外部中断0的小开关
//PX0没有设置,是因为其控制优先级,这里不必,让其为默认值就好
}
void main()
{
Init_INT0();
while(1)
{
working();
}
}
S3:【方法一】中断服务函数之直接在中断服务函数中延时
void ServiceINT0() interrupt 0 //为外部中断0服务的中断函数
{
L8=0;
Delay(60000);
Delay(60000);
Delay(60000);
Delay(60000);
L8=1;
}
实验现象:L1不断闪烁,按下S5,L8闪烁
疑问:S5按键和INT0引脚相连,但按下S5和中断启动有什么关联?——>按下S5,触发低电平或下降沿,作为中断信号
S4:【方法二】中断服务函数之在中断服务函数中标志变量,在外部执行延时
代码:
unsigned char stat_int=0;//中断标志位
void ServiceINT0() interrupt 0 //为外部中断0服务的中断函数
{
stat_int=1;
}
void LEDINT(void)
{
if(stat_int==1)//说明有外部中断产生
{
L8=0;
Delay(60000);
Delay(60000);
Delay(60000);
Delay(60000);
L8=1;
}
stat_int=0;//执行中断中的任务后,标志位清零归位
}
void main()
{
Init_INT0();
while(1)
{
working();
LEDINT();//放在while循环中不断查询标志位的状态,从而判断是否执行中断任务
}
}
优点:中断服务函数内部尽量简洁(少做事情),只需对标志位进行置1,适用于一整个外部事件在中断任务中执行。中断函数一般要求快进快出,一些可做可不做的事放到中断外面去做,保障实时性
缺点:有点类似轮流查询,L1亮的时候L8不会亮,L8亮的时候L1不会亮
完整代码:
#include <REGX52.H>
sbit L1=P0^0;
sbit L8=P0^7;//用到LED灯,对其进行位声明
void SelectHC573(void)
{
P2=(P2&0x1F)|0x80;//只需要打开与LED相关的锁存器开关
}
void Delay(unsigned int t)
{
while(t--);
while(t--);
while(t--);//较长的延时
}
void working()
{
SelectHC573();//只有先调用该函数才能让LED有机会亮起来(使能端)
L1=0;
Delay(60000);
L1=1;
Delay(60000);
}
//*****
void Init_INT0()//中断初始化函数
{
IT0=1;//下降沿触发
EA=1;//IE总开关
EX0=1;//IE对应外部中断0的小开关
}
unsigned char stat_int=0;//中断标志位
void ServiceINT0() interrupt 0 //为外部中断0服务的中断函数
{
stat_int=1;
}
void LEDINT(void)
{
if(stat_int==1)//说明有外部中断产生
{
L8=0;
Delay(60000);
Delay(60000);
Delay(60000);
Delay(60000);
L8=1;
}
stat_int=0;//执行中断中的任务后,标志位清零归位
}
//*****
void main()
{
Init_INT0();
while(1)
{
working();
LEDINT();//放在while循环中不断查询标志位的状态,从而判断是否执行中断任务
}
}
三、经验总结
1.中断函数的主函数
2.中断函数的初始化和中断服务函数的编写
3.状态位
4.延时在中断函数内部和外部的区别
感谢B站小蜜蜂老师的教程,本笔记资料及代码均来自教程,仅作为个人复习、整理和学习交流用。