外部中断相关寄存器
038.4.2 外部中断相关寄存器
#include "reg52.h"
#include <intrins.h>
sbit LED1 = P1^0;
sbit LED2 = P1^1;
sbit LED3 = P1^2;
sbit LED4 = P1^3;
//sbit KEY1 = P3^2;
//sbit KEY2 = P3^3;
//sbit SUN = P3^7;
typedef unsigned char uchar;
typedef unsigned int uint;
void Delay_xms(uint xms) // @11.0592MHz
{
uchar data i, j;
while (xms)
{
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
//初始化
IT0 = 1;
EX0 = 1;
IT1 = 1;
EX1 = 1;
EA = 1;
while (1)
{
//Delay_xms(1000);
}
}
void Int0_Routine(void) interrupt 0
{
Delay_xms(10);
LED3 = ~LED3;
}
void Int1_Routine(void) interrupt 2
{
Delay_xms(10);
LED4 = ~LED4;
}
一、外部中断相关寄存器
外部中断不是只配置一个“开关”就能工作。一次中断从外部引脚到中断服务程序,要依次经过触发方式识别、请求标志、本地允许、总允许和优先级仲裁:
外部电平变化
│
▼
触发方式 ITx 是否匹配?
│ 是
▼
请求标志 IEx 置 1
│
├── 本地允许 EXx = 1?
├── 总允许 EA = 1?
└── 当前优先级允许响应?
│
▼
跳转到中断向量并执行 ISR
在本节程序中,五条关键配置语句分别承担不同职责:
| 代码 | 所属寄存器位 | 作用 |
|---|---|---|
IT0 = 1 | TCON.0 | INT0 选择下降沿触发 |
EX0 = 1 | IE.0 | 允许外部中断0 |
IT1 = 1 | TCON.2 | INT1 选择下降沿触发 |
EX1 = 1 | IE.2 | 允许外部中断1 |
EA = 1 | IE.7 | 打开 CPU 中断总允许 |
IE0、IE1 与 IE 很容易混淆:IE 是地址为 A8H 的完整中断允许寄存器;IE0、IE1 则是 TCON 中的两个外部中断请求标志位。它们名字相似,但位置和职责完全不同。
1.1 演示代码
STC89C52 的中断相关寄存器可以按功能分为三类:
| 类别 | 主要寄存器 | 回答的问题 |
|---|---|---|
| 中断控制与标志 | TCON、SCON、T2CON、XICON | 什么事件触发?请求是否已经发生?外设怎样运行? |
| 中断允许 | IE、XICON | 该中断源是否获准向 CPU 提交请求? |
| 中断优先级 | IP、IPH、XICON | 多个请求同时存在时谁先响应,能否发生嵌套? |
本节程序只显式配置 TCON 和 IE 中的五个位,没有配置优先级寄存器。这样完全可以正常工作:复位后所有中断都处于最低优先级 0;当同级请求同时出现时,芯片再按固定查询顺序仲裁,而不是因为没有设置优先级就无法响应。
程序的输入输出对应关系是:
SW3 ──► P3.2 / INT0 ──► interrupt 0 ──► P1.2 / LED3
SW4 ──► P3.3 / INT1 ──► interrupt 2 ──► P1.3 / LED4
源程序保留了 LED1~LED4 四个位定义,但两个 ISR 实际翻转的是 LED3 和 LED4。KEY1、KEY2 被注释掉,是因为中断硬件直接监视 P3.2、P3.3,不再需要主循环通过变量轮询按键。
1.2 TCON寄存器
TCON 是地址为 88H 的 8 位、可位寻址特殊功能寄存器。它同时管理定时器0、定时器1以及外部中断0、外部中断1:
TCON(88H)
位序号 B7 B6 B5 B4 B3 B2 B1 B0
位名称 TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
用途 └──── 定时器1/0 ────┘ └── 外部中断1/0 ──┘
复位值 0 0 0 0 0 0 0 0
视频重点使用低四位,但高四位也必须认识:
| 位 | 位地址表达 | 含义 | 谁置位或控制 | 清零方式 |
|---|---|---|---|---|
B7 TF1 | TCON.7 | 定时器1溢出请求标志 | T1 溢出时由硬件置 1 | CPU 响应 T1 中断时硬件清 0,也可软件清 0 |
B6 TR1 | TCON.6 | 定时器1运行控制 | 软件置 1启动、清 0停止 | 软件控制 |
B5 TF0 | TCON.5 | 定时器0溢出请求标志 | T0 溢出时由硬件置 1 | CPU 响应 T0 中断时硬件清 0,也可软件清 0 |
B4 TR0 | TCON.4 | 定时器0运行控制 | 软件置 1启动、清 0停止 | 软件控制 |
B3 IE1 | TCON.3 | INT1 请求标志,对应 P3.3 | 外部中断1条件成立时由硬件置 1 | 下降沿模式响应后硬件清 0;低电平模式要先让引脚恢复高电平 |
B2 IT1 | TCON.2 | INT1 触发类型选择 | 软件配置 | 0 低电平,1 下降沿 |
B1 IE0 | TCON.1 | INT0 请求标志,对应 P3.2 | 外部中断0条件成立时由硬件置 1 | 下降沿模式响应后硬件清 0;低电平模式要先让引脚恢复高电平 |
B0 IT0 | TCON.0 | INT0 触发类型选择 | 软件配置 | 0 低电平,1 下降沿 |
TR0、TR1 是定时器运行开关,不是中断允许位;TF0、TF1 是溢出请求标志,也不是定时器启动开关。类似地,IT0、IT1 只选择触发方式,IE0、IE1 只表示请求发生,真正允许外部中断的是 IE 寄存器中的 EX0、EX1 和 EA。
从复位状态开始执行 IT0 = 1、IT1 = 1 后,其余位不变,得到:
TCON = 0000 0101B = 0x05
│ │
IT1 IT0
1.3 中断系统
STC89C52 有 8 个中断源。每个中断源都拥有事件条件、请求标志、本地允许位、优先级位和固定中断向量:
| C51中断号 | 中断源 | 请求标志 | 本地允许位 | 优先级低位 | 优先级高位 | 向量地址 |
|---|---|---|---|---|---|---|
| 0 | INT0 | IE0 | EX0 | PX0 | PX0H | 0003H |
| 1 | Timer0 | TF0 | ET0 | PT0 | PT0H | 000BH |
| 2 | INT1 | IE1 | EX1 | PX1 | PX1H | 0013H |
| 3 | Timer1 | TF1 | ET1 | PT1 | PT1H | 001BH |
| 4 | UART | RI 或 TI | ES | PS | PSH | 0023H |
| 5 | Timer2 | TF2 或 EXF2 | ET2 | PT2 | PT2H | 002BH |
| 6 | INT2 | IE2 | EX2 | PX2 | PX2H | 0033H |
| 7 | INT3 | IE3 | EX3 | PX3 | PX3H | 003BH |
请求进入 CPU 的基本逻辑可以写成:
请求有效 AND 本地允许=1 AND EA=1 AND 优先级条件满足
CPU 响应后会完成当前机器指令,将返回地址压栈,转入固定向量,再由向量入口跳到 C51 编译器安排的中断服务程序。ISR 最终执行 RETI,清除中断系统的“正在服务”状态并返回断点。普通函数返回指令 RET 不能代替 RETI。
1.4 中断寄存器
数据手册列出的相关寄存器如下:
| 寄存器 | 地址 | 8个位,从 B7 到 B0 |
|---|---|---|
IE | A8H | EA、保留、ET2、ES、ET1、EX1、ET0、EX0 |
IP | B8H | 保留、保留、PT2、PS、PT1、PX1、PT0、PX0 |
IPH | B7H | PX3H、PX2H、PT2H、PSH、PT1H、PX1H、PT0H、PX0H |
TCON | 88H | TF1、TR1、TF0、TR0、IE1、IT1、IE0、IT0 |
SCON | 98H | SM0/FE、SM1、SM2、REN、TB8、RB8、TI、RI |
T2CON | C8H | TF2、EXF2、RCLK、TCLK、EXEN2、TR2、C/T2、CP/RL2 |
XICON | C0H | PX3、EX3、IE3、IT3、PX2、EX2、IE2、IT2 |
其中 T2CON 的每一位含义为:
| 位 | 含义 |
|---|---|
TF2 | 定时器2溢出标志,需要软件清零;RCLK 或 TCLK 为 1时不会置位 |
EXF2 | T2EX 外部事件标志,满足捕获/重装条件时置位,需要软件清零 |
RCLK | 选择定时器2溢出作为串口接收波特率时钟 |
TCLK | 选择定时器2溢出作为串口发送波特率时钟 |
EXEN2 | 允许 T2EX 负跳变产生捕获或重装 |
TR2 | 定时器2运行控制,1启动、0停止 |
C/T2 | 0 选择内部定时,1 选择外部事件计数 |
CP/RL2 | 选择捕获或自动重装方式,并受 RCLK、TCLK 等位共同影响 |
T2CON 在后续定时器2课程中才会实际配置,但先明确各位职责,可以避免把 TF2 请求标志、TR2 运行位和 ET2 中断允许位混在一起。
1.4.1 中断允许寄存器IE和XICON
IE 是地址为 A8H 的中断允许寄存器,可位寻址:
IE(A8H) B7 B6 B5 B4 B3 B2 B1 B0
EA - ET2 ES ET1 EX1 ET0 EX0
复位值 0 x 0 0 0 0 0 0
| 位 | 英文记忆 | 具体含义 |
|---|---|---|
EA | Enable All | CPU 总中断允许;1开放总闸门,0屏蔽全部可屏蔽中断 |
| B6 | Reserved | 保留位,数据手册以 x 表示,不应作为程序状态依据 |
ET2 | Enable Timer 2 | 定时器2中断允许;1允许,0禁止 |
ES | Enable Serial | 串口中断允许;1允许,0禁止 |
ET1 | Enable Timer 1 | 定时器1中断允许;1允许,0禁止 |
EX1 | Enable External 1 | 外部中断1允许;1允许,0禁止 |
ET0 | Enable Timer 0 | 定时器0中断允许;1允许,0禁止 |
EX0 | Enable External 0 | 外部中断0允许;1允许,0禁止 |
EA 中的 A 可以按 “All” 记忆,即所有中断的总闸门;不是输出 out 的意思。EX 中的 X 表示 external,ET 中的 T 表示 timer,ES 中的 S 表示 serial。
INT2、INT3 的允许、标志、触发方式和优先级低位不在 IE 或 TCON 中,而集中在 XICON:
XICON(C0H) B7 B6 B5 B4 B3 B2 B1 B0
PX3 EX3 IE3 IT3 PX2 EX2 IE2 IT2
复位值 0 0 0 0 0 0 0 0
| 位 | 含义 |
|---|---|
PX3 | INT3 优先级低位,与 PX3H 组合形成四级优先级 |
EX3 | INT3 本地允许位,1允许、0禁止 |
IE3 | INT3 请求标志,触发条件成立时由硬件置位 |
IT3 | INT3/P4.2 触发方式,0低电平、1下降沿 |
PX2 | INT2 优先级低位,与 PX2H 组合形成四级优先级 |
EX2 | INT2 本地允许位,1允许、0禁止 |
IE2 | INT2 请求标志,触发条件成立时由硬件置位 |
IT2 | INT2/P4.3 触发方式,0低电平、1下降沿 |
EX2、EX3 虽然在 XICON 中,仍然要经过 IE.EA 总闸门。任何中断源都不能绕过 EA。
1.4.2 定时器/计数器0/1控制寄存器TCON
理解 TCON 低四位时,最有效的方法是把 INT0 和 INT1 分成两组:
外部中断0:P3.2/INT0 ── IT0选择触发方式 ──► IE0请求标志
外部中断1:P3.3/INT1 ── IT1选择触发方式 ──► IE1请求标志
| 外部中断 | 引脚 | 触发选择位 | 请求标志位 | 本地允许位 | C51中断号 |
|---|---|---|---|---|---|
| INT0 | P3.2 | IT0 | IE0 | EX0 | 0 |
| INT1 | P3.3 | IT1 | IE1 | EX1 | 2 |
正常使用时,软件负责配置 IT0、IT1;中断硬件负责在事件发生时置位 IE0、IE1。请求标志虽然也能被软件读写,但不应在普通流程中用软件反复置位模拟按键。初始化或故障恢复时可以按芯片手册清理遗留标志。
在下降沿触发模式中,CPU 响应后会由硬件清除相应请求标志。在低电平触发模式中,只要外部引脚仍保持低电平,请求条件就持续成立;即使内部状态被清除,也可能立即重新申请中断。因此低电平触发通常要求外设在 ISR 中或 ISR 返回前撤销低电平请求。
1.4.3 串行口控制寄存器SCON
SCON 是地址为 98H 的串口控制寄存器,八个位全部可位寻址:
SCON(98H) B7 B6 B5 B4 B3 B2 B1 B0
SM0/FE SM1 SM2 REN TB8 RB8 TI RI
| 位 | 含义 |
|---|---|
SM0/FE | 当 PCON.SMOD0=0 时,与 SM1 组合选择串口方式;当 SMOD0=1 时作为帧错误标志 FE |
SM1 | 串口工作方式选择位之一 |
SM2 | 多机通信及接收筛选控制,具体行为随串口方式变化 |
REN | 串口接收允许;1允许接收,0禁止接收 |
TB8 | 方式2、3中要发送的第9位数据 |
RB8 | 方式2、3中接收到的第9位;方式1中可反映停止位状态 |
TI | 发送中断标志;发送到规定位置后硬件置 1,必须由软件清 0 |
RI | 接收中断标志;完整接收并满足条件后硬件置 1,必须由软件清 0 |
串口发送和接收共用一个中断源、一个允许位 IE.ES 和同一个 interrupt 4。因此串口 ISR 必须分别判断 TI、RI,处理后由软件清零。CPU 响应串口中断不会自动清除这两个标志,否则程序会不断重新进入 ISR。
SCON 与本节两个按键中断没有直接关系,但它体现了同一条通用规律:外设控制寄存器产生请求标志,IE 中的本地允许位决定请求能否进入中断系统,EA 再作总控制。
1.4.4 应用案例
本开发板的按键和 LED 都是低电平有效,但原因不同:
按键输入:
P3.2/INT0 ── SW3 ── GND
P3.3/INT1 ── SW4 ── GND
LED输出:
+5V ── LED3 ── R10(10 kΩ)── P1.2
+5V ── LED4 ── R11(10 kΩ)── P1.3
- 按键松开时,P3 口内部弱上拉使 INTx 为高电平;按下后开关闭合,INTx 被接到 GND,形成下降沿。
- LED 端口输出 0 时,电流沿
+5V → LED → 10 kΩ电阻 → P1.x → GND流动,LED 点亮。 - LED 端口输出 1 时,P1.x 接近 +5V,LED 两端没有足够压差,LED 熄灭。
因此第一次按下 SW3 后,ISR 对 LED3 取反,使复位高电平变为低电平,LED3 点亮;再次按下又恢复高电平,LED3 熄灭。SW4 与 LED4 的过程相同。
1.4.4.1 例题: 配置外部中断
以外部中断1为例,完整信号链如下:
按下 SW4
│
▼
P3.3/INT1 从 1 变为 0
│ IT1=1,检测下降沿
▼
TCON.IE1 由硬件置 1
│ IE.EX1=1,本地允许
│ IE.EA=1,总允许
│ [PX1H,PX1]=00,优先级0
▼
CPU 跳到 0013H,对应 interrupt 2
│
▼
执行 Int1_Routine()
│ 10 ms简单消抖
│ LED4 = ~LED4
▼
硬件清除下降沿请求标志,RETI 返回主程序
外部中断0完全对应另一组位:
P3.2/INT0 → IT0 → IE0 → EX0 → EA → [PX0H,PX0]
→ 0003H → Int0_Routine() interrupt 0 → LED3翻转
机械按键会发生触点抖动,一次按下可能包含多个快速下降沿。本例在 ISR 内延时 10 ms 是便于观察的简单做法,但 ISR 内不宜长时间阻塞。更可靠的设计是让外部 ISR 只记录事件或暂时关闭 EX0/EX1,再由定时器延时确认电平并恢复中断。
二、中断处理
中断控制可以概括为四类位:
| 位的类型 | 本节示例 | 核心问题 |
|---|---|---|
| 触发方式位 | IT0、IT1 | 什么电气条件算作事件? |
| 请求标志位 | IE0、IE1 | 事件是否已经发生? |
| 允许位 | EX0、EX1、EA | CPU 是否获准响应? |
| 优先级位 | PX0/PX0H、PX1/PX1H | 多个请求冲突时谁先处理? |
这四类位必须分开理解。触发方式正确但没有允许,中断不会被响应;允许全部打开但没有请求事件,CPU 也不会进入 ISR;优先级只负责仲裁,不负责产生事件或打开中断。
2.1 外部中断与触发方式
INT0 和 INT1 都支持低电平触发与下降沿触发:
ITx | 模式 | 电平示意 | 行为 |
|---|---|---|---|
| 0 | 低电平触发 | ──────┐____,低电平期间持续有效 | 只要引脚为 0,请求条件持续存在 |
| 1 | 下降沿触发 | ──────┐ 的跳变瞬间 | 记录一次由 1 到 0 的变化 |
本板按键波形可以画成:
松开 按下并保持 松开
高电平 ───────────┐ ┌─────────
│ │
低电平 └──────────────────────┘
▲
└── 下降沿:ITx=1 时触发
下降沿模式更适合“每按一次产生一次事件”的按键逻辑;低电平模式适合由外设保持请求,直到软件处理完成的场景。两种模式都需要考虑按键抖动、信号持续时间和噪声,不是简单地把 ITx 改成 0 或 1就一定可靠。
2.2 中断优先级控制
STC89C52 使用一个高位和一个低位为每个中断源编码四级优先级:
| 高位 H | 低位 L | 优先级 |
|---|---|---|
| 0 | 0 | 0,最低 |
| 0 | 1 | 1,较低 |
| 1 | 0 | 2,较高 |
| 1 | 1 | 3,最高 |
IP 地址为 B8H,保存六个常规中断源的优先级低位:
IP(B8H) B7 B6 B5 B4 B3 B2 B1 B0
- - PT2 PS PT1 PX1 PT0 PX0
| 位 | 对应中断 |
|---|---|
| B7、B6 | 保留位,不用于优先级配置 |
PT2 | Timer2 优先级低位 |
PS | UART 优先级低位 |
PT1 | Timer1 优先级低位 |
PX1 | INT1 优先级低位 |
PT0 | Timer0 优先级低位 |
PX0 | INT0 优先级低位 |
IPH 地址为 B7H,八个位都是优先级高位:
IPH(B7H) B7 B6 B5 B4 B3 B2 B1 B0
PX3H PX2H PT2H PSH PT1H PX1H PT0H PX0H
| 位 | 对应中断及其低位 |
|---|---|
PX3H | INT3,高位;低位为 XICON.PX3 |
PX2H | INT2,高位;低位为 XICON.PX2 |
PT2H | Timer2,高位;低位为 IP.PT2 |
PSH | UART,高位;低位为 IP.PS |
PT1H | Timer1,高位;低位为 IP.PT1 |
PX1H | INT1,高位;低位为 IP.PX1 |
PT0H | Timer0,高位;低位为 IP.PT0 |
PX0H | INT0,高位;低位为 IP.PX0 |
IP 可位寻址,IPH 不可位寻址,因此设置 IPH 时要按字节使用掩码,保留不想改变的其他位。INT2、INT3 的低位 PX2、PX3 在 XICON 中,不在 IP 中。
复位后所有有效优先级位均为 0,本例的 INT0、INT1 都属于优先级0。若两者在同一时刻申请,芯片按照固定同级查询顺序 INT0 → Timer0 → INT1 → Timer1 → UART → Timer2 → INT2 → INT3 处理,因此 INT0 先于 INT1。高优先级请求可以打断正在服务的低优先级中断,同级请求不能互相打断。
2.3 中断允许寄存器
中断允许采用“两级闸门”:
INT0:IE0请求 ──► EX0本地允许 ──┐
INT1:IE1请求 ──► EX1本地允许 ──┼──► EA总允许 ──► 优先级仲裁 ──► CPU
其他中断请求 ──► 各自允许位 ──┘
| 组合 | 结果 |
|---|---|
EX0=0、EA=1 | INT0 被单独屏蔽,其他已允许中断仍可工作 |
EX0=1、EA=0 | INT0 分闸门已开,但总闸门关闭,CPU 不响应任何可屏蔽中断 |
EX0=1、EA=1 | INT0 获准进入优先级仲裁 |
EX1=1、EA=1 | INT1 获准进入优先级仲裁 |
本节从复位状态设置 EX0、EX1、EA 后,IE 的有效控制位为:
IE = 1x00 0101B
│ │ │
EA EX1 EX0
B6 是保留位,数据手册用 x 表示,不应读取它来判断程序状态。若用整字节方式写入常用值 IE = 0x85,有效位与上图相同,但会同时把其他中断允许位写成 0;逐位写 EX0 = 1、EX1 = 1、EA = 1 更容易保留系统中已有的其他允许状态。
2.4 例题1: 外部中断配置代码分析
初始化代码执行后的寄存器状态为:
TCON = 0000 0101B = 0x05
IE有效位 = 1x00 0101B
IP有效位(B5~B0) = 00 0000B
IPH = 0000 0000B
逐句分析如下:
IT0 = 1;
把 TCON.0 置 1,P3.2/INT0 选择下降沿触发。它没有打开中断,也没有直接调用函数。
EX0 = 1;
把 IE.0 置 1,允许 INT0 的请求通过本地闸门。
IT1 = 1;
把 TCON.2 置 1,P3.3/INT1 选择下降沿触发。
EX1 = 1;
把 IE.2 置 1,允许 INT1 的请求通过本地闸门。
EA = 1;
把 IE.7 置 1,最后打开 CPU 的中断总闸门。工程中通常先完成各中断源配置、清理标志,再开启本地允许位,最后开启 EA,避免初始化尚未完成时意外进入 ISR。
主循环为空,说明主程序不需要查询按键:
while (1)
{
//Delay_xms(1000);
}
中断函数声明中的编号必须与向量匹配:
void Int0_Routine(void) interrupt 0
void Int1_Routine(void) interrupt 2
interrupt 0 对应 INT0 向量 0003H,interrupt 2 对应 INT1 向量 0013H。这里的 0、2 是 C51 中断编号,不是优先级。函数名称可以自定义,interrupt n 的编号不能写错。
最后要注意,ISR 中的 Delay_xms(10) 会阻塞同级和更低优先级中断,按键抖动仍可能在 ISR 返回后产生第二个下降沿。学习阶段可以用它观察现象,实际项目应尽量缩短 ISR,把消抖和业务处理移到定时任务或主循环中。