单片机之中断篇

目录

1、中断的概念

2、中断控制系统

2.1 中断系统的结构

2.2 中断控制

3、中断处理过程

4、中断编程及应用


1、中断的概念

日常生活的中断现象举例

中断是指在突发事件到来时先中止当前正在进行的工作,转而去处理突发事件。待处理完成后,再返回到原先被中止的工作处,继续进行随后的工作。

中断的一般概念

中断响应过程:由中断管理系统处理突发事件的过程;

中断源:中断管理系统能够处理的突发事件;

中断请求:中断源向CPU提出的处理请求;

中断函数:针对中断源和中断请求提供的服务函数;

中断嵌套:在中断服务过程中执行更高级别的中断服务。

中断过程与调用一般函数过程的相似性: 两者都需要保护断点,都可实现多级嵌套等。

中断过程与调用一般函数过程的差异性:

1、前者是程序设计者事先安排的(断点位置是明确的),而后者却是系统根据工作环境随机决定的(断点位置是随机的)。

2、主函数与一般函数之间具有主从关系,而主函数与中断函数之间则是平行关系(中断函数只能被系统调用);

3、一般函数调用是纯粹软件处理过程,而中断函数调用却是需要软、硬件配合才能完成的过程。

中断实现的功能

1分时操作CPU可以使多个外设同时工作,并分时为各外设提供服务,从而大大提高了CPU的利用率和输入/输出的速度。

2实时处理:当计算机用于实时控制时,请求CPU提供服务是随机发生的。有了中断系统,CPU就可以立即响应并加以处理。

3故障处理:当计算机运行中出现如电源断电、存储器校验出错、运算溢出等错误时,CPU可及时转去执行故障处理程序,减小或消除故障产生的影响。

实例1 单片机开关状态检测

要求:若有按键压下→D1状态反转。

利用查询法编程如下:

#include<reg51.h>
sbit p1_0=P1^0;
sbit p3_2=P3^2;
main(){
	p1_0=0;
	while(1){
		if(p3_2==0)p1_0=!p1_0;
	}
}

利用中断法编程如下:

#include<reg51.h>
sbit p1_0=P1^0;
int0_srv() interrupt 0{
	p1_0=!p1_0;
}
main(){
	IT0=1;
	IE=0x81;
	while(1);
}

运行结果如下:

2、中断控制系统

2.1 中断系统的结构

1、中断源

中断源数量和种类越多,MCU处理突发事件的能力就越强。

80C51单片机共有5种中断源。

2、中断请求标志

当中断信号出现时,单片机中某些寄存器位(中断请求标志位)可被硬件置1

CPU通过定期查看中断请求标志位是否为1,便可知道有无中断请求。

2.2 中断控制

中断系统的组成

中断信号分别沿5条水平路径由左向右进行传送。

其中,TCONSCONIEIP是相关SFR

1TCON寄存器

定时/计数器的控制寄存器Timer/Counter Control Register字节地址为88H可位寻址。

注意 51单片机复位后,TCON初值为0——默认没有上述中断请求,默认采用电平触发方式。

2SCON寄存器

串口控制寄存器(Serial control register),字节地址为98H,可位寻址。

注意TI和RI虽然是2个中断请求标志位,但在SCON之后经或门电路合成为1个信息,统一接受中断管理。

3IE寄存器

中断允许寄存器(Interrupt Enable Register),字节地址为A8H,可位寻址。

注意禁止中断并不能阻止中断请求标志值的硬件刷新;

单片机复位后,IE的初值为0——默认为整体禁止中断。

4IP 寄存器

中断优先级寄存器(Interrupt Priority Registers),字节地址为B8H,可位寻址。

优先级原则:

1)高级中断请求可以打断正在执行的低级中断;

2)同级或低级中断请求不能打断正在执行的中断;

3)同级中断源同时提出请求时按自然优先级响应:

     INT0→ T0 → INT1→T1→TI/RI

4)单片机复位时,IP初值为0——默认所有中断源均为低级中断。

中断嵌套演示

功能:

Ø LED0 代表主函数的功能;
Ø K0 产生 INT0 中断请求,调用 LED1 显示功能;
Ø K1 产生 INT1 中断请求,调用 LED2 显示功能;
Ø 设置 INT1 为高级中断, INT0 为低级中断;
Ø 高级中断运行时,若有低级中断请求,则 D1 点亮;高级中断结束后,低级中断才能运行。
#include"reg51.h"

char led_mod[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示字模
sbit D1=P3^0;

void delay(unsigned int time){  //延时
	unsigned char j ;
	for(j=255;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=0;P1=P2=0x40;  //输出初值
	IE=0x85;  //开中断
	while(1){
		for(i=0;i<=9;i++){ //字 符0-9无限循环
			P0=led_mod[i];
			delay(35000);
}}}

仿真运行图如下:

中断标志汇总

中断管理寄存器汇总

3、中断处理过程

中断处理包括中断请求、中断响应、中断服务、中断返回等环节。

1、中断响应

  CPU响应中断的基本条件为:
(1)有中断源发出中断请求;
(2
)中断总允许位EA=1,即CPU开中断;
(3
)申请中断的中断源的中断允许位为1

CPU响应中断后的操作过程:
1.中断优先级查询,阻止后来的同级或低级中断请求。
2.保护断点,即把程序计数器PC的内容压入堆栈保存。
3.清除中断请求标志位。
4.调用中断函数并开始运行。
5.返回断点继续运行。
注意除中断函数运行是软件方式外,其余中断处理过程都是由单片机硬件自动完成的。


2、响应时间
Ø从查询中断请求标志到执行中断函数第一条语句所经历的时间,称为中断响应时间。
ØCPU在每个机器周期的S6期间查询每个中断请求的标志位。
Ø中断响应时间 = 1个查询机器周期 + 2个调用中断函数周期= 3个机器周期,这也是对中断请求做出响应所需的最短时间。


3、中断撤销
1.定时/计数器中断:硬件自动撤销
2.外部中断:脉冲触发:自动
3.电平触发:外加电路
4.串口中断:软件撤销


4、中断服务函数
C51中断函数的声明格式:
void  函数名
(void)   interrupt n [using m]
interrupt
n,表示是关于中断源n的中断服务函数;
using m,表示该中断函数将使用第m组工作寄存器。缺省为当前工作寄存器组。
注意1、中断服务函数既没有返回值,也没有调用参数; 2、中断服务函数只能由系统调用,不能被其他函数调用。

4、中断编程及应用

重新认识实例1的程序

#include<reg51.h>
sbit p1_0=P1^0;
int0_srv() interrupt 0{
	p1_0=!p1_0;
}
main(){
	IT0=1;
	IE=0x81;
	while(1);
}
 

注意中断允许设置也可采用位变量实现,即EX0=1EA=1

实例2  将第4章实例3改用中断方式实现

问题:

查询法需占用大量CPU机时,如何降低按键检测开销?

中断法——有键闭合时才检测键盘(获取闭合键号)

硬件更改

增加一个4输入与门器件U3→行线分接输入端,输出端接P3.2INT0)②键盘连线改接在P2

软件更改

①主函数中进行中断初始化,中断函数中查找闭合键号并刷新LED显示

每次中断返回前都应将列电平置为全低,行电平置为全高,为下次中断做准备 。

#include<reg51.h>

char led_mod[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//1ed字模
                0x7f,0x6f,0x77,0x7c,0x58,0x5e,0x79,0x71};
char key_buf[]={0xee,0xde,0xbe,0x7e,0xed,0xdd,0xbd,0x7d, //键值
                0xeb,0xdb,0xbb,0x7b,0xe7,0xd7,0xb7,0x77};
void getKey() interrupt 0{  //中 断函数
	char key_scan[]={0xef,0xdf,0xbf,0x7f}; //键扫描码
	char i=0,j=0;
	for(i=0;i<4;i++){
		P2= key_scan[i];  //输出扫描码
		for(j=0;j<16;j++){
			if(key_buf[j]==P2){ //读键值,并判断键号
				P0=led_mod[j]; //显示闭合键键号”
				break;
			}
		}
	}
	P2=0x0f;  //为下次中断做准备
}
void main(void){
	P0=0x00;  //开机黑屏
	IT0=1;  //脉冲触发
	EX0=1;  //INT0允许
	EA=1;  //总中断允许
	P2 = 0x0f;  //为首次中断做准备,列线全为0,行线全为1
	while(1);  //模拟其他程序功能
}

仿真运行图如下:

实例3  将第4章实例2改用中断方式实现

问题:当CPU运行于LED循环环节时,将因不能及时检测按键状态,而使按键操作不灵敏。

硬件改动:增加一只4输入与门电路,使按键闭合电平作为外部中断信号。

软件改动:将标志位修改功能放在中断函数中进行。

#include<reg51.h>

char led[]={0xfe,0xfd,0xfb,0xf7};//LED花样数据
bit dir=0,run=0; //全局变量
void delay (unsigned int time);  //键控中断函数

key() interrupt 0 {
	switch(P0 & 0x0f){   //修改标志位状态
	case 0x0e:run=1;break;
	case 0x0d:run=0,dir=0;break;
	case 0x0b:dir=1;break;
	case 0x07:dir=0;break;
}}
void main(){ 
	char i;
	IT0=1;EX0=1;EA=1;//边沿触发、INT0允许、 总中断允许
	while(1){
		if(run)
			if(dir) //若run=dir=1,自上而下流动
				for(i=0;i<=3;i++){
					P2=led[i];
					delay(200);
				}
			else  //若run=1,dir=0, 自下而上流动
			 for(i=3;i>=0;i--) {
					P2=led[i];
					delay(200);
			  }
		else P2=0xff;  //若run=0,灯全灭
}}

void delay(unsigned int time){
	unsigned int j = 0;
	for(;time>0;time--)
		for(j=0;j<125;j++);
}

运行效果——按键动作灵敏度明显增强


本篇小结
1、中断是指在突发事件到来时先中止当前正在进行的工作,转而去处理突发事件。待处理完成后,再返回到原先被中止的工作处,继续进行随后的工作。
2、中断的核心问题包括,
51单片机的中断源、中断控制寄存器、中断处理过程。
3、
C51中断函数的声明格式为:void 函数名 (void) interrupt n [using m]

猜你喜欢

转载自blog.csdn.net/qq_45385706/article/details/112104779