【笔记】中断
source link: https://en.loli.fj.cn/2022/11/23/%E4%B8%AD%E6%96%AD/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
【笔记】中断
2022-11-232022-11-25
中断学习笔记
注意:本文所有代码均按照sdcc编译器代码规范编写,如果使用的Keli编译器,需要自行修改代码
- 中断:打断CPU当前工作的一种事件
- 中断源:所有可以引发中断的事件的集合
- 标准51单片机的中断源(5种/3类)
- 外部中断:由单片机引脚输入的中断
- 外部中断0
- 外部中断1
- 定时/计数器中断:由定时/计数器引起的中断
- 定时/计数器0中断
- 定时/计数器1中断
- 串行中断:由串行通讯(发送串行数据、接收串行数据)引起的中断
- 外部中断:由单片机引脚输入的中断
- 标准51单片机的中断源(5种/3类)
- 中断向量:中断函数的入口地址
- 在C51代码中,通常不直接使用中断向量,而是根据头文件中指定的指针变量来使用中断向量
数字信号的种类(4种/2类)
- 电平信号
- 高电平信号
- 低电平信号
- 边沿信号
- 上升沿信号
- 下降沿信号
外部中断请求类型
- 标准51单片机支持的外部中断请求类型
- 低电平请求
- 下降沿请求
STC12C5A60S2使用外部中断
- 开中断:STC12C5A60S2的12引脚默认为P3.2端口、13引脚默认为P3.3端口。如果需要开中断,需要将12引脚切换为INT0端口、将13引脚设置为INT1端口
- 指定中断请求类型(低电平请求、下降沿请求):虽然标准51单片机支持2种中断请求,但是使用时只能设置1种,每次需要中断时,通过这1种中断请求实现中断
- 指定中断处理函数:当检测到中断请求后,立即执行中断处理函数
- 通过IE寄存器实现开中断
- IE寄存器是可以位寻址的
- IE寄存器从第8位(最高位)到第1位(最低位)分别是:
EA
、空
、空
、ES
、ET1
、EX1
、ET0
、EX0
EA
:中断总开(1)关(0)EX0
:外部中断0的开(1)关(0)EX1
:外部中断1的开(1)关(0)ET0
:定时/计数器0的开(1)关(0)ET1
:定时/计数器1的开(1)关(0)ES
:串行中断的开(1)关(0)
关闭所有中断
通过字节寻址
IE = 0x00;
通过位寻址
EA = 0;
开启外部中断0
通过字节寻址
IE = 0x81;
通过位寻址
EA = 1;
EX0 = 1;
开启外部中断1
通过字节寻址
IE = 0x84;
通过位寻址
EA = 1;
EX1 = 1;
同时开启外部中断0和外部中断1
通过字节寻址
IE = 0x85;
通过位寻址
EA = 1;
EX0 = 1;
EX1 = 1;
指定中断请求类型
通过TCON(Timer Config)寄存器的低4位指定中断请求的类型
TCON寄存器是可以位寻址的
TCON寄存器从第4位到第1位分别是:
IE1
、IT1
、IE0
、IT0
IT0
:设置外部中断0的请求类型为低电平请求(0)或下降沿请求(1)IT1
:设置外部中断1的请求类型为低电平请求(0)或下降沿请求(1)IE0
:外部中断0的使能信号。当外部中断0接收到中断信号后,CPU会自动将IE0
设置为1;当外部中断0的中断信号处理结束后,CPU会自动将IE0
设置为0IE1
:外部中断1的使能信号。当外部中断1接收到中断信号后,CPU会自动将IE1
设置为1;当外部中断0的中断信号处理结束后,CPU会自动将IE1
设置为0
中断按键:将一个普通按键,一端接GND,另一端接INT0或INT1
中断请求类型设置为低电平请求(一个时刻)
- 这种方式如果中断按键按下时间过长,会导致中断处理函数执行多次
IT0 = 0;
中断请求类型设置为下降沿请求(一个瞬间)
- 这种方式如果中断按键按下出现抖动,会导致中断处理函数执行多次
IT0 = 1;
指定中断处理函数
- 无参数列表
- 无需声明,通常放在整个程序最后
- 函数名自定义
- 必须指定中断向量号
- 中断处理函数不能手动调用
中断向量:用于控制中断的内存地址
中断向量号:用于标记中断的编号,方便编程
interrupt <num>
:指定中断向量号,取值范围为0~4
0
:外部中断01
:定时/计数器中断02
:外部中断13
:定时/计数器中断14
:串行终端
void int0(void) interrupt <num>
{
...
}
阻止中断的接收
- 当一个中断处理函数正在执行时,阻止中断的接收
- 阻止中断的接收可以用来消除抖动
void int0(void) __interrupt 0
{
// 阻止中断的接收
EX0 = 0;
// 业务代码
...
// 还原中断的接收
EX0 = 1;
}
完整代码示例
- 利用外部中断0实现中断
#include<8052.h>
void init()
{
// 指定开启外部中断0
IE = 0x81;
// 指定外部中断0的终端请求类型为下降沿请求
IT0 = 1;
}
void main(void)
{
init();
while (1)
{
...
}
}
// 指定外部中断0的中断函数
void int0(void) __interrupt 0
{
// 阻止中断的接收
EX0 = 0;
// 业务代码
...
// 还原中断的接收
EX0 = 1;
}
定时/计数器中断(计数器)
在标准51单片机上有2个16位的定时/计数器
计数值:计数的总次数
计数初值:开始计数的起点
计数最大值:可以计数的上限
- 51单片机做多可以计16位的数
定时/计数器的计数方式
- 减计数:从计数初值(计数值)开始减到0。x86的PC使用的就是减计数的计数器
- 加计数:从计数初值(最大值-计数值)开始加到计数器能力最大值。标准51单片机使用的就是加计数的计数器
定时/计数器的计数内容
- 定时器:数内部的时基(时间基准)
- 计数器:数外部的脉冲信号周期(每个周期一高一低)
定时器的时间计算
- 时钟周期:1个时钟周期 = 1 / 晶振的频率
- 如果51单片机接了一个
12MHz
的晶振,那么时钟周期为1/12μs
- 如果51单片机接了一个
- 机器周期:1个机器周期 = 12 * 时钟周期
- 如果51单片机接了一个
12MHz
的晶振,那么机器周期为1μs
- 如果51单片机接了一个
STC12C5A60S2使用计数器中断
- 通过TMOD(Timer Model)寄存器指定模式
- TMOD寄存器是不可以位寻址的
- TMOD寄存器从第4位到第1位是用来设置定时/计数器0的,分别是:
GATE
、C/T、M1
、M0
- TMOD寄存器从第8位到第5位是用来设置定时/计数器1的,分别是:
GATE
、C/T、M1
、M0
GATE
:门控信号,用来指定定时/计数器的开关的方式,1表示硬件开启,0表示软件开启- C/T:1表示工作在计数模式,0表示工作在定时模式
M1
:用来设置工作方式的高位M0
:用来设置工作方式的低位
工作方式 | M1 | M0 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
2 | 1 | 0 |
3 | 1 | 1 |
写入计数初值
- 用2个初值寄存器存放初值
- 定时/计数器0:高8位用
TH0
寄存器,低8位用TL0
寄存器 - 定时/计数器1:高8位用
TH1
寄存器,低8位用TL1
寄存器
- 定时/计数器0:高8位用
定时/计数器0
加计数(MCU)
TH0 = (计数最大值 - 计数值) / 256;
TL0 = (计数最大值 - 计数值) % 256;
减计数(CPU)
TH0 = (计数最大值 - 计数值) / 256;
TL0 = (计数最大值 - 计数值) % 256;
开启定时/计数器
- 通过TCON(Timer Config)寄存器的高4位指定定时/计数器的开启
- TCON寄存器从第8位到第5位分别是:
TF1
、TR1
、TF0
、TR0
TR0
:定时/计数器0的软开(1)关(0)TR1
:定时/计数器1的软开(1)关(0)TF0
:定时/计数器的计数溢出标识,标识计数是(1)否(0)已完成TF1
:定时/计数器的计数溢出标识,标识计数是(1)否(0)已完成
定时/计数器0
TR0 = 1;
监测是否完成计数
if (TF0)
{
...
}
完整代码示例
- 通过按键,接收脉冲信号,累计5次开始中断
- 在计数模式下,需要利用
T0
和T1
引脚来接收脉冲信号,初始是高电平 - 可以将
T0
和T1
引脚接按键,实现发出脉冲信号
- 在计数模式下,需要利用
查询式中断
- 定时/计数器完成计数后只会改变计数溢出标识,需要自己判断进行中断
- 进入中断后需要手动将溢出标识置0
#include<8052.h>
void init()
{
// 为定时/计数器0指定模式
// 指定门控信号为软件开启
// 指定工作在计数模式
// 指定工作方式3
TMOD = 0x05;
// 为定时/计数器0指定计数初值
TH0 = (65535 - 5) / 256;
TL0 = (65535 - 5) % 256;
// 为定时/计数器0开启计数
TR0 = 1;
}
void main(void)
{
init();
while (1)
{
// 当定时/计数器0溢出标识为1时开始中断
if (TF0)
{
// 阻止计数
TR0 = 0;
// 业务代码
...
// 重置溢出标识
TF0 = 0;
// 重新指定计数初值
TH0 = (65535 - 5) / 256;
TL0 = (65535 - 5) % 256;
// 恢复计数
TR0 = 1;
}
}
}
中断式中断
- 定时/计数器完成计数后自动中断
- 进入中断后溢出标识会自动置0
#include<8052.h>
void init()
{
// 指定开启定时计数器0中断
IE = 0x82;
// 为定时/计数器0指定模式
// 指定门控信号为软件开启
// 指定工作在计数模式
// 指定工作方式3
TMOD = 0x05;
// 为定时/计数器0指定计数初值
TH0 = (65535 - 5) / 256;
TL0 = (65535 - 5) % 256;
// 为定时/计数器0开启计数
TR0 = 1;
}
void main(void)
{
init();
while (1)
{
}
}
void timer0(void) __interrupt 1
{
// 阻止计数
TR0 = 0;
// 业务代码
...
// 重新指定计数初值
TH0 = (65535 - 5) / 256;
TL0 = (65535 - 5) % 256;
// 恢复计数
TR0 = 1;
}
STC12C5A60S2使用定时器中断
#include<8052.h>
void init()
{
// 指定开启定时计数器0中断
IE = 0x82;
// 为定时/计数器0指定模式
// 指定门控信号为软件开启
// 指定工作在定时模式
// 指定工作方式3
TMOD = 0x01;
// 为定时/计数器0指定时间初值(1ms=1000次)
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
// 为定时/计数器0开启计数
TR0 = 1;
}
void main(void)
{
init();
while (1)
{
}
}
void timer0(void) __interrupt 1
{
// 阻止计数
TR0 = 0;
// 业务代码
...
// 重新指定计数初值
TH0 = (65535 - 50000) / 256;
TL0 = (65535 - 50000) % 256;
// 恢复计数
TR0 = 1;
}
Recommend
-
95
1)继承TServerEventHandler类,获取连接用户的基本信息包括IP和端口,从而监控是否保存有没有清除的连接TServerEventHandler类提供了用户连接和断开的时候,针对套接字的处理方式,其中提供了两个函数createContext 当一个新的用户连接的时候会被调用deleteContext...
-
70
Redis 高负载下的中断优化
-
69
-
61
(点击上方公众号,可快速关注) 作者:Chen Minxing,个人公号: 心父母美国梦
-
85
【猎云网(微信号:)】6月29日报道(编译:田小雪) 去年上半年,美国发生了两次全国范围内的911报警电话呼叫中断。第一次,是3月8...
-
58
-
41
在最近开发的一个系统中,有一个定时任务,每天需要将一份数据(大约200w条),发送至一个线上key-value存储系统中。 说到定时任务,最常见的,就是使用crontab。原来这一套系统已经开发完成,部署在深圳IDC,工作良好。最近,需...
-
30
一、HBase知识介绍 考虑到来听分享的大部分都是MySQL DBA,因此这里做了个简单的HBase相关介绍,主要介绍了如下三个方面的内容: 1、HBase简介 HBase是基于google bigtable的开源实现,又称为hadoop datab...
-
37
5 月 2 日 19:29 到 22:35 UTC 之间,微软 Azure 发生了三小时左右中断,导致 Azure、Microsoft 365、Dynamics 和 DevOps 等多项服务出现连接问题。 根据最新消息,本次事故发生在 DNS 迁移期间,具体时间为 5 月 2 日 19:29 到...
-
5
HAL 库开发笔记(三)- 外部中断上一篇文章我们提到,用轮询的方法消除按键抖动、检测输入,有可能会消耗过多的系统资源并导致卡机,也有可能会错过检测。这就是为什么我们需要使用中断了。基本原理
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK