外部中断_单片机_普中
1 中断介绍
在我们的日常生活中,经常会遇到这样的情况:我们正在看书,突然客厅的电话响了,这时往往会停止看书,转而去接电话,接完电话后又接着看书。这种停止当前工作,转而去做其他工作,做完后又返回来做先前工作的现象称为中断。
所以单片机虽然是个机器,它也有类似的中断现象,当单片机正在执行某程序时,如果突然出现意外情况,它就需要停止当前正在执行的程序,转而去处理意外情况,处理完后又接着执行原来的程序。
2 中断相关概念
图1 中断结构图
(1) 中断源
要让 CPU 中断当前的程序去做其他事情,需要向它发出请求信号,CPU 接收到中断请求信号后才能产生中断。让CPU产生中断的信号称为中断源(又称中断请求源)。
51系列单片机的中断源包括:两个外部中断源、两个定时器/计数器中断源和一个串行通信口中断源,如果它们向 CPU 发出中断请求信号,CPU 就会产生中断,停止执行当前的程序,转而去执行指定的程序(又称中断服务程序或中断子程序),执行完后又返回来执行原来的程序。
(2) 中断的优先级别
单片机内的CPU在工作时,如果一个中断源向它发出中断请求信号,它就会产生中断;如果同时有两个或两个以上的中断源发出中断请求信号,CPU会怎么办呢?CPU会先接受优先级别高的中断源请求,然后再接受优先级别低的中断源请求。
(3) 中断处理过程
① 响应中断请求。当 CPU 正在执行主程序时,如果接收到中断源发出的中断请求信号,就会响应中断请求,停止主程序,开始执行中断。
② 保护断点。为了在执行完中断后能返回主程序,在执行中断时,会将主程序的下一条指令的地址(又称断点地址)保存到数据存储器(RAM)的堆栈中。
③ 寻找中断入口地址。保护好断点后,CPU开始寻找中断入口地址(又称矢量地址),中断入口地址存放着相应的中断子程序,不同的中断源对应着不同的中断入口地址。
④ 执行中断子程序。CPU寻找到中断入口地址后,就开始执行中断入口地址处的中断子程序。由于几个中断入口地址之间只有8个单元空间(表中如0003H~000BH相隔8个单元),较小的中断子程序(程序只有一两条指令)可以写在这里,较大的中断子程序无法写入,通常的做法是将子程序写在其他位置,而在中断入口地址单元只写一条跳转指令,由该指令跳转到中断子程序。
⑤ 中断返回。执行完中断子程序后,就会返回到主程序,返回的方法是从RAM的堆栈中取出之前保存的断点地址,然后执行该地址处的主程序,从而返回到主程序。
(4)中断相关寄存器
(5)中断响应条件:①中断源有中断请求;②中断源的中断允许位为 1;③ CPU 开中断(即 EA=1)。
3 功能要求:外部中断属于单片机的内部资源,本实验所使用的独立按键KEY3和KEY3直接接在单片机开发板P3.2和P3.3,而P3.2和P3.3不仅是普通的IO口,而且还可以作为外部中断使用。故可以通过按键来模拟外部的脉冲信号输入到外部中断管脚来触发外部中断。要实现的功能是,当按下KEY3可控制LED1指示灯亮灭,按下KEY4可控制LED2指示灯亮灭。
4 原理分析
(1)在中断结构图1中,INT0和INT1即为外部中断0和外部中断1。
INT0对应的是P3.2口的附加功能,可由IT0选择其触发方式(低电平有效或者下降沿有效)。当CPU监测到P3.2引脚上出现有效的中断信号时,中断标志IE0置1(单片机自动完成),向申请中断。
INT1对应的是P3.3口的附加功能,可由IT1选择其触发方式(低电平有效或者下降沿有效)。当CPU监测到P3.3引脚上出现有效的中断信号时,中断标志IE1置1(单片机自动完成),向申请中断。
(2)外部中断寄存器的配置
1)中断请求标志寄存器 TCON
① IT0(TCON[0]):外部中断0触发方式控制位,当IT0=0时,为低电平触发方式;当IT0=1时,为边沿触发方式(下降沿有效);
② IE0(TCON[1]):外部中断0中断请求标志位;
③ IT1(TCON[2]):外部中断1触发方式控制位,当IT1=0时,为低电平触发方式;当IT1=1时,为边沿触发方式(下降沿有效);
④ IE1(TCON[3]):外部中断1中断请求标志位。
2)中断允许控制寄存器 IE
① EX0(IE[0]):外部中断0允许位;
② ET0(IE[1]):定时/计数器T0中断允许位;
③ EX1(IE[2]):外部中断1允许位;
④ ET1(IE[3]):定时/计数器T1中断允许位;
⑤ ES(IE[4]):串行口中断允许位;
⑥ IE[5]
⑦ IE[6]
⑧ EA(IE[7]):CPU中断允许位,即总允许位。
4 硬件设计
(1)系统框图
(2)独立按键和LED灯原理图
5 软件设计
1 #include "reg52.h" 2 3 typedef unsigned int u16; 4 typedef unsigned char u8; 5 6 //定义输入、输出管脚 7 sbit KEY3 = P3^2; //独立按键3控制管脚 8 sbit KEY4 = P3^3; //独立按键4控制管脚 9 sbit LED1 = P2^0; //LED1控制管脚 10 sbit LED2 = P2^1; //LED2控制管脚 11 12 //延时函数,ten_us=1时,大约延时10us 13 void delay_10us(u16 ten_us) 14 { 15 while(ten_us--); 16 } 17 18 //对外部中断0进行初始化设置 19 void exti0_init(void) 20 { 21 IT0 = 1; //下降沿触发方式 22 EX0 = 1; //打开INT0的中断允许 23 EA = 1; //打开总中断 24 } 25 26 //对外部中断1进行初始化设置 27 void exti1_init(void) 28 { 29 IT1 = 1; //下降沿触发方式 30 EX1 = 1; //打开INT1的中断允许 31 EA = 1; //打开总中断 32 } 33 34 void main() 35 { 36 exti0_init(); //对外部中断INT0进行配置 37 exti1_init(); //对外部中断INT1进行配置 38 while(1) 39 { 40 41 } 42 } 43 44 //外部中断0中断函数,中断号为0 45 void exti0() interrupt 0 46 { 47 delay_10us(1000); //消抖,忽略按下抖动过程 48 if(KEY3==0) //再次判断按键3是否按下 49 LED1 = !LED1; //LED1状态翻转 50 } 51 52 //外部中断1中断函数,中断号为2 53 void exti1() interrupt 2 54 { 55 delay_10us(1000); //消抖,忽略按下抖动过程 56 if(KEY4==0) //再次判断按键4是否按下 57 LED2 = !LED2; //LED2状态翻转 58 }
6 仿真结果
7 实现现象
当按下按键KEY3,指示灯LED1点亮,再按下按键KEY3,指示灯LED1熄灭,如次循环。同理,按键KEY4控制LED2。