51单片机学习笔记之中断(外部中断、定时器中断、中断嵌套)
要学习51单片机中断的朋友,拥有这一篇博文就够了,深入浅出,里面包含了寄存器,外部中断、定时器中断、中断嵌套等的讲解,还有代码实战。快一万字,写得不容易,还请大家点赞支持一下,后续持续更新
- (一)寄存器
- 1.什么是寄存器
- 2.寄存器怎么用
- (二)中断
- 1.中断允许寄存器IE
- EX0
- ET0
- EX1
- ET1
- ES
- EA
- 使用方法
- 2.中断优先级寄存器IP
- PS——串行口中断优先级控制位
- PT1——定时器/计数器1中断优先级控制位
- PX1——外部中断1中断优先级控制位
- PT0——定时器/计数器0中断优先级控制位
- PX0——外部中断0中断优先级控制位
- 中断优先级(高到低)
- 3.TCON寄存器
- TF1:片内定时器/计数器T1的溢出中断请求标志位。
- TF0:片内定时器/计数器T0的溢出中断请求标志位。
- IE1:外部中断请求1的中断请求标志位。
- IE0: 外部中断请求0的中断请求标志位。
- IT1:选择外部中断请求1为负跳变触发方式还是电平触发方式。
- IT0:选择外部中断请求0为负跳变触发还是电平触发方式。
- 4.SCON寄存器
- TI:串行口发送中断请求标志位。
- RI:串行口接收中断请求标志位。
- (三)外部中断
- 1.外部中断0,按下开关K3,数码管0变1
- 寄存器配置:
- 完整代码:
- 2.外部中断1,按下开关K4,数码管0变1
- 寄存器配置:
- 完整代码:
- 3.外部中断扩展
- 寄存器配置:
- 完整代码:
- (四)定时器中断
- 1.定时器0
- 寄存器配置:
- 完整代码:
- 2.定时器1
- 寄存器配置:
- 完整代码:
- 3.定时器计数控制数码管0到60
- 寄存器配置:
- 完整代码:
- 4.定时器做的时钟
- 寄存器配置:
- 完整代码:
- (五)中断嵌套
- 1.外部中断嵌套K3,K4
- 寄存器配置:
- 完整代码:
(一)寄存器
要想学习中断那么首先就要了解寄存器,在这里我们学习一下什么是寄存器,寄存器怎么用。
1.什么是寄存器
寄存器是特殊的RAM,特殊功能寄存器是控制单片机硬件的开关(例如IE)或者是指示单片机状态的信号(例如PSW),通过特殊寄存器你就可以方便的控制整个MCU,并且知道当前的MCU的工作状态。
2.寄存器怎么用
AT89S51单片机中的特殊功能寄存器(SFR)的单元地址映射在片内RAM区的80H~FFH区域中,它共有26个,离散地分布在该区域中。用到哪个寄存器就相应配置哪个寄存器即可。寄存器太多就不一一写出来了,用到再去找就好。
(二)中断
单片机的中断是由单片机片内的中断系统来实现的。当中断请求源(简称中断源)发出中断请求时,如果中断请求被允许的话,单片机暂时中止当前正在执行的主程序,转到中断服务程序处理中断服务请求,处理完中断服务请求后,再回到原来被中止的程序之处(断点),继续执行被中断的主程序。
1.中断允许寄存器IE
EX0
外部中断0允许位。EX0=1,允许外部中断0中断;EX0=0,禁止外部中断0中断。当EX0=1( SETB EX0 )时,同时单片机P3.2引脚上出现中断信号时,单片机中断主程序的执行而“飞”往中断服务子程序,执行完后通过中断返回指令RET 动返回主程序。当EX0=0( CLR EX0)时,即使单片机P3.2引脚上出现中断信程序也不会从主程序“飞” 出去执行,因为此时单片机的CPU相当于被“堵上了耳朵”,根本接收不到P3.2引脚上的中断信号,但是这并不表示这个信号不存在。如果单片机的CPU有空查一下TCON中的IE0位,若为1就说明有中断信号出现过。
ET0
T0溢出中断允许位。ET0=1,允许T0中断;ET0=0,禁止T0中断。
EX1
外部中断1允许位。EX1=1,允许外部中断1中断;EX1=0,禁止外部中断1中断。当EX1=1( SETB EX1)时,并且外部P3.3引脚上出现中断信号时,单片机CPU会中断主程序而去执行相应的中断服务子程序;当EX1=0( CLR EX1)时使外部P3.3引脚上即使出现中断信号,单片机的CPU也不能中断主程序转而去行中断服务子程序。
因此,可以这样认为,EX0和EX1是决定CPU能否感觉到外部引脚P3.2P3.3上的中断信号的控制位。
ET1
T1溢出中断允许位。ET1=1,允许T1中断;ET1=0,禁止T1中断。
ES
串行中断允许位。ES=1,允许串行口中断;ES=0,禁止串行口中断。
EA
中断总允许位。EA=1,CPU开放中断;EA=0,CPU禁止所有的中断请求。总允许EA好比一个总开关。EA就相当于每家水管的总闸,如果总闸不开,各个龙头即使开了也不会有水;反过来,如果总闸开了而各个分闸没开也不会有水,所当我们想让P3.2和P3.3引脚上的信号能够中断主程序则必须将EA位设置为0(CLR EA)。
使用方法
(1)整体赋值:IE=0x81;(开启全局中断,打开外部中断0 )。
(2)单独赋值:EA=1;EX0=1;(开启全局中断,打开外部中断0 )。
2.中断优先级寄存器IP
PS——串行口中断优先级控制位
PS=1,串行口中断定义为高优先级中断。
PS=0,串行口中断定义为低优先级中断。
PT1——定时器/计数器1中断优先级控制位
PT1=1,定时器/计数器1中断定义为高优先级中断。
PT1=0,定时器/计数器1中断定义为低优先级中断。
PX1——外部中断1中断优先级控制位
PX1=1,外部中断1定义为高优先级中断。
PX1=0,外部中断1定义为低优先级中断。
PT0——定时器/计数器0中断优先级控制位
PT0=1,定时器/计数器0中断定义为高优先级中断。
PT0=0,定时器/计数器0中断定义为低优先级中断。
PX0——外部中断0中断优先级控制位
PX0=1,外部中断0定义为高优先级中断。
PX0=0,外部中断0定义为低优先级中断。
中断优先级(高到低)
外部中断0
T0溢出中断
外部中断1
T1溢出中断
串行口中断
T2溢出中断(52)
3.TCON寄存器
TF1:片内定时器/计数器T1的溢出中断请求标志位。
当启动T1计数后,定时器/计数器T1从初值开始加1计数,当计数溢出时,由硬件自动为TF1置“1”,向CPU申请中断。CPU响应TF1中断时,TF1标志位由硬件自动清零,TF1也可由软件清零。
TF0:片内定时器/计数器T0的溢出中断请求标志位。
功能与TF1相同。
IE1:外部中断请求1的中断请求标志位。
IE1=0,无中断请求。
IE1=1,外部中断1有中断请求。当CPU响应该中断,转向中断服务程序时,由硬件清“0”IE1。
IE0: 外部中断请求0的中断请求标志位。
IE0=0,无中断请求。
IE0=1,外部中断0有中断请求。当CPU响应该中断,转向中断服务程序时,由硬件清“0”IE0。
IT1:选择外部中断请求1为负跳变触发方式还是电平触发方式。
IT1=0,为电平触发方式,外部中断请求输入信号为低电平有效,并把IE置“1”。转向中断服务程序时,则由硬件自动把IE1清零。
IT1=1,为负跳变触发方式,外部中断请求输入信号电平为从高到低的负跳变有效,,并把IE置“1”。转向中断服务程序时,则由硬件自动把IE1清零。
IT0:选择外部中断请求0为负跳变触发还是电平触发方式。
与IT1相似。
4.SCON寄存器
TI:串行口发送中断请求标志位。
当CPU将1字节的数据写入串行口的发送缓冲器SBUF时,就启动一帧串行数据的发送,每发送完一帧串行数据后,硬件把TI中断请求标志位自动置“1”。CPU响应串行口发送中断时,并不能清除TI标志位,TI标志位必须在中断服务程序中用指令对其清零。
RI:串行口接收中断请求标志位。
在串行口接收完一个串行数据帧,硬件自动使RI中断请求标志位置“1”。CPU在响应串行口接收中断时,RI标志位并不清零,必须在中断服务程序中用指令对RI清零。
(三)外部中断
51单片机的外部中断int0对应的引脚为p3.2,外部中断int1对应的引脚为p3.3。
1.外部中断0,按下开关K3,数码管0变1
寄存器配置:
EA=1;//总中断允许EX0=1;//允许外部中断0IT0=0;//选择外部中断0为电平触发方式
完整代码:
#include<reg51.h>
#define uchar unsigned char
sbit key = P3^2;void delay(unsigned int i)//延时函数
{unsigned int j;for(;i>0;i--)for(j=0;j<333;j++){}
}void main()//主函数
{EA=1;//总中断允许EX0=1;//允许外部中断0IT0=0;//选择外部中断0为电平触发方式while(1)//循环{P0=0x3f;}//P0.0口的Led亮
}
void key_scan() interrupt 0 //外部中断0的中断服务函数
{if(key==0)//判断是否有按键按下{delay(10);//延时去抖if(key==0){P2=0xfe;P0=0x06;while(!key);//等待按键松开P2=0xff;P0=0x3f;}}
}
2.外部中断1,按下开关K4,数码管0变1
寄存器配置:
EA=1;//总中断允许EX1=1;//允许外部中断0IT1=0;//选择外部中断0为电平触发方式
完整代码:
#include<reg51.h>
#define uchar unsigned char
sbit key = P3^3;void delay(unsigned int i)//延时函数
{unsigned int j;for(;i>0;i--)for(j=0;j<333;j++){}
}void main()//主函数
{EA=1;//总中断允许EX1=1;//允许外部中断0IT1=0;//选择外部中断0为电平触发方式while(1)//循环{P0=0x3f;}//P0.0口的Led亮
}
void key_scan() interrupt 1 //外部中断1的中断服务函数
{if(key==0)//判断是否有按键按下{delay(10);//延时去抖if(key==0){P2=0xfe;P0=0x06;while(!key);//等待按键松开P2=0xff;P0=0x3f;}}
}
3.外部中断扩展
寄存器配置:
IT0 = 1;//跳沿触发IT1 = 1;//跳沿触发PX1 = 1;//中断1高于中断0IE = 0x85;/*由低到高:EX1(第3位)=1,EX0 (第0位)= 1,EA (第八位)= 1 IE = 10000101*/
完整代码:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uint i;
void delay(uint xms);
void Int();
void Interrupt0();
void Interrupt1(); void main()
{Int();P2 = 0xfe;
while(1)
{for (i = 0;i < 7;i++){P2 = _crol_(P2, 1);//先左移delay(600);}for (i = 0;i < 7;i++){P2 = _cror_(P2, 1);//再右移delay(600);}}}void Int()
{IT0 = 1;//跳沿触发IT1 = 1;//跳沿触发PX1 = 1;//中断1高于中断0IE = 0x85;/*由低到高:EX1(第3位)=1,EX0 (第0位)= 1,EA (第八位)= 1 IE = 10000101*/
}void delay(uint xms)//AT89C5211.0592MHz
{uint x, y;for (x = xms;x > 0;x--)for (y = 110;y > 0;y--);
}void Interrupt1() interrupt 0
{while (1){P2 = 0x0f;delay(600);P2 = 0xf0;delay(600);}
}
void Interrupt2() interrupt 2/*外部中断1的标号是2!*/
{while (1){P2 = 0xcc;//(11001100)delay(600);P2 = 0x33;delay(600);}}
(四)定时器中断
1.定时器0
寄存器配置:
TMOD = 0x01;TH0 = (65536 - 45872) / 256; // 设置定时器0为工作方式1(M1M0为01)TL0 = (65536 - 45872) % 256; // 装初值11.0592M晶振定时50ms数位45872EA = 1; // 开总中断ET0 = 1; // 开定时器0中断TR0 = 1; // 启动定时器0
完整代码:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit led1 = P2^0;
uchar num = 0;void main()
{TMOD = 0x01;TH0 = (65536 - 45872) / 256; // 设置定时器0为工作方式1(M1M0为01)TL0 = (65536 - 45872) % 256; // 装初值11.0592M晶振定时50ms数位45872EA = 1; // 开总中断ET0 = 1; // 开定时器0中断TR0 = 1; // 启动定时器0while(1){;}
}void T0_time() interrupt 1
{TH0 = (65536 - 45872) / 256;TL0 = (65536 - 45872) % 256;num++;if (num == 20){num = 0;led1 = ~led1;}
}
2.定时器1
寄存器配置:
TMOD = 0x01;TH0 = (65536 - 45872) / 256; // 设置定时器1为工作方式1(M1M0为01)TL0 = (65536 - 45872) % 256; // 装初值11.0592M晶振定时50ms数位45872EA = 1; // 开总中断ET1 = 1; // 开定时器1中断TR1 = 1; // 启动定时器1
完整代码:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit led1 = P2^0;
uchar num = 0;void main()
{TMOD = 0x01;TH0 = (65536 - 45872) / 256; // 设置定时器1为工作方式1(M1M0为01)TL0 = (65536 - 45872) % 256; // 装初值11.0592M晶振定时50ms数位45872EA = 1; // 开总中断ET1 = 1; // 开定时器1中断TR1 = 1; // 启动定时器1while(1){;}
}void T1_time() interrupt 3
{TH0 = (65536 - 45872) / 256;TL0 = (65536 - 45872) % 256;num++;if (num == 20){num = 0;led1 = ~led1;}
}
3.定时器计数控制数码管0到60
寄存器配置:
TMOD=0x11;//写在一起//定时器0//TMOD=0x01;TH0=(65536-45872)/256;TL0=(65536-45872)%256;EA=1;ET0=1;TR0=1;//定时器1//TMOD=0x10;TH1=(65536-45872)/256;TL1=(65536-45872)%256;EA=1;ET1=1;TR1=1;
完整代码:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极数码管编码
uchar num0,num1;
uint ge ,shi;
sbit LSA=P2^2;//74HC138译码器端口
sbit LSB=P2^3;
sbit LSC=P2^4;
void display_time(uint ,uint);
void delay_ms(uint);void main()
{TMOD=0x11;//写在一起//定时器0//TMOD=0x01;TH0=(65536-45872)/256;TL0=(65536-45872)%256;EA=1;ET0=1;TR0=1;//定时器1//TMOD=0x10;TH1=(65536-45872)/256;TL1=(65536-45872)%256;EA=1;ET1=1;TR1=1;while(1){ display_time(ge ,shi);//时间一直显示中}
}void T0_time()interrupt 1 //数码管处理 T0定时器
{TH0=(65536-45872)/256;//每50ms产生一次中断TL0=(65536-45872)%256;//所以每20次中断,个位+1num0++;if(num0==20){num0=0;ge++;if(ge==10){shi++; //时间进位ge=0;}if(shi==6)shi=0; //时间归零}
}void display_time(uint ge ,uint shi)
{LSA=0;LSB=1;LSC=1;P0=table[ge];//送入个位数字delay_ms(5);LSA=1;LSB=1;LSC=1;P0=table[shi];//送入十位数字delay_ms(5);
}
void delay_ms(uint ms)
{uint i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}
4.定时器做的时钟
寄存器配置:
TMOD=0x01;TH0=(65536-45872)/256;TL0=(65536-45872)%256;EA=1;ET0=1;TR0=1;
完整代码:
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴极数码管编码
uchar num;
uint hour_ge,hour_shi,minute_ge, minute_shi,second_ge,second_shi;
sbit LSA=P2^2;//74HC138译码器端口
sbit LSB=P2^3;
sbit LSC=P2^4;
void display_time(uint,uint,uint,uint,uint,uint);
void delay_ms(uint);
void main()
{TMOD=0x01;TH0=(65536-45872)/256;TL0=(65536-45872)%256;EA=1;ET0=1;TR0=1;while(1){ display_time(hour_shi,hour_ge,minute_shi,minute_ge,second_shi,second_ge);//时间一直显示中}
}void T0_time()interrupt 1 //数码管处理 T0定时器
{TH0=(65536-45872)/256;//每50ms产生一次中断TL0=(65536-45872)%256;//所以每20次中断,个位+1num++;if(num==20){num=0;second_ge++;//秒+1}if(second_ge==10){second_ge=0;second_shi++;if(second_shi==6){second_shi=0;minute_ge++;if(minute_ge==10){minute_ge=0;minute_shi++;if(minute_shi==6){minute_shi=0;hour_ge++;if(hour_ge==10){hour_ge=0;hour_shi++;if(hour_shi==2&&hour_ge==4){hour_shi=0;hour_ge=0;}} } }}}}void display_time(uint hour_shi,uint hour_ge,uint minute_shi,uint minute_ge,uint second_shi,uint second_ge)
{LSA=0;LSB=0;LSC=0;//第六个数码管送入second_geP0=table[second_ge];delay_ms(1);LSA=1;LSB=0;LSC=0;//第五个数码管送入second_shiP0=table[second_shi];delay_ms(1);LSA=1;LSB=1;LSC=0;//第四个数码管送入minute_ge P0=table[minute_ge]; delay_ms(1);LSA=0;LSB=0;LSC=1;//第三个数码管送入minute_shi P0=table[minute_shi];delay_ms(1);LSA=0;LSB=1;LSC=1;//第二个数码管送入hour_geP0=table[hour_ge];delay_ms(1);LSA=1;LSB=1;LSC=1;//第一个数码管送入hour_shiP0=table[hour_shi];delay_ms(1);}void delay_ms(uint ms)
{uint i,j;for(i=ms;i>0;i--)for(j=110;j>0;j--);
}
(五)中断嵌套
1.外部中断嵌套K3,K4
寄存器配置:
IT0 = 1;IT1 = 1;PX0 = 1;IE = 0x85;/*由低到高:EX1(第3位)=1,EX0 (第0位)= 1,EA (第八位)= 1 IE = 10000101*/
完整代码:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit LED1 = P2 ^ 0;
sbit LED2 = P2 ^ 1;void Int();
void Interrupt1();
void Interrupt2(); void main()
{Int();while (1);}void Int()
{IT0 = 1;IT1 = 1;PX0 = 1;IE = 0x85;/*由低到高:EX1(第3位)=1,EX0 (第0位)= 1,EA (第八位)= 1 IE = 10000101*/
}void Interrupt1() interrupt 0
{LED1 = ~LED1;}
void Interrupt2() interrupt 2/*外部中断1的标号是2!*/
{LED2 = ~LED2;}
看到最后相信你也应该收获到很多,一起进步吧!
51单片机学习笔记之中断(外部中断、定时器中断、中断嵌套)相关推荐
- AutoLeaders控制组—51单片机学习笔记
文章目录 AutoLeaders控制组-51单片机学习笔记 1.1单片机及开发板介绍 单片机介绍 单片机应用领域 STC89C52单片机 内部结构 开发板介绍 2.1点亮一个Led 新建工程 编程 认 ...
- 51单片机学习笔记2 仿真器的使用及STC89Cxx简介
51单片机学习笔记2 仿真器的使用及STC89Cxx简介) 一.连接步骤 1. 硬件连接 2. 安装软件驱动 3. 检查是否安装成功 二.仿真步骤 1. 打开一个51工程 2. 选择仿真设备 3. S ...
- 51单片机学习笔记-1简介及点灯
51单片机学习笔记 文章目录 51单片机学习笔记 1. 51单片机简介 1.1 安装软件 1.2 单片机简介 2. LED灯 2.1点亮一个LED 2.1.1原理分析 2.1.2 创建工程 2.2LE ...
- [51单片机学习笔记TWO]----蜂鸣器
蜂鸣器音乐播放实验 首先应该了解一下蜂鸣器音乐播放的原理,在这里我只讲一下电磁式蜂鸣器驱动原理(还有一种是压电式蜂鸣器): 电磁式蜂鸣器驱动原理: 蜂鸣器发声原理是电流通过电磁线圈,使电磁圈产生磁场来 ...
- 单片机c语言北航,【下载资料】《51单片机学习笔记》北航版
原标题:[下载资料]<51单片机学习笔记>北航版 如果手机下载有问题,请移步至电脑端,链接:https://forum.mianbaoban.cn/t/topic/36906 内容简介 本 ...
- 51单片机学习笔记5 流水灯实现及蜂鸣器控制
51单片机学习笔记5 流水灯实现及蜂鸣器控制 一.流水灯 1. 硬件电路 2. 代码实现 (1) 点亮一个LED的基本操作 (2) 使用算术左移实现流水灯 (3) 使用库文件左移函数 二.蜂鸣器 1. ...
- 51单片机学习笔记1 简介及开发环境
51单片机学习笔记1 简介及开发环境 一.51单片机 1. STC89C52单片机简介 2. 命名规则 3. 封装 (1)PDIP (2)LQFP (3)PLCC (4)PQFP 二.STC8051结 ...
- AutoLeader控制组——51单片机学习笔记(一)
目录 1.点亮LED灯 1.1LED灯闪烁 1.2控制LED灯按时闪烁: 1.3 LED灯流水灯 1.4二进制点灯 2.独立按键控制LED灯 2.1按键控制LED亮灭 2.2.按键控制灯左右移动 3. ...
- 51单片机学习笔记(郭天祥版)(3)——引脚讲解、数码管静态显示、中断系统(外部中断,定时器中断)...
学习引脚的功能 9引脚 复位管脚,当给2个机器周期(24个时钟振荡周期)的高电平时会复位,单片机正常工作时会给0.5v的低电平 VPD备用电源的输入端,当主电源VCC发生故障降低到某一规定的低电平时, ...
最新文章
- Blender三维建筑场景动画制作学习教程
- 工业红外温度传感器 测温探头在线式4-20mA 变送器红外线非接触式
- 【maven】idea maven slf4j : StackOverflowError
- 华为云 EI 聚焦三大基础研究创新,助力产业智能升级
- C++ Copy Elision
- Taurus入门,这么神奇的性能测试工具不能不知道
- python误差修正模型_如何用格兰杰检验、协整对数据进行分析_格兰杰因果检验...
- 《符号学:原理与推演》(一)符号的构成
- mentohust 使用
- 实时交通仿真平台概要
- ECCV 2020预会议 直播笔记| Cross-Modal Weighting Network for RGB-D Salient Object Detection
- vue 前端仿QQ截图实现Web端自定义截屏(JS版)
- 激光打印机热定影器的组成以及维护
- GoogleEarth二次开发平台指南(1) ---如何将谷歌地球嵌入到自定义的窗体中
- STL教程:C++ STL快速入门
- 网桥调用iptables规则的善后处理
- 怎么把视频中的音乐给快速提取出来
- 查看Linux服务器公网内网IP地址
- 小小破解一下百度MP3的加密URL链接
- SiTime硅晶振相位噪声测量指南