51之中断
中断的概念
中断发生
CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理
中断响应和中断服务
CPU暂时中断当前的工作,转去处理事件B
中断返回
待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A
这一过程称为中断
二.中断过程示意图
三.MCS51中断系统的结构
MCS51的中断系统有5个中断源(8052有 6个) ,2个优先级,可实现二级中断嵌套
中断编号 | 中断名 | 中断源 |
---|---|---|
0 | 外部中断0 | IE0(P3.2) |
1 | 定时器0溢出中断 | TF0 |
2 | 外部中断1 | IE1(P3.3) |
3 | 定时器1溢出中断 | TF1 |
4 | 串行口中断 | RI |
四.中断寄存器
单片机有10个寄存器主要与中断程序的书写控制有关
中断允许控制寄存器IE
定时器控制寄存器TCON
串口控制寄存器SCON
中断优先控制寄存器IP
定时器工作方式控制寄存器TMOD
定时器初值赋予寄存器(TH0/TH1,TL0/TL1)
五.部分寄存器详解
1.中断允许控制寄存器(IE)
EX0:外部中断0允许位;
ET0:定时/计数器T0中断允许位;
EX1:外部中断1允许位;
ET1:定时/计数器T1中断允许位;
ES :串行口中断允许位;
EA :CPU中断允许(总允许)位。
2.定时器/计数器控制寄存器控制寄存器(TCON)
IT0:外部中断0触发方式控制位
当IT0=0时,为电平触发方式(低电平有效)
当IT0=1时,为边沿触发方式(下降沿有效)
IE0:外部中断0中断请求标志位
IT1:外部中断1触发方式控制位
IE1:外部中断1中断请求标志位
TF0:定时/计数器T0溢出中断请求标志位
TF1:定时/计数器T1溢出中断请求标志位
3.串行口控制寄存器(SCON)
RI:串行口接收中断标志位。当允许串行口接收数据时,每接收完一个串行帧,由硬件置位RI。注意,RI必须由软件清除。
TI:串行口发送中断标志位。当CPU将一个发送数据写入串行口发送缓冲器时,就启动了发送过程。每发送完一个串行帧,由硬件置位TI。CPU响应中断时,不能自动清除TI,TI必须由软件清除。
4.中断优先级控制寄存器(IP)
PX0:外部中断0优先级设定位
PT0:定时/计数器T0优先级设定位
PX1:外部中断0优先级设定位
PT1:定时/计数器T1优先级设定位
PS :串行口优先级设定位
PT2:定时/计数器T2优先级设定位
六.中断响应条件
中断源有中断请求
此中断源的中断允许位为1
开中断(即EA=1)
80C51的定时/计数器的结构
定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。
TMOD : 控制定时器的工作方式。8个bit,高四位 bit 控制 T1,、低四位 bit 控制 T0。因为定时器有4种工作方式;TMOD = 0x00(工作方式0),TMOD = 0x01(工作方式0),TMOD = 0x02(工作方式2),TMOD = 0x03(工作方式3)。以上是控制低4位的,所以是对应着T0。
TR0:T0定时器 使能开关,TR0 = 1,开始工作; =0停止工作。
ET0:T0定时器中断开关,定时时间一到,就会跑去中断程序。ET0=1,中断使能,=0失能。
EA : 中断总开关,你可以想象成电路的总电闸,EA=1,中断使能; =0,中断失能。
TH0,TL0 : T0定时器计数寄存器,组成16位的计数,0x0000--0xFFFF(0--65535),只要TH0TL0=0xFFFF(65535),程序就会跑去中断程序,在中断程序中,我们要重新给TH0,TL0重新赋值的。
假如说,我们定时50毫秒,TH0,TL0对应着什么值呢? 上面我们说了,TH0,TL0,组成的16位计数器计数范围是 0---65535 。50ms = 50 000us,我们只要让 TH0 TL0 从(65535 - 50000)开始计数,TH0,TL0就会不停的+1,直到TH0,TL0=65535,就是计数了50000次,时间就是过了50ms。我们只要在中断程序里面,重新赋值给TH0,TL0=(65535 - 50000),定时器就会不停得每50ms中断一次了。
void Timer0() interrupt 1 using 1
Timer0 是函数名,随便取的
interrupt xx using y
跟在interrupt 后面的xx 值得是中断号,就是说这个函数对应第几个中断端口,一般在51中
0 外部中断0
1 定时器0
2 外部中断1
3 定时器1
4 串行中断
实际上编译的时候就是把你这个函数的入口地址方到这个对应中断的跳转地址
using y 这个y是说这个中断函数使用的那个寄存器组,51里面一般有4组 r0 -- r7寄存器,一共有32个,如果你的终端函数和别的程序用的不是同一个寄存器组则进入中断的时候就不会将寄存器组压入堆栈返回时也不会谈出来节省代码和时间
外部1中断:
/**************************************************************************************
* 外部中断1实验 *
实现现象:下载程序后,按照光盘内操作视频接线,操作K4按键使LED1(D11)状态取反。
注意事项:无。
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k4=P3^3; //定义按键K4
sbit led=P2^0; //定义P20口是led
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : Int1Init()
* 函数功能 : 设置外部中断1
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int1Init()
{
//设置INT1
IT1=1;//跳变沿出发方式(下降沿)
EX1=1;//打开INT1的中断允许。
EA=1;//打开总中断
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Int1Init(); // 设置外部中断1
while(1);
}
/*******************************************************************************
* 函 数 名 : Int1() interrupt 2
* 函数功能 : 外部中断0的中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int1() interrupt 2 //外部中断1的中断函数
{
delay(1000); //延时消抖
if(k4==0)
{
led=~led;
}
}
定时器0中断:
/**************************************************************************************
* 定时器0中断实验 *
实现现象:下载程序后,按照光盘内视频操作接线,D11小灯循环点亮1秒,熄灭1秒。使用单片机内部定时器可以实现准确延时。
注意事项:无。
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit led=P2^0; //定义P20口是led
/*******************************************************************************
* 函 数 名 : Timer0Init
* 函数功能 : 定时器0初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Timer0Init(); //定时器0初始化
while(1);
}
/*******************************************************************************
* 函 数 名 : void Timer0() interrupt 1
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer0() interrupt 1
{
static u16 i;
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
led=~led;
}
}
1 #include <reg52.h>
2 #include <intrins.h>
3 typedef unsigned char uchar;
4 sbit LED = P1 ^ 0;
5 uchar count = 0;
6 void Interrupt() interrupt 1
7 {
8 TH0 = (65536 - 46080) / 256; //触发中断时重新装填计时
9 TL0 = (65536 - 46080) % 256;
10 if (count == 20)
11 {
12 LED = ~LED;
13 count = 0;
14 }
15 else ++count;
16 }
17 void main(void)
18 {
19 LED = 0xff; //初始化LED
20 TMOD = 0x01; //初始化TMOD,定时器0,方式1
21 TH0 = (65536 - 46080) / 256; //装填计数
22 TL0 = (65536 - 46080) % 256;
23 EA = 1; //开放所有中断
24 ET0 = 1; //开放定时器0中断控制位
25 TR0 = 1; //定时器0开始计时
26 while(1)
27 {
28 _nop_();
29 }
30 }
#include<reg52.h>
sbit LED0=P1^0;
unsigned char i;
void main()
{
TMOD=0X01; //设置使用定时器0,16位的定时/计数寄存器
TL0=0xD8; //低八位赋初值
TH0=0XF0; //高八位赋初值
ET0=1; //开启定时器0中断
TR0=1; //运行定时器0
EA=1; //开启中断总开关
while(1);
}
void Delay(void) interrupt 1 using 0
{
i++;
TR0=0; //进入中断函数时,关闭定时器
TL0=0XD8; //重新赋初值
TH0=0XF0;
if(i==20) //因为10ms一次处罚看不出明显结果,所以让20次触发才让灯变一次
{
LED0=~LED0;
}
TR0=1; //重新开启定时器
}
定时器1中断:
/**************************************************************************************
* 定时器1中断实验 *
实现现象:下载程序后,按照视频操作正确接线,静态数码管间隔一秒循环显示0-F。使用单片机内部定时器可以实现准确延时。
注意事项:
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u8 n=0;
/*******************************************************************************
* 函 数 名 : Timer1Init
* 函数功能 : 定时器1初始化
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1Init()
{
TMOD|=0X10;//选择为定时器1模式,工作方式1,仅用TR1打开启动。
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
ET1=1;//打开定时器1中断允许
EA=1;//打开总中断
TR1=1;//打开定时器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Timer1Init(); //定时器1初始化
while(1);
}
/*******************************************************************************
* 函 数 名 : void Timer1() interrupt 3
* 函数功能 : 定时器0中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Timer1() interrupt 3
{
static u16 i;
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
i++;
if(i==1000)
{
i=0;
P0=~smgduan[n++];
if(n==16)n=0;
}
}
外部0中断:
/**************************************************************************************
* 外部中断0实验 *
实现现象:下载程序后,按照光盘内操作视频接线,操作K3按键使LED1(D11)状态取反
注意事项:无。
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit k3=P3^2; //定义按键K3
sbit led=P2^0; //定义P20口是led
/*******************************************************************************
* 函 数 名 : delay
* 函数功能 : 延时函数,i=1时,大约延时10us
*******************************************************************************/
void delay(u16 i)
{
while(i--);
}
/*******************************************************************************
* 函 数 名 : Int1Init()
* 函数功能 : 设置外部中断1
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0Init()
{
//设置INT0
IT0=1;//跳变沿出发方式(下降沿)
EX0=1;//打开INT0的中断允许。
EA=1;//打开总中断
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
Int0Init(); // 设置外部中断0
while(1);
}
/*******************************************************************************
* 函 数 名 : Int0() interrupt 0
* 函数功能 : 外部中断0的中断函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void Int0() interrupt 0 //外部中断0的中断函数
{
delay(1000); //延时消抖
if(k3==0)
{
led=~led;
}
}
上一篇: php制作圆形用户头像方法
下一篇: STM32CUBEMX HAL库 趟坑记