实现目标
1、了解51单片机中断51单片机中断系统、中断源、中断响应条件和优先级等,通过外部中断0实现按键控制LED亮灭为例理解中断工作原理和编程实现过程。
2、具体实现:按键事件的外部中断实现,实验现象为,按下第四个独立按键(P3.2
),第一个LED(P2.0
)亮灭翻转。
一、中断概述
1.1、中断定义
CPU执行程序时,由于发生了某种随机的事件(包括外部或内部),让CPU暂时停下正在运行的程序,转而去执行一段处理事件的程序(中断服务子程序或中断处理程序),当这段程序执行完时(事件处理完时),程序又返回被停下的程序继续执行,这一过程称为中断。引发中断的称为中断源。中断可分为外部中断和内部中断。
中断程序执行中又出现了中断,那么这种情况又叫做中断嵌套。
1.2、中断的作用和意义
中断的最终目的是高效处理紧急程序,并且不会占用CPU资源。还有就是能实现程序的并行化,实现嵌入式系统进程之间的切换等。
实时控制:在确定的时间内对相应事件做出相应;例如:温度控制;
故障处理:检测到故障,需要第一时间进行处理;
数据传输:不确定数据何时会来,利用中断进行控制;
1.3、中断的一些重要概念
中断涉及的概念比较多,先阐释如下:
轮询: 依次询问每一个IO设备,如果检测到需要提供服务,立刻执行服务,再询问下一个设备。
适用场景:频繁需要服务的外设
优点:实现简单
缺点:消耗大量CPU资源。慢速的IO交互无需大量频繁的检测。
中断: 当外部设备需要服务时,CPU接收到中断请求,立刻停止当前程序,转而执行中断服务程序,执行结束后,回到原先处继续执行。
适用场景:慢速交互的情况
优点:实时性高、即刻响应、节约CPU资源
缺点:实现稍复杂
中断源 :发生中断的源头 。传统51单片机 中一般至少有5个 基础的中断源 (按自然优先级排列)。
中断优先级:
自然优先级:当几个中断同时向CPU发出请求,CPU会根据中断自然优先级依次处理。
抢占优先级: 当进入某个中断时,发生了优先级更高的中断,CPU会打断低优先级的中断,转而执行高优先级中断,形成中断嵌套。同级不会打断。传统51单片机只有2个优先级,设置寄存器IP即可更改默认排序,一般保持默认即可。
**中断嵌套:**在执行中断服务函数的过程中,有优先级更高的中断发生,会暂停当前中断执行,转而执行更高级的中断程序。即形成嵌套。
中断请求: 中断源向CPU申请中断。
中断响应: CPU接收到中断请求转去执行中断服务程序的行为。
中断服务程序: 由开发者预先定义(关键字interrupt + 中断号),处理相应的中断事件。原则上,不要在中断中写任何阻塞程序,以保证其实时性。
中断号: 是CPU进入对应中断服务程序的重要标志,不同的中断源对应不同的中断号。
中断返回: 执行完对应中断服务程序后,返回中断点处继续往下执行。
**中断点:**主函数被中断的地方。
1.4、89C51/52的中断系统结构
二、外部中断
2.1 51单片机的外部中断
51单片机还有两个外部中断源:外部中断0、外部中断1。分别由单片机的12号引脚(INT0/P3.2)、13号(INT1/P3.3)引脚的低电平/负跳变触发。要使用这两个外部中断,首先要进行初始化操作,即写入相关的寄存器。初始化外部中断需要写入两个寄存器。IE -- 中断允许控制寄存器和TCON -- 控制寄存器,如果要修改中断优先级,则要写入IP寄存器(一般采用默认优先级)。
1、中断允许控制寄存器(IE)
2、中断请求标志寄存器(TCON)
3、中断优先级寄存器(IP)
2.2 外部中断配置(INT0 为例)
了解了上述3个寄存器 之后,配置引脚外部中断 其实很简单。具体配置流程如下(以INT0为例):
- 设置外部中断 触发方式为下降沿触发
IT0 = 1;
- 使能外部中断
EX0 = 1;
- 打开关总中断
EA = 1;
三、程序设计
3.1 外部中断0 程序
cpp
#include <REGX52.H>
sbit LED1 = P2^0;
sbit K3 = P3^2;
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
void INT0_Init(void) //外部中断函数初始化 子程序
{
EA = 1; //打开总中断开关
EX0 = 1; //打开外部中断0
IT0 = 1; //外部中断0设为低电平触发 // 1则为下降沿触发
}
void main() //主程序
{
INT0_Init(); //调用外部中断初始化程序,让它等待条件触发
while(1)
{
}
}
void INTO() interrupt 0 //当按键按下,下降沿触发,满足触发条件进来执行该中断程序
{
if(K3 == 0)
{
Delay10ms();
// 按下消抖
if(K3 == 0)
{
LED1 = !LED1;
}
}
}
3.2 外部中断1 程序
cpp
#include <REGX52.H>
sbit LED1 = P2^0;
sbit K4 = P3^3;
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 18;
j = 235;
do
{
while (--j);
} while (--i);
}
void main() //主程序
{
IT1 = 1; //外部中断1设为低电平触发 // 1则为下降沿触发
EX1 = 1; //打开外部中断1
EA = 1; //打开总中断开关
while(1)
{
}
}
void INT1_1() interrupt 0 //当按键按下,下降沿触发,满足触发条件进来执行该中断程序
{
if(K4 == 0)
{
Delay10ms();
// 按下消抖
if(K4 == 0)
{
LED1 = !LED1;
}
}
}