中断系统
1.前言
记录对51单片机中断、定时/计数器的重要知识点以及难点理解,并且举例中断在实际编程中的应用,从而加深对单片机中断、定时/计数器的理解,熟练的使用中断。
2.什么是中断
中断
就是计算机在执行某一程序的过程中,由计算机系统内部或外部的某种原因而
必须终止当前程序的运行
,
先去执行相应的处理程序
,然后再
返回继续执行原程序
。
3.什么是中断系统
实现中断功能的软、硬件系统统称为中断系统。
4.中断的流程
即:
中断请求
、
中断响应
、
中断处理
、
中断返回
5.中断的优先级控制
通常情况下,一个程序中可能会有多个中断,优先级越高的中断优先执行。如果在一个中断的服务过程中,有一个优先级更高的中断插入,则当前中断暂停,前往执行优先级更高的中断。当优先级高的中断执行完毕后再返回继续执行低优先级的中断。
6.中断源
MCS-51共有五个中断源
-
外部中断
INT0
、
INT1
-
定时/计数器
T0
和
T1
的溢出中断 - 串行口的发送和接受中断(只占用一个中断源)
中断源 | 功能 |
---|---|
|
外部中断0请求,由
引脚(P3.2)输入。低电平/负跳变有效,中断请求标志为IE0 |
|
外部中断1请求,由
引脚(P3.3)输入。低电平/负跳变有效,中断请求标志为IE1 |
|
定时/计数器0溢出中断请求,中断标志位为
|
|
定时/计数器1溢出中断请求,中断标志位为
|
|
串行口中断请求,中断请求标志位
或
|
外部中断
从单片机外部引脚
INT0
和
INT1
输入中断请求信号的中断。
外部中断的触发方式有两种
电平触发
IT0 =0
和
跳变触发(边沿)
IT0 = 1
,可以通过定时/计数器控制寄存器
TCON
编程选择。
7.与中断有关的特殊功能寄存器
与中断有关的特殊功能寄存器一共有4个。
-
定时/计数器控制寄存器(
TCON
)、 -
串行口控制寄存器(
SCON
)、 -
中断允许控制寄存器(
IE
)、 -
中断优先级控制寄存器(
IP
)
7.1.定时/计数器控制寄存器
TCON
TCON
作用
:
-
控制定时/计数器
T0
和
T1
的溢出中断 -
控制外部中断的触发方式.由
IT0
和
IT1
控制 - 锁存外部中断请求标志位
位地址 | 位定义 | 功能 |
---|---|---|
88H | IT0 |
选择外部中断0的中断触发方式。由软件控制。
。
|
89H | IE0 |
选择外部中断1的中断触发方式。功能与
相似 |
8AH |
7.2.串行口控制寄存器
SCON
SCON
串行口的接收发送数据中断请求标志位
(
RI
和
TI
)
位定义 | 功能 |
---|---|
|
串行口发送中断请求标志位。CPU每发送一帧数据,硬件置位1(
),但是中断被响应时,需要在中断服务程序中通过软件对
清零 |
|
串行口接受中断请求标志位。每接收一帧数据,硬件置位1(
),但是中断被响应时,一样需要在中断服务程序中通过软件对
清零 |
串行口中断不能由硬件自动清除中断请求标志位,需要用户通过软件进行控制清零。
7.3.中断允许控制寄存器
IE
IE
IE
是控制中断的开关,通过对
IE
的清0和置1操作来控制中断的屏蔽和开放。
中断允许控制寄存器
IE
对中断的开放与屏蔽实现两级控制,存在一个总的中断控制位
EA
位定义 | 功能 |
---|---|
|
总中断允许控制位。当
时,不允许任何中断请求。 |
|
串行口中断控制位。当
时,不允许串行口中断;当
且
时,允许串行口中断。 |
|
定时/计数器1中断允许控制位。当
时,屏蔽
的溢出中断;当EA=1且
时,允许T1溢出中断 |
|
定时/计数器0中断允许控制位。功能与
相同。 |
|
外部中断1的中断允许控制位。当
时,屏蔽外部中断1的中断请求;当
且
时,允许外部中断1的中断请求 |
|
外部中断0的中断允许控制位。功能与
相同 |
若某个中断源被允许,出来
IE
对应位置1外,还需要总中断控制位
EA
置1。
实例
:若允许片内两个定时/计数器中断,禁止其他中断源的中断请求,尝试编写出设置IE的响应指令
#include <reg51.h>
EX0 = 0; // 禁止外部中断0
EX1 = 0; // 禁止外部中断1
ES = 0; // 禁止串行口中断
ET0 = 1; // 允许定时/计数器0中断
ET1 = 1; // 允许定时/计数器1中断
EA = 1; // 总中断控制器打开
7.4.中断优先级控制寄存器
IP
IP
位定义 | 功能 |
---|---|
|
串行口中断优先级控制位。PS=1,串行口中断为高优先级;PS=0,为低优先级。 |
|
定时/计数器1中断优先级控制位。当
时,T1溢出中断为低优先级;当
时,T1溢出中断为高优先级。 |
|
定时/计数器0中断优先级控制位。当
时,T0溢出中断为低优先级;当
时,T0溢出中断为高优先级。 |
|
外部中断1的中断优先级控制位。当
时,外部中断1为低优先级;当
时,外部中断1为高优先级。 |
|
外部中断0的中断优先级控制位。当
时,外部中断0为低优先级;当
时,外部中断0为高优先级。 |
同级内第二优先级的次序
:
外部中断0
>
T0溢出中断
>
外部中断1
>
T1溢出中断
>
串行口中断
8.中断系统在实际编程中的应用
8.1.实例一:中断的初始化
#include <reg51.h>
void init() // 中断的初始化函数
{
EA = 1; // 总中断控制位
ES = 1; // 串行口中断允许
EX0 = 1; // 外部中断0允许
EX1 = 1; // 外部中断1允许
ET0 = 1; // 定时/计数器0中断允许
ET1 = 1; // 定时/计数器1中断允许
IT0 = 1; // 选择外部中断0的触发方式
IT1 = 1; // 选择外部中断1的触发方式
}
例1
:假设允许外部中断0和1中断,并设定外部中断0为高级中断,外部中断1为低级中断,外部中断0为下降沿触发方式,外部中断1为电平触发方式。试写出该程序的中断初始化程序。
#include <reg51.h>
void init() //
{
EA = 1; 打开中断控制
EX0 = 1; 允许外部中断0
EX1 = 1; 允许外部中断1
IT0 = 1; 外部中断1采取边沿触发方式
IT1 = 0; 外部中断0采取电平触发方式
PX0 = 1; 外部中断0为高优先级
PX1 = 0; 外部中断1为低优先级
}
8.2.实例二:利用中断控制LED闪烁形式
要求
:
用80C51单片机控制8个LED灯,在外部中断0输入引脚(P3.2)接一个开关K1。要求将外部中断0设置为下降沿触发,程序启动是8个LED以跑马灯的形式交替闪烁。每按一次开关K1,使引脚接地,产生一个下降沿触发的外部中断请求。在中断服务程序中,8个LED高四位和低四位交替闪烁5次,然后中断返回,8个LED继续以跑马灯形式闪烁。
采用
Protues
+
Keil
仿真
元器件
- 单片机:
80C51
*1- 开关按钮:
Button
*1- 电阻:
MINRES470K
*1- LED:
LED-BLUE
*8
仿真图
代码
#include<reg52.h>
unsigned char code table[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0x00,0xff}; // 控制P2端口的状态
unsigned char i,j,k,num;
void delay() // 延时函数
{
for(i = 0;i<100;i++)
{
for(j=0;j<200;j++)
;
}
}
void init() // 中断的初始化
{
EA = 1; // 打开总中断控制
EX0 = 1; // 允许外部中断0
IT0 = 1; // 外部中断为下降沿触发方式
}
void main()
{
init();
while(1)
{
for(num =0;num<10;num++)
{
P2 = table[num];
delay();
}
}
}
void int0() interrupt 0 // 中断服务程序
{
for(k = 0;k<5;k++){
P2 = 0xf0;
delay();
P2=0x0f;
delay();
}
}
8.3.实例三:多级中断控制LED不形式闪烁
要求
:在
例2
的基础上,在外部中断1输入引脚(P3.3)接一只按钮开关K2。当按下K1时,外部中断0下降沿触发方式触发,进入外部中断0服务程序,上下4个灯交替闪烁;此时按下K2,外部中断1下降沿触发方式触发,进入外部中断1服务程序,8个灯交替闪烁。当外部中断1响应完毕后,返回继续响应外部中断0,直到外部中断0响应完毕,返回执行主程序。
首先我们分析一波中断初始化函数
-
两个外部中断0和1。外部中断0的服务程序为上下4灯交替闪烁,外部中断1的服务程序为8灯闪烁。即
EA = 1; EX0 = 1; EX1 = 1;
-
优先级:外部中断1 > 外部中断0 即
PX1 = 1; PX0 = 0;
-
触发方式:都为下降沿触发。即
IT0 = 1; IT1 = 1;
这样我们的中断初始化程序基本完成
void init()
{
EA = 1;
EX0 = 1; EX1 = 1;
PX0 = 0; PX1 = 1;
IT0 = 1; IT1 = 1;
}
其次我们再捯饬一下主程序
void main()
{
init();
while(1)
{
for(num =0;num<10;num++)
{
P2 = table[num];
delay();
}
}
}
另外我们再搞一下外部中断0的服务程序
void int0() interrupt 0
{
for(k = 0;k<5;k++)
{
P2 = 0xf0;
delay();
P2=0x0f;
delay();
}
}
最后我们再他喵的弄一下外部中断1的服务程序
void int1() interrupt 2 // 外部中断1服务程序
{
for(l = 0;l < 5; l++)
{
P2 = 0x00;
delay();
P2 = 0xff;
delay();
}
}
完整代码
#include<reg52.h>
unsigned char code table[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f, 0x00, 0xff}; // 控制P2端口的状态
unsigned char i, j, k, l, num;
void delay() // 延时函数
{
for(i = 0; i < 200; i++)
{
for(j = 0; j < 200; j++)
;
}
}
void init() // 中断的初始化
{
EA = 1;
EX0 = 1; EX1 = 1;
PX0 = 0; PX1 = 1;
IT0 = 1; IT1 = 1;
}
void main()
{
init();
while(1)
{
for(num = 0; num < 10; num++)
{
P2 = table[num];
delay();
}
}
}
void int0() interrupt 0 // 外部中断0中断服务程序
{
EX0 = 0;
for(k = 0; k < 5; k++)
{
P2 = 0xf0;
delay();
P2 = 0x0f;
delay();
EX0 = 1;
}
}
void int1() interrupt 2 // 外部中断1服务程序
{
for(l = 0;l < 5; l++)
{
P2 = 0x00;
delay();
P2 = 0xff;
delay();
}
}
仿真图
文章来源:
中断系统