当前位置: 首页 > news >正文

单片机-89C51部分:7、中断

飞书文档https://x509p6c8to.feishu.cn/wiki/A5gcwyL5giq1JOkkcsscn8eLnzf

一、中断的作用

中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的,中断功能的存在,很大程度上提高了单片机处理外部或内部事件的能力。它也是单片机最重要的功能之一,是我们学习单片机必须要掌握的。

为了能让大家更容易理解中断概念, 我们先来举一个生活事例:

你打开火,烧上一壶水。然后去洗衣服,在洗衣服的过程中,突然听到水壶发出水开的报警声,这时,你停止洗衣服动作,立即去关掉火,然后才回去继续洗衣服。
这个过程中实际上就发生了一次中断。对于单片机来讲,中断是指 CPU 在处理某一事件 A 时,发生了另一事件 B,请求 CPU 迅速去处理(中断发生);CPU 暂时停止当前的工作(中断响应), 转去处理事件 B(中断服务);待 CPU 将事件 B 处理完毕后,再回到原来事件 A 被中断的地方继续处理事件 A(中断返回),这一过程称为中断。

二、那中断是如何解决实际问题的呢?

回到按键章节,如果我们在while循环中,没有耗时的代码需要执行,这段代码是能够实时记录按键值的,但如果我们的程序设计复杂后,有耗时的任务需要处理,例如下方的Delay1ms(20000);延时20s,那在这20s内我们按下按键,芯片就无法读取到信号的变化了。

#include <reg52.h>sfr P4    = 0xe8;                   //for 89C5xRC/RD+ series and 90C5xRc/RD+, location at 0E8H
sbit INT2 = P4^3;
sbit INT3 = P4^2;sfr XICON = 0xc0;                   //for 89C5xRC/RD+ series and 90C5xRc/RD+, location at 0C0H
sbit PX3  = XICON^7;
sbit EX3  = XICON^6;
sbit IE3  = XICON^5;
sbit IT3  = XICON^4;
sbit PX2  = XICON^3;
sbit EX2  = XICON^2;
sbit IE2  = XICON^1;
sbit IT2  = XICON^0;sbit key1 = P4^3;
sbit led1 = P2^7;void delay_ms(unsigned int xms)   //@12MHz
{unsigned int i, j;for(i=xms;i>0;i--){for(j=124;j>0;j--){}}
}void main()
{while(1){//当按键按下时灯切换if(key1 == 0){led1= ~led1;delay_ms(1000);}delay_ms(20000);}               
}

这时候,我们就需要用中断的功能,帮我们实时记录。

三、51单片机的中断

STC89C5X 系列单片机提供了 8 个中断请求源,它们分别是:外部中断O(INT0)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3)、定时器 0中断、定时器 1 中断、定时器 2 中断、串口(UART)中断。

外部中断:由外部引脚触发的中断

定时器中断:由定时器触发的中断

串口中断:通讯过程中发送或接收数据完毕触发的中断

外部中断

这个章节我们先来看下外部中断,也就是INT0、INT1、INT2、INT3。

下面这个框图很重要,它会给我们介绍,如果我们需要使用单片机的某个中断,需要配置哪些寄存器,我们通过框图、再结合寄存器表格和示例程序,就能知道怎么使用单片机中断。

中断寄存器

TCON.0/IT0:中断触发行为设置

IE0:外部中断0请求源,IE0=1外部中断向CPU请求中断,中断响应后,IE0=0

不需要手动设置,由CPU处理即可。

EX0:外部中断0允许寄存器

EA:总中断允许寄存器

中断初始化

void exti0_init(void)
{IT2=1;//触发方式:下降沿EX2=1;//打开 INT2 的中断允许EA=1;//打开总中断
}

中断服务程序(回调函数)

//在中断函数中 exti0 是函数名,可自定义,interrupt 是一个关键字,表示 51 单片机中断。
//后面的“0”是中断号
//外部中断 0 中断号为 0
//定时器中断0,中断号为1
//外部中断 1,则中断号为 2。
void exti0() interrupt 0 //外部中断 0 中断函数
{//执行所需的功能
}

外部中断代码:

#include <reg52.h>sfr P4    = 0xe8;                   //for 89C5xRC/RD+ series and 90C5xRc/RD+, location at 0E8H
sbit INT2 = P4^3;
sbit INT3 = P4^2;sfr XICON = 0xc0;                   //for 89C5xRC/RD+ series and 90C5xRc/RD+, location at 0C0H
sbit PX3  = XICON^7;
sbit EX3  = XICON^6;
sbit IE3  = XICON^5;
sbit IT3  = XICON^4;
sbit PX2  = XICON^3;
sbit EX2  = XICON^2;
sbit IE2  = XICON^1;
sbit IT2  = XICON^0;sbit key1 = P4^3;
sbit led1 = P2^7;void delay_ms(unsigned int xms)   //@12MHz
{unsigned int i, j;for(i=xms;i>0;i--){for(j=124;j>0;j--){}}
}void exit2() interrupt 6
{//当按键按下时灯切换if(key1 == 0){led1= ~led1;delay_ms(1000);}
}void main()
{IT2 = 1; //设置中断触发条件为下降沿EX2 = 1; //运行中断2经过EA = 1;  //使能中断while(1){delay_ms(20000);}               
}

要注意:

标准的单片机头文件reg52.h是没有P4,我们可以参考工具自行添加。

中断优先级

每一个中断的优先级别均可用软件设置。高优先级的中断请求可以打断低优先级的中断,反之,低优先级的中断请求不可以打断高优先级及同优先级的中断。当两个相同优先级的中断同时产生时,将由查询次序来决定系统先响应哪个中断。

默认情况下所有中断优先级被设置为最高优先级3,当系统开启了多个中断,根据具体的业务设置对应的优先级即可。例如系统开启了外部中断INT0和INT1,默认情况下INT0的优先级是比INT1要高的,假设系统触发了INT0,INT0在执行中断服务程序时,INT1将不会被及时响应。
主任务:洗衣服
INT0:女朋友来电
INT1: 厨房着火
如果不修改中断优先级,在INT0执行的时候,INT1将不会被响应。
所以我们需要降低INT0的优先级,设置PX0H=0 PX0=0,把优先级降到0,同时INT1的PX1H=1 PX1=1,这样就能保证在INT0执行的时候,INT1也能被及时响应。

IP XICON IPH 中断优先级控制寄存器

IP、IPH - PX0H PX0

0b0000 0001

0b0100 0000

0*8+1*4+0*2+0*1 = 4

0*8+0*4+0*2+0*1=0

0x40

注意:

IPH这个寄存器是不可位寻址的,
如要想让PX0H这位置一的话,直接 PX0H=1;这个写法是错误的,因为它不能位寻址。
只能 IPH= 0x01(0000 0001)

//STC单片机的中断优先级需要设置IP和IPH寄存器,IP寄存器可以位操作,IPH只能寄存器操作
//优先级也可以不设置,默认的中断优先级就是0,因为复位之后IPH和IP寄存器默认值就是0
PX0 = 1;
IPH =
0x01;

0x0116进制的表示

在Keil C51中数不能直接以二进制形式赋值,所以需要设置寄存器某一位为1,用10进制或16进制显示,这里涉及到进制转换:

一个寄存器8位,相当于一个字节。

十进制:十进制是我们平常使用的数字系统,包含0到9这10个数字。

二进制:二进制是一种数值表示方式,只包含0和1两个数字。常常这样表示:0b0000 0000

十六进制:十六进制是一种数值表示方式,包含0到9和A到F这16个数字,常常这样表示0x01

A可以理解为十进制的10,B=11,C=12,D=13,E=14,F=15

二进制

二进制转十六进制

十六进制

十进制

0b0000 0001

0*8+0*4+0*2+0*1=0

0*8+0*4+0*2+1*1=1

0x01

0×16¹+1×16⁰

0×16+1×1 = 1

1

0b0000 0100

0*8+0*4+0*2+0*1=0

0*8+1*4+0*2+0*1=4

0x04

0×16¹+4×16⁰

0×16+4×1 = 4

4

0b0001 0000

0*8+0*4+0*2+1*1=1

0*8+0*4+0*2+0*1=0

0x10

1×16¹+0×16⁰

1×16+0×1 = 16

16

0b0001 1111

0*8+0*4+0*2+1*1=1

1*8+1*4+1*2+1*1=15=f

0x1f

1×16¹+f×16⁰

f=15

1×16+15×1 = 31

31

相关文章:

  • 无刷空心杯电机及机器人灵巧手的技术解析与发展趋势
  • ECMAScript 版本
  • 意法半导体(ST)重磅收购Deeplite,边缘AI版图再扩张
  • LangChain4j +DeepSeek大模型应用开发——3 人工智能服务 AIService
  • 制药领域的技术革命:Profinet转CanOpen网关大放异彩
  • alibaba的EasyExcel导出合并单元格,超简单
  • 深度相机(一)——深度相机模型及用途介绍
  • 天梯——算式拆分
  • 在g2o图优化框架中,顶点(Vertex)和边(Edge)的定义与功能的区别
  • SAP-ABAP:ABAP内存:SAP开发中的数据暂存利器解析
  • V Rising 夜族崛起 [DLC 解锁] [Steam] [Windows SteamOS]
  • C语言学习路线
  • TypeScript中的函数类型定义与类型约束
  • web服务与Nginx
  • MySQL 主从复制
  • 二叉树的所有路径(回溯算法基础)
  • 蓝牙耳机开发--TWS蓝牙耳机双向通信充电盒设计
  • 滑动窗口模板
  • 《系统分析师-第三阶段—总结(六)》
  • Android Studio学习记录1
  • 铁路五一假期运输今日启动,预计发送旅客1.44亿人次
  • IPO周报|4月最后2只新股周一申购,今年以来最低价股来了
  • 北上广深还是小城之春?“五一”想好去哪玩了吗
  • 伊朗港口爆炸致18死800余伤,三分之二伤者已出院
  • 解码人格拼图:探索心理健康的多维视角
  • 我国风电光伏装机历史性超过火电