目录
前言
分析STC89C52外部中断的硬件组成与细节。中断:为了响应外部或内部的事件而暂停当前正在执行的任务,转而去处理这些事件的一种机制。
实验2中,使用数码管和LED1/2,和电机进行中断实验,后续会介绍到。
一.中断概念
1.1 什么是中断
中断是计算机运行过程中,为了响应外部或内部的事件而暂停当前正在执行的任务,转而去处理这些事件的一种机制。
中断机制是现代计算机系统中不可或缺的组成部分,它允许CPU在必要时打断正在进行的任务,转而处理其他更紧急的任务。中断可以分为两大类:
- 外部中断:这类中断是由CPU之外的设备发起的,比如输入/输出设备的请求、定时器到期或者外部信号的到来等。
- 内部中断:这类中断是由CPU内部产生的,通常与程序执行相关,如除以零、访问非法内存地址等。
此外,中断还可以分为可屏蔽中断和不可屏蔽中断。可屏蔽中断可以被CPU忽略,而不可屏蔽中断则必须被CPU立即处理。
总的来说,中断机制使得计算机能够更加高效地运行,它允许系统及时响应外部事件,保证系统的实时性和可靠性。同时,它也为多任务操作系统提供了基础,使得多个任务能够共享CPU资源,提高了计算机的整体性能。
1.2 中断流程图
中断随时有可能发生,但无论何时发生,只要一旦发生,单片机将立即暂停当前程序, 赶去处理中断程序,处理完中断程序后再返回刚才暂停处接着执行原来的程序。 单片机在执行程序时其程序流程图如下:
1.3 中断机制优点
中断机制的优点主要体现在以下几个方面:
- 实时响应:中断允许计算机系统对外部事件做出快速的响应。当外部设备需要CPU注意时,中断机制可以立即暂停当前任务,确保系统能够在最短的时间内处理这些事件。
- 资源利用:通过中断,CPU可以在等待外部设备完成操作(如输入/输出)的同时执行其他任务,这样可以提高CPU的利用率,避免资源的浪费。
- 多任务处理:在多任务操作系统中,中断机制是实现任务切换的关键。它使得操作系统能够在不同的任务之间进行有效的切换,每个任务都能够得到合理的CPU时间,从而保证系统的公平性和效率。
- 错误处理:中断机制可以帮助计算机及时发现和处理运行中的错误,如硬件故障或程序异常,从而保证系统的稳定运行。
- 用户交互:中断使得计算机能够及时响应用户的输入,如键盘敲击和鼠标移动,提供流畅的用户体验。
- 紧急事件处理:对于一些紧急事件,如电源故障或其他关键硬件问题,中断机制可以确保计算机能够立即处理这些问题,防止更严重的损害发生。
二.外部中断
2.1 什么是外部中断
外部中断通常涉及到以下几个方面:
- 配置和使能:为了产生中断,需要先对中断线进行配置和使能。这包括设置边沿检测的触发寄存器,以及在中断屏蔽寄存器的相应位写入1以允许中断请求。
- 触发方式:外部中断可以通过I/O接口的高低电平变化来触发。当外部设备(如传感器或另一个计算机系统)向接口发送信号时,会产生一个中断请求。
- 中断函数:一旦外部中断被触发,CPU会暂停当前的任务,转而执行与该中断相关的中断服务程序或中断函数。这个函数通常用于处理外部设备的数据或响应外部事件。
- 定时中断:虽然定时中断通常不被归类为外部中断,但它们也是由外部时钟信号触发的。当达到预定的时间点时,系统会进入定时中断响应函数。
- 串口中断:串口中断是外部中断的另一种形式,当串口的数据寄存器不为空时,即有数据等待传输或接收时,系统会进入串口的中断响应函数。
2.2 外部中断介绍
2.2.1 STC89C52RC外部中断结构图
图中 INT0 和 INT1 即为外部中断 0 和外部中断 1 输入口。
①INT0 对应的是 P3.2 口的附加功能,可由 IT0(TCON.0)选择其为低电平有 效还是下降沿有效。当 CPU 检测到 P3.2 引脚上出现有效的中断信号时,中断标志 IE0(TCON.1)置 1,向 CPU 申请中断。
②INT1 对应的是 P3.3 口的附加功能,可由 IT1(TCON.2)选择其为低电平有 效还是下降沿有效。当 CPU 检测到 P3.3 引脚上出现有效的中断信号时,中断标志 IE1(TCON.3)置 1,向CPU 申请中断。
2.2.2 中断允许控制
CPU 对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器 IE 控制的。
EX0(IE.0),外部中断 0 允许位;
ET0(IE.1),定时/计数器 T0 中断允许位;
EX1(IE.2),外部中断 0 允许位;
ET1(IE.3),定时/计数器 T1 中断允许位;
ES(IE.4),串行口中断允许位;
EA (IE.7), CPU 中断允许(总允许)位
2.2.3 中断请求标志 TCON
IT0(TCON.0),外部中断 0 触发方式控制位。
当 IT0=0 时,为电平触发方式。
当 IT0=1 时,为边沿触发方式(下降沿有效)。
IE0(TCON.1),外部中断 0 中断请求标志位。
IT1(TCON.2),外部中断 1 触发方式控制位。
IE1(TCON.3),外部中断 1 中断请求标志位。
TF0(TCON.5),定时/计数器 T0 溢出中断请求标志位。
TF1(TCON.7),定时/计数器 T1 溢出中断请求标志位
三.外部中断配置
3.1基础配置
我们使用基本的 2 个外部中断:(INT0 和 INT1)。
我们知道要让 51 单片机发生中断必须要满足以下 3 个条件,这 3 个条件的 顺序可以任意:
①中断源有中断请求;
②此中断源的中断允许位为 1;
③CPU
比如我们配置外部中断 0,对应的配置程序如下:
EA=1;//打开总中断开关
EX0=1;//开外部中断 0
IT0=0/1;//设置外部中断的触发方式
void exti0_init(void) { IT0=1;//跳变沿触发方式(下降沿) EX0=1;//打开 INT0 的中断允许 EA=1;//打开总中断 } void exti0() interrupt 0 //外部中断 0 中断函数 { //执行所需的功能 }
3.2 基础实验1
实验1:使用独立按键 K3 控制 LED 亮灭,K3 连接外部 中断 0(P3.2)管脚。学习本章可以参考前面的实验章节内容。
3.2.1 硬件部分
本实验使用到硬件资源如下:
(1)独立按键模块(K3)
(2)LED 模块(D1) LED 模块和独立按键模块电路在前面章节已介绍过,这里就不多说。原理图 中 K3 键是连接在单片机 P3.2 口(外部中断 0),K4 按键是连接在 P3.3 口(外 部中断 1)
实验结果:通过控制K3开关,实现中断函数中对LED灯的亮灭操作。
3.2.1 代码部分
#include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; //定义LED1管脚 sbit LED1=P2^0; //定义独立按键K3控制脚 sbit KEY3=P3^2; void delay_10us(u16 ten_us) { while(ten_us--); } void exti0_init(void) { IT0=1;//跳变沿触发方式(下降沿) EX0=1;//打开INT0的中断允许 EA=1;//打开总中断 } void main() { exti0_init();//外部中断0配置 while(1) { } } void exti0() interrupt 0 //外部中断0中断函数 { delay_10us(1000);//消斗 if(KEY3==0)//再次判断K3键是否按下 LED1=!LED1;//LED1状态翻转 }
3.3 基础实验2
主程序:8*8LED点阵以一行循环滚动显示,
使用外部中断0:使用 K3 控制 LED1亮灭,
使用外部中断2:使用K4控制直流电机开启和LED2亮灭。
3.3.1硬件部分
3.3.2运行代码
#include "reg52.h" typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; //定义74HC595控制管脚 sbit SRCLK=P3^6; //移位寄存器时钟输入 sbit rCLK=P3^5; //存储寄存器时钟输入 sbit SER=P3^4; //串行数据输入 #define LEDDZ_COL_PORT P0 //点阵列控制端口 u8 ghc595_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //定义独立按键控制脚 sbit KEY3=P3^2; sbit KEY4=P3^3; //定义LED1控制脚 sbit LED1=P2^0; sbit LED2=P2^1; //定义直流电机控制管脚 sbit DC_Motor=P1^0; void delay_ms(u16 ms) { u16 i,j; for(i=ms;i>0;i--) for(j=110;j>0;j--); } void delay_10us(u16 ten_us) { while(ten_us--); } void exti0_init(void) { IT0=1; EX0=1; EA=1; } void exti1_init(void) { IT1=1; EX1=1; EA=1; } void hc595_write_data(u8 dat) { u8 i=0; for(i=0;i<8;i++)//循环8次即可将一个字节写入寄存器中 { SER=dat>>7;//优先传输一个字节中的高位 dat<<=1;//将低位移动到高位 SRCLK=0; delay_10us(1); SRCLK=1; delay_10us(1);//移位寄存器时钟上升沿将端口数据送入寄存器中 } rCLK=1; delay_10us(1); rCLK=0;//存储寄存器时钟上升沿将前面写入到寄存器的数据输出 } void main() { u8 i=0; exti0_init(); exti1_init(); LEDDZ_COL_PORT=0x00;//将LED点阵列全部设置为0,即LED阴极为低电平 DC_Motor=0;//关闭电机 while(1) { for(i=0;i<8;i++) { hc595_write_data(0x00);//消除前面寄存器缓存数据 hc595_write_data(ghc595_buf[i]);//写入新的数据 delay_ms(500);//延时500ms } } } void exit0() interrupt 0 { delay_ms(1000); LED1=!LED1; } void exit1() interrupt 2 { DC_Motor=!DC_Motor;//开启电机 //delay_ms(DC_MOTOR_RUN_TIME); LED2=!LED2; }
3.3.3运行结果
点阵模块从下往上循环滚动,按K3可以控制LED1灯的亮灭,按K4可以控制直流电机和LED2
灯的亮灭。
以上就是本期补齐的内容,欢迎参考指正,如有不懂,欢迎评论或私信出下期!!!