51单片机入门-2-中断与定时
前言
自学笔记,没有历史知识铺垫(省略百度部分)了解51单片机的中断与定时
一、中断基础
1.中断同级优先级
2.中断条件
- 中断源: 有段请求(如
INT0#/INT1#/T0/T1/代码请求
等)- 中断源中断允许位: 1 (相当于子开关,如
EX0/EX1/ET0/ET1/ES/EADC/ELVD
等)- CPU开启中断
EA
位:1 (相当于总开关)
3.中断程序执行原理图
低优先级中断可以被高优先级打断
高优先级中断不能被低优先级中断打断
4.定时器计数与时间换算公式
t=(1/晶振频率)x(一个机器周期晶振震荡周期)x(定时器数值)
其中一个机器周期晶振震荡周期为12
定时器数值意思为定时器需要运行的数值,注意定时器16位最大记录65536
如
晶振频率选用12MHz
则每次计数时间约为(1/12000000)*12*1=0.000001秒
即1微秒,
要使计数时间为1ms,则定时器数值位0.001/(1/12000000)*12=
1000,则计数初始值为65535-1000
要使计数时间为10ms,则定时器数值位0.01/(1/12000000)*12=
10000,则计数初始值为65535-10000
要使计数时间为50ms,则定时器数值位0.05/(1/12000000)*12=
50000,则计数初始值为65535-50000
当晶振频率选用11.0592MHz
则每次计数时间约为(1/11059200)*12*1=0.000001085秒
即1.085微秒,
要使计数时间为1ms,则定时器数值位0.001/(1/11059200)*12=
922,则计数初始值为65535-922
要使计数时间为10ms,则定时器数值位0.01/(1/11059200)*12=
9216,则计数初始值为65535-9216
要使计数时间为50ms,则定时器数值位0.05/(1/11059200)*12=
46080,则计数初始值为65535-46080
二、中断相关寄存器
针对于TMOD/IE等名词,并不是针对单片机的引脚,而是单片机中特殊寄存器的命名规则
官方文档93页
1.中断相关寄存器列表
IE
中断允许寄存器(可寻址)IE2
中断允许寄存器2(不可寻址)IP
中断优先级控制寄存器(可寻址)TCON
定时器控制寄存器(可寻址)TMOD
工作方式控制寄存器 (不可寻址)T2MOD
工作方式控制寄存器 (不可寻址)SCON
串行口控制寄存器(可寻址)PSW
程序状态字(可寻址)PCON
电源控制器及波特率选择寄存器(可寻址)ADC_CONTR
AD转换控制寄存器(可寻址)
2. 中断功能的开关 – IE 中断允许寄存器
该寄存器主要作用是控制单片机的中断是否允许启用
如下每一位都表示中断允许控制位
EA
该位用于控制整个单片机的中断功能是否开启,总开关概念
- 设置为0表示禁止单片机开启所有中断功能
- 设置为1 表示允许单片机开启任意中断功能
EX0
该位用于控制单片机INT0引脚是否转为外部中断0功能(不开启时该引脚默认为普通IO功能)
- 设置为0 不开启该引脚的外部中断功能,使用默认的IO功能
- 设置为1 开启该引脚的外部中断功能(IO功能相应的会被关闭)
EX1
该位用于控制单片机INT1引脚是否转为外部中断1功能(不开启时该引脚默认为普通IO功能)
- 设置为0 不开启该引脚的外部中断功能,使用默认的IO功能
- 设置为1 开启该引脚的外部中断功能(IO功能相应的会被关闭)
ET0
该位用于控制单片机开启定时器/计数器0的中断功能
问题:开启时影响会单片机哪些引脚的功能发生转换?
- 设置为0 不开启定时器/计数器0的中断功能
- 设置为1 开启定时器/计数器0的中断功能
ET1
该位用于控制单片机开启定时器/计数器1的中断功能
- 设置为0 不开启定时器/计数器1的中断功能
- 设置为1 开启定时器/计数器1的中断功能
ES
串行中断允许控制位 该位控制串行中断的开关(待了解)
- 设置为0 关闭串行中断功能
- 设置为1 开启串行中断功能
EADC
AD转换中断允许控制位(待了解)
ELVD
低压检测中断允许控制位(待了解)
3. 中断/定时器/计数器的通用控制 – TCON 中断/定时器/计数器通用控制寄存器
该寄存器用于定时器/计数器的控制
TF0
计数器0 溢出标识位
TF1
计数器1 溢出标识位
TR0
定时器/计数器0 运行控制位
- 设置为0 停止定时器/计数器工作
- 设置为1 启动定时器/计数器工作
TR1
定时器/计数器1 运行控制位
- 设置为0 停止定时器/计数器工作
- 设置为1 启动定时器/计数器工作
IE0
外部中断请求0 标识位 (当CPU采集到INT0 出现请求中断时,自动置为1,中断服务结束后自动置为0)
IE1
外部中断请求1 标识位 (当CPU采集到INT0 出现请求中断时,自动置为1,中断服务结束后自动置为0)
IT0
外部中断请求0 控制位
- 设置为0 表示低电平方式触发 外部中断0
- 设置为1 表示下降沿方式触发 外部中断0
IT1
外部中断请求1 控制位
- 设置为0 表示低电平方式触发 外部中断1
- 设置为1 表示下降沿方式触发 外部中断1
4. 定时/计数器工作方式的配置 – TMOD工作方式控制寄存器
该寄存器用于定时器/计数器工作方式的配置
高4位 控制定时器/计数器1
GATE
定时器/计数器1 的 门控位
- 设置为0 表示用
TR1
即可控制 定时器/计数器1 的开启与禁止- 设置为1 表示需要用
TR1和INT1#
一起才能控制 定时器/计数器1 的开启与禁止
C/T
定时器/计数器1 具体功能为计数还是定时
- 设置为0 表示定时功能 使用TH和TL可以设置初始数值,8位定时器读取TH和TL最大为65535时触发中断
- 设置为1 表示计数功能 由外部引脚 T1做计数脉冲
M1 M0
控制定时器/计数器工作模式
低4位 控制定时器/计数器0
GATE
定时器/计数器0 的 门控位
- 设置为0 表示用
TR0
即可控制 定时器/计数器0 的开启与禁止- 设置为1 表示需要用
TR0和INT0#
一起才能控制 定时器/计数器0 的开启与禁止
C/T
定时器/计数器0 具体功能为计数还是定时
- 设置为0 表示定时功能 使用TH和TL可以设置初始数值,8位定时器读取TH和TL最大为65535时触发中断
- 设置为1 表示计数功能 由外部引脚 T0做计数脉冲
M1 M0
控制定时器/计数器工作模式
M1位 | M0位 | 对应工作模式 | 描述 |
---|---|---|---|
0 | 0 | 0 | 13位计时计数器 (8192) |
0 | 1 | 1 | 16位计时计数器 (65536) |
1 | 0 | 2 | 8位计时计数器,可自动重新载入计数值 (256) |
1 | 1 | 3 | 当成两组独立的8位计时器(256,T0和T1不能同时用) |
5.TH0/TL0 (TH1/TL1) 定时器高/低8位寄存器
定时器计数的寄存器,可以设置初始值,用于设定定时器的定时间隔
6.IP 定时/计数器同级优先级的配置 – 中断优先级寄存器
该寄存器的作用是设置中断同级优先级顺序时使用
PT0
定时中断0优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PT1
定时中断1优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PX0
外部中断0优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PX1
外部中断1优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PS
串口中断优先级设定位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PPCA
PCA中断优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PLVD
低压中断优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
PADC
ADC中断优先级设置位
- 设置位1 表示设置位同级高优先级
- 设置位0 表示设置位同级低优先级
7.串口的工作方式和控制功能 – SCON 串口控制寄存器
控制和设置串口工作方式的寄存器
SM0/FE
串行口工作方式选择位,FE
功能时为帧错误检测
- 当PCON寄存器中的
SMOD0
为1时,该位用于帧错误检测。当检测到一个 无效停止位时,通过UART接收器设置该位。它必须由软件清0。- 当PCON寄存器中的
SMOD0
位为0时,该位和SM1一起指定串行通信的工作方式。
SM1
串行口工作方式选择位
SM2
多机通信控制位
- 工作方式0时:非多机通讯方式,
SM2
位需要设置为0
,无特殊作用- 工作方式1时:非多机通讯方式,
SM2
位需要设置为0
,表示只有接收到**有效的停止位(第九位RB8
)**才激活RI
- 工作方式2或3时:多机通信控制位,(
REN
需要置为1
)
A)SM2
位设置为1
时,则接收器处于地址帧筛选状态,此时可以利用接收到的第9位RB8
来筛选地址帧
—RB8
位读取为0时,则表示接收的数据不是地址帧,应该舍弃,并且保持RI=0
状态
—RB8
位读取为1时,则表示接收的数据是地址帧,数据存入SBUF
,并且RI=1
状态,触发串口中断,可以在中断中再进行地址号的比较
B)SM2
位设置为0
时,则接收器处于地址帧筛选被禁止状态,此时接收到的第九位RB8
通常为校验标志位
—RB8
无论是0还是1,数据都会存入SBUF
中,并且RI=1
状态
REN
允许/禁止串行口接收的控制位
- 设置为0 禁止接收
- 设置为1 允许接收
TB8
发送的第九位数据,与SM2
结合使用
- 工作方式0时: 无用
- 工作方式1时: 无用
- 工作方式2或3时: 按需要置位或清0(奇偶校验的标志位或地址帧/数据帧的标志位)
RB8
接收到的第九位数据,与SM2
相关
- 工作方式0时: 无用
- 工作方式1时: 此位数据为接收到的停止位
- 工作方式2或3时:
SM2
设置为0,则此位数据为奇偶校验的标志位;SM2
设置为1时,地址帧/数据帧的标志位
TI
发送中断请求标志位
- 工作方式0时: 串行发送第八位结束时,由内部硬件自动置位,并向主机发起中断请求,响应中断服务接收后,
TI
必须由软件设置为0- 其他工作方式时: 停止位开始发送时,由内部硬件自动置位,并向主机发起中断请求,响应中断服务接收后,
TI
必须由软件设置为0
RI
接受中断请求标志位
- 工作方式0时: 接收第八位数据结束时,由内部硬件自动置位,并向主机发起中断请求,响应中断服务接收后,
RI
必须由软件设置为0- 其他工作方式时: 接收停止位中间时,由内部硬件自动置位,并向主机发起中断请求,响应中断服务接收后,
RI
必须由软件设置为0
SM0 | SM1 | 工作方式 | 功能说明 | 波特率 |
---|---|---|---|---|
0 | 0 | 方式0 | 同步移位串行方式:移位寄存器 | 当UART_M0x6 = 0时,波特率是SYSclk/12,当UART_M0x6 = 1时,波特率是SYSclk / 2 |
0 | 1 | 方式1 | 8位UART,波特率可变 | ( 2SMOD/32 )×(定时器1的溢出率或BRT独立波特率发生器的溢出率) |
1 | 0 | 方式2 | 9位UART | ( 2SMOD/ 64) x SYSclk系统工作时钟频率 |
1 | 1 | 方式3 | 9位UART,波特率可变 | (2SMOD/32 )x(定时器1的溢出率或BRT独立波特率发生器的溢出率) |
注意:
SMOD
PCON中的波特率选择位
设置为0:波特率加倍
设置为1:波特率正常
溢出率
为每秒溢出多少次T1溢出率 = fosc / {12 * [256-(TH1)]}
fosc
为晶振频率 如11.0592MHZ
的晶振频率为11059200
RI
和TI
向主机发送中断请求时,他们之间的关系是或逻辑
,单片机无法自动识别,使用时,需要业务操作进行区分
8.电源的控制 --PCON 电源控制寄存器
控制电源和部分串口功能的寄存器
SMOD
波特率选择位,复位时默认清零(与电源无关,与串口有关)
SMOD=0
时,串口方式为1/2/3,则波特率加倍SMOD=1
时,串口方式为1/2/3,则波特率正常
SMOD0
帧错误检测有效控制位(与电源无关,与串口有关)
SMOD0=0
时,SM0/FE
的功能是SM0
,与SM1
进行串口功能的工作方式选择SMOD0=1
时,SM0/FE
的功能是FE
,进行帧错误检测
LVDF
低压检测标志位(也是低压检测中断请求标志位)
- 正常/空闲工作时:
— 当工作电压Vcc低于低压检测门槛电压时,该位置1。该位要由软件清0 当低压检测电路发现工作电压Vcc偏低时,不要进行EEPROM/IAP操作。- 在进入掉电工作状态前:
— 如果低压检测电路未被允许可产生中断,则在进入掉电模式后,该低压检测电路不工作以降低功耗。
— 如果被允许可产生低压检测中断,则在进入掉电模式后,该低压检测电路继续工作,在内部工作电压Vcc低于低压检测门槛电压 后,产生低压检测中断,可将MCU从掉电状态唤醒。
POF
上电复位标志位
GF1(GF0)
两个通用工作标志位,用户可以任意使用。
PD
设置为1,单片机进入断电模式,时钟停振,CPU/定时器/串口停止工作,只有外部中断继续工作,此时功耗<0.1uA
IDL
设置为1,单片机进入空闲模式,除了CPU停止工作外,其他部件继续工作
9.其他中断寄存器参考
三、中断的使用
1.原理图
2. INT0#
触发流程
- 主服务开始运行
EA
已开启总中断功能EX0
已开启INT0#
引脚中断功能- 当
INT0#
引脚传入下降沿电平
(中断的触发)CPU
检测到IT0
配置的下降沿电平
就是中断开始工作的信号CPU
自动设置IE0
为1IP中断优先级控制器
…- 开始执行
void xxx() interrupt 0
中断服务- 中断服务执行结束
CPU
自动设置IE0
为0- 程序返回主服务继续运行
3.中断的使用-下降沿触发
代码
#include <reg52.h>
sbit LED = P0^0;
sbit LED2 = P0^1;
void delay(unsigned int millis);
void main(){
/**
* IE 中断允许寄存器
*/
EA=1;
EX0=1;
/**
* TCON 中断/定时器/计数器通用控制寄存器
*/
IT0=1;
while(1){
LED=0;
delay(3000);
LED=1;
delay(3000);
}
}
//中断0 服务
void switchLed2() interrupt 0 {
LED2=0;
}
void delay(unsigned int millis){
unsigned int i2;
unsigned int y=120;
for(millis;millis>0;millis--)
{
for(i2=0;i2<y;i2++);
}
}
4.中断的使用-低电平触发
将上边代码中 IT0=0;
即可改变为低电平触发
5.中断实验效果
GND飞线接通
INT0#
触发中断,P0^1
位的黄灯点亮成功
注意
如果是低电平触发IT0=0
,GND飞线持续接入INT0#
时,红灯程序会近乎停止,(CPU跳转到中断服务运行时,主服务会停止)
四、定时器/计数器的使用
1.定时器中断原理图
2.定时器的使用
IE
位: 1 开启中断TR0/TR1
: 1 启动定时器/计数器中断功能TMOD
:确定T0/T1工作方式TH0/TL0(TH1/TL1)
: 设置指定的初始值(未设置则从0开始)(计数到65536时触发中断)
如下代码程序为定时器0 计满65536后点亮LED2
代码
#include <reg52.h>
sbit LED = P0^0;
sbit LED2 = P0^1;
void delay(unsigned int millis);
void main(){
/**
* IE 中断允许寄存器
*/
EA=1;
ET0=1;
/**
* TCON 中断/定时器/计数器通用控制寄存器
*/
TR0=1;
/**
* TMOD 工作方式 选择 0000 0001 65536计满后触发中断
*/
TMOD=0x01;
//定时器初始值
TH0=0; //定时器初始值高8位
TL0=0; //定时器初始值低8位
while(1){
LED=0;
delay(3000);
LED=1;
delay(3000);
}
}
// 中断1 服务
void switchLed2() interrupt 1 {
LED2=0;
}
void delay(unsigned int millis){
unsigned int i2;
unsigned int y=120;
for(millis;millis>0;millis--)
{
for(i2=0;i2<y;i2++);
}
}
如下代码程序通过多次定时控制,为近乎10秒切换一次LED2的状态
#include <reg52.h>
sbit LED = P0^0;
sbit LED2 = P0^1;
unsigned char count=0;
void delay(unsigned int millis);
void main(){
/**
* IE
*/
EA=1;
ET0=1;
/**
* TCON
*/
TR0=1;
/**
* TMOD
*/
TMOD=0x01;
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
while(1){
LED=0;
delay(3000);
LED=1;
delay(3000);
if(count>=200)
{
LED2=~LED2;
count=0;
}
}
}
void switchLed2() interrupt 1 {
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
count++;
}
void delay(unsigned int millis){
unsigned int i2;
unsigned int y=120;
for(millis;millis>0;millis--)
{
for(i2=0;i2<y;i2++);
}
}
如下代码,由两个定时器控制的不同频段闪烁的LED灯,LED1每秒改变一次,LED2每5秒改变一次
(一个定时器也可以控制多各种业务逻辑,此处演示两个定时器)
#include <reg52.h>
sbit LED1 = P0^0;
sbit LED2 = P0^1;
unsigned char count1,count2;
void main(){
/**
* IE
*/
EA=1;
ET0=1;
ET1=1;
/**
* TCON
*/
TR0=1;
TR1=1;
/**
* TMOD
*/
TMOD=0x01;
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
TH1=(65536-46080)/256;
TL1=(65536-46080)%256;
while(1){
if(count1>=100){
LED1=~LED1;
count1=0;
}
if(count2>=100)
{
LED2=~LED2;
count2=0;
}
}
}
void switchLed2() interrupt 1 {
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
count2++;
}
void switchLed1() interrupt 3 {
TH1=(65536-46080)/256;
TL1=(65536-46080)%256;
count1++;
}
3.计数器的使用
IE
位: 1 开启中断TR0/TR1
: 1 启动定时器/计数器中断功能TMOD
:确定T0/T1工作方式TH0/TL0(TH1/TL1)
: 设置指定的初始值(未设置则从0开始)(计数到65536时触发中断)
与定时器的区别是修改TMOD的内容,准确的说是调整
C/T
位的值为1,表示使用计数器模式
注意
TMOD
高4位和低4位分别指 定时器/计数器1 和定时器/计数器0 的配置
/**
* TMOD 工作方式 选择 0000 0101 外部引脚计数满65536触发
*/
TMOD=0x05;
总结
本章主要为了解51单片机的中断与定时