
在实际的单片机开发中中断系统是连接硬件事件与软件响应的核心桥梁。无论是按键触发、定时器溢出还是串口接收到数据都需要通过中断机制来确保CPU能够及时响应而无需持续轮询。对于学习单片机汇编语言的同学而言中断系统既是课程的重点也是期末考试的必考难点。它涉及中断源、中断向量、中断允许控制、中断优先级、现场保护与恢复等一系列紧密关联的概念任何一个环节理解不到位都可能导致程序运行异常。本文将以典型的8051系列单片机为背景深入讲解中断系统的完整工作机制。我们将从最基本的中断概念入手逐步拆解中断响应的全过程并结合具体的汇编代码示例演示如何编写中断服务程序。更重要的是我们将针对常见的考点和易错习题进行剖析帮助你不仅理解原理更能应对考试和实际编程中的问题。通过本文你将掌握中断系统的配置流程、中断服务程序的编写规范并学会排查中断不响应、中断嵌套混乱等典型问题。1. 理解中断系统从硬件事件到软件响应中断的本质是一种硬件触发的机制它允许CPU暂停当前正在执行的程序转而去处理一个更紧急的事件处理完毕后再返回原程序继续执行。这个过程类似于你在看书时电话铃响了你标记下当前的阅读位置保护现场去接电话执行中断服务程序接完电话后再回来从标记的位置继续看书恢复现场。1.1 中断系统的核心组件在8051单片机中中断系统主要由以下几个部分构成中断源能够产生中断请求信号的来源。8051通常有5个固定的中断源INT0外部中断0由P3.2引脚引入。T0定时器/计数器0溢出中断。INT1外部中断1由P3.3引脚引入。T1定时器/计数器1溢出中断。TI/RI串行口中断包含发送完成(TI)和接收完成(RI)。中断向量每个中断源在程序存储器ROM中都有一个固定的入口地址称为中断向量。当某个中断被响应时CPU会自动跳转到对应的中断向量地址去执行程序。这是中断服务程序ISR的起点。中断允许寄存器IE这是一个可编程的寄存器用于控制整个中断系统的总开关以及每个中断源的独立开关。只有相应的中断允许位被置1该中断请求才有可能被CPU响应。中断优先级寄存器IP当多个中断同时请求时IP寄存器用于设定它们的优先顺序。高优先级的中断可以打断正在执行的低优先级中断服务程序实现中断嵌套。定时器/计数器控制寄存器TCON其中的某些位用于标识外部中断的触发方式电平触发/边沿触发以及定时器溢出标志。1.2 中断响应的完整流程理解中断响应流程是应对考题的关键。整个过程可以分为以下几个阶段中断请求中断源事件发生如定时器溢出、外部引脚电平变化相应的中断请求标志位如TF0、IE0被硬件自动置1。中断判优如果多个中断请求同时发生硬件会根据IP寄存器的设置和固定的内部顺序INT0 T0 INT1 T1 串口来决定优先响应哪一个。中断响应如果CPU处于开中断状态EA1且该中断源被允许如EX01则在当前指令执行完毕后CPU响应中断。硬件自动完成三件事将下一条指令的地址即断点地址压入堆栈保护。清除正在响应的中断源请求标志位对于边沿触发的外部中断和定时器中断硬件会自动清除对于串口中断和电平触发的外部中断需要软件手动清除。根据中断源将程序计数器PC跳转到对应的中断向量地址。执行中断服务程序ISR程序员在中断向量地址处通常放置一条跳转指令如LJMP跳转到实际的中断处理代码段。在ISR中首先要做的是保护现场将PSW、ACC等可能被破坏的寄存器压栈然后执行具体的处理逻辑最后在返回前恢复现场。中断返回ISR执行到最后一条指令RETI时硬件自动将之前压栈的断点地址弹出到PCCPU从而返回到主程序被中断的地方继续执行。RETI指令还会通知中断系统本次中断处理已结束。2. 环境准备与核心寄存器详解在动手编写代码前必须清楚如何配置控制中断系统的各个寄存器。这些寄存器的每一位都对应着特定的控制功能。2.1 中断允许寄存器IE - Interrupt EnableIE寄存器地址为A8H支持位寻址。它控制着中断的总开关和分开关。位符号地址功能说明7EAAFH总中断允许控制位。EA1CPU开放所有中断EA0CPU屏蔽所有中断。6-AEH保留位。5ET2ADH定时器2中断允许位8052系列才有。4ESACH串行口中断允许位。ES1允许串口中断。3ET1ABH定时器1中断允许位。ET11允许T1中断。2EX1AAH外部中断1允许位。EX11允许INT1中断。1ET0A9H定时器0中断允许位。ET01允许T0中断。0EX0A8H外部中断0允许位。EX01允许INT0中断。配置示例若想允许外部中断0和定时器0中断需要设置EA1, EX01, ET01。SETB EA ; 打开总中断开关 SETB EX0 ; 允许外部中断0 SETB ET0 ; 允许定时器0中断 ; 或者使用字节操作 MOV IE, #10000011B ; EA1, EX01, ET012.2 中断优先级寄存器IP - Interrupt PriorityIP寄存器地址为B8H支持位寻址。它用于设置5个基本中断源的优先级默认为0低优先级。位符号地址功能说明7-BFH保留位。6-BEH保留位。5PT2BDH定时器2优先级8052。4PSBCH串行口中断优先级。3PT1BBH定时器1中断优先级。2PX1BAH外部中断1优先级。3PT0B9H定时器0中断优先级。0PX0B8H外部中断0优先级。规则某位设为1对应中断源为高优先级设为0则为低优先级。当两个不同优先级的中断同时请求时先响应高优先级。当两个相同优先级的中断同时请求时按内部查询顺序INT0 - T0 - INT1 - T1 - 串口响应。高优先级中断可以打断正在执行的低优先级中断服务程序反之则不能。2.3 定时器/计数器控制寄存器TCONTCON的低4位与外部中断相关高4位与定时器相关。地址88H支持位寻址。位符号地址功能说明7TF18FH定时器1溢出标志。溢出时硬件置1响应中断后硬件清0或软件清0。6TR18EH定时器1运行控制位。软件置1启动清0停止。5TF08DH定时器0溢出标志。同TF1。4TR08CH定时器0运行控制位。同TR1。3IE18BH外部中断1请求标志。检测到INT1引脚有效信号时硬件置1响应中断后硬件清0边沿触发模式。2IT18AH外部中断1触发方式控制。IT11边沿触发下降沿有效IT10电平触发低电平有效。1IE089H外部中断0请求标志。同IE1。0IT088H外部中断0触发方式控制。同IT1。注意对于电平触发的外部中断CPU在响应中断后不会自动清除IE0/IE1标志。因此必须在中断服务程序中通过撤销INT0/INT1引脚上的低电平信号来使硬件自动清0否则会引发中断重复响应。2.4 中断向量表中断向量是固定的入口地址。编写程序时必须将跳转到实际ISR的指令放在这些地址上。中断源中断向量地址ROM说明外部中断0 (INT0)0003H通常放置LJMP INT0_ISR定时器0 (T0)000BH通常放置LJMP TIMER0_ISR外部中断1 (INT1)0013H通常放置LJMP INT1_ISR定时器1 (T1)001BH通常放置LJMP TIMER1_ISR串行口 (TI/RI)0023H通常放置LJMP UART_ISR3. 汇编语言中断编程实战理解了寄存器我们就可以开始编写一个完整的中断程序。我们将以实现一个功能为例利用外部中断0INT0接按键控制一个LED接P1.0的亮灭同时利用定时器0中断实现约1秒的延时用于LED闪烁的频率控制。3.1 项目需求与硬件连接分析功能系统上电后LED以1秒为周期闪烁。当按下连接在INT0P3.2引脚上的按键时LED状态立即翻转亮变灭或灭变亮然后继续以新的状态闪烁。硬件假设单片机AT89C51/52或其他兼容8051内核的单片机。LED阳极通过限流电阻接VCC阴极接P1.0。P1.0输出0时LED亮输出1时LED灭。按键一端接地另一端接INT0P3.2引脚。单片机内部上拉电阻使引脚常态为高电平按键按下时变为低电平。晶振假设为12MHz一个机器周期为1μs。3.2 程序结构与初始化代码首先我们需要进行中断系统和定时器的初始化。ORG 0000H ; 程序起始地址 LJMP MAIN ; 跳转到主程序 ORG 0003H ; 外部中断0向量地址 LJMP EXT0_ISR ; 跳转到外部中断0服务程序 ORG 000BH ; 定时器0中断向量地址 LJMP TIMER0_ISR ; 跳转到定时器0服务程序 ORG 0030H ; 主程序放在向量区之后 MAIN: MOV SP, #60H ; 设置堆栈指针避开工作寄存器区和位寻址区 LCALL INIT ; 调用初始化子程序 LOOP: SJMP LOOP ; 主循环等待中断发生 ; 初始化子程序 INIT: ; 1. 初始化LED状态假设初始为灭 SETB P1.0 ; P1.0输出高电平LED灭 ; 2. 设置外部中断0为边沿触发 SETB IT0 ; IT01下降沿触发 ; 3. 配置定时器0为模式116位定时器 MOV TMOD, #01H ; TMOD0000 0001BT0模式1T1模式0未用 ; 4. 计算定时器初值12MHz晶振定时50ms ; 机器周期 12 / 12MHz 1μs ; 定时50ms需要计数次数 N 50000 ; 初值 X 65536 - 50000 15536 3CB0H MOV TH0, #3CH ; 高8位 MOV TL0, #0B0H; 低8位 ; 5. 启动定时器0 SETB TR0 ; TR01启动T0 ; 6. 开启中断 SETB EX0 ; 允许外部中断0 SETB ET0 ; 允许定时器0中断 SETB EA ; 开启总中断 RET关键点解释ORG伪指令用于指定后续代码存放的起始地址。必须将跳转指令准确放在中断向量地址上。定时器初值计算是常考考点。模式1是16位计数器最大计数值65536。初值 65536 - 所需计数值。初始化顺序先配置触发方式、定时器模式再赋初值、启动定时器最后打开中断允许位。这个顺序可以避免意外中断。3.3 中断服务程序编写中断服务程序需要完成现场保护、核心逻辑处理和现场恢复。; 定时器0中断服务程序 - 用于产生1秒延时基准 TIMER0_ISR: PUSH ACC ; 保护现场将ACC压栈 PUSH PSW ; 保护现场将PSW压栈 ; 重装定时器初值为下一次50ms定时做准备 MOV TH0, #3CH MOV TL0, #0B0H ; 软件计数器减1假设R7作为50ms计数器 DJNZ R7, TIMER0_EXIT ; 如果R7不为0跳转到退出 ; 如果R7为0说明20个50ms到了即1秒 MOV R7, #20 ; 重置软件计数器为20 CPL P1.0 ; 取反P1.0LED状态翻转 TIMER0_EXIT: POP PSW ; 恢复现场PSW出栈 POP ACC ; 恢复现场ACC出栈 RETI ; 中断返回必须用RETI ; 外部中断0服务程序 - 响应按键立即翻转LED EXT0_ISR: PUSH ACC PUSH PSW ; 按键消抖简单延时 LCALL DELAY_10MS ; 再次检测INT0引脚确认是有效按键防干扰 JB P3.2, EXT0_EXIT ; 如果P3.2已经是高电平则认为是干扰退出 ; 执行核心功能翻转LED CPL P1.0 ; 等待按键释放避免一次按下多次触发 WAIT_RELEASE: JNB P3.2, WAIT_RELEASE ; 如果P3.2还是低电平循环等待 EXT0_EXIT: POP PSW POP ACC RETI ; 一个简单的10ms延时子程序用于按键消抖 DELAY_10MS: MOV R6, #20 D1: MOV R5, #250 DJNZ R5, $ DJNZ R6, D1 RET关键点解释现场保护与恢复中断可能发生在任何时刻必须保护中断程序中会用到的所有寄存器如ACC、PSW、B以及通用寄存器Rn。通常使用PUSH和POP指令成对操作。PSW保护了标志位和当前工作寄存器组。定时器中断在ISR中必须重装初值否则下次定时会从0开始计数导致定时不准。使用软件计数器如R7来实现更长的定时如1秒。外部中断消抖机械按键会产生抖动需要在检测到中断后延时再判断避免误触发。防干扰与等待释放JB P3.2, EXT0_EXIT用于排除干扰脉冲。WAIT_RELEASE循环确保按键松开后才退出防止一次按下产生多次中断。中断返回必须使用RETI指令它除了恢复PC还会通知中断控制系统该中断已处理完毕允许响应新的同级或低级中断。4. 核心考点与典型习题剖析掌握了基本编程后我们针对考试中常见的题型和易错点进行深入分析。4.1 考点一中断响应条件与流程判断常见题型判断在某种特定条件下如某条指令执行期间某个中断请求是否会被响应何时响应例题假设CPU正在执行一条MOVX A, DPTR指令访问外部RAM需2个机器周期此时外部中断0INT0引脚上出现了一个有效的下降沿IT01。已知EA1EX01且无其他中断请求。问INT0中断是否会被响应何时响应分析与解答条件满足EA和EX0都已打开INT0请求有效满足中断响应条件。响应时机CPU会在当前指令执行完毕后去查询中断请求标志。MOVX指令需要2个机器周期。因此INT0的中断请求会在该MOVX指令的第二个机器周期结束时被采样到并在该指令执行完毕后即下一条指令开始前进入中断响应周期。答案会被响应。响应发生在MOVX A, DPTR指令执行完毕之后。关键记忆点中断采样发生在每个指令的最后一个机器周期。响应发生在当前指令执行完下一条指令开始前。长指令如乘除、MOVX执行期间发生中断也需要等该指令执行完。4.2 考点二中断优先级与嵌套分析常见题型给定中断允许和优先级设置分析多个中断同时或先后发生时的响应顺序。例题设置IE 8FH (10001111B) IP 06H (00000110B)。请分析(1) 若INT0和T1中断同时请求谁先被响应(2) 若CPU正在执行T1的中断服务程序此时INT0请求中断会怎样(3) 若CPU正在执行INT0的中断服务程序此时T1请求中断会怎样寄存器分析IE 10001111BEA1, ES0, ET11, EX10, ET01, EX01。允许INT0、T0、T1中断。IP 00000110BPX10, PT01, PX00。T0为高优先级INT0和T1为低优先级。解答同时请求INT0和T1同时请求且均为低优先级。此时按内部查询顺序决定。查询顺序为INT0 - T0 - INT1 - T1 - 串口。因此INT0先于T1被响应。T1执行中INT0请求T1为低优先级INT0也为低优先级。同级或低级中断不能打断正在执行的中断服务程序。因此CPU不会响应INT0直到T1的ISR执行完毕返回主程序后才会响应INT0。INT0执行中T1请求同理T1不能打断INT0。但这里有一个陷阱T1的中断请求标志TF1在请求时已被置1。虽然本次不能打断但当INT0执行完RETI返回后CPU会立即检测到仍有未处理的T1中断请求因为TF1未被清除并且此时INT0的ISR已结束所以会紧接着响应T1中断而不会先返回主程序。这种现象看起来像是“连续中断”。4.3 考点三中断标志位的清除常见题型分析中断服务程序中是否需要手动清除中断标志以及不清除会导致什么问题。例题在电平触发的外部中断服务程序中为什么通常需要等待外部信号恢复高电平如果不这样做可能发生什么分析与解答原因对于电平触发方式ITx0其中断请求标志IEx是由外部引脚P3.2/P3.3的低电平直接置位的。CPU响应中断后硬件不会自动清除IEx标志。只要引脚上低电平持续存在IEx就保持为1。后果如果ISR执行完毕返回后引脚低电平仍然存在CPU会立即再次检测到有效的中断请求从而再次进入同一个ISR。这就导致了中断的重复响应仿佛程序“卡死”在中断里。解决方案在电平触发的中断服务程序中必须确保在返回前外部引脚的低电平信号已消失如等待按键释放。通常通过循环检测引脚状态实现如示例代码中的WAIT_RELEASE部分。对比记忆中断源触发方式请求标志清除方式外部中断0/1边沿触发IE0/IE1CPU响应中断后硬件自动清除。外部中断0/1电平触发IE0/IE1硬件不会自动清除。需在ISR中确保外部信号恢复高电平。定时器0/1溢出TF0/TF1CPU响应中断后硬件自动清除。也可软件查询清0。串行口发送/接收TI/RI硬件不会自动清除。必须在ISR中用软件指令清除CLR TI 或 CLR RI。4.4 考点四现场保护与恢复的细节常见题型给出一个有缺陷的中断服务程序找出其中现场保护/恢复的错误。例题以下定时器中断服务程序片段有什么问题TIMER_ISR: MOV A, #55H ADD A, R0 MOV R0, A RETI分析与解答 该ISR没有进行任何现场保护。它直接使用了A累加器、R0寄存器以及R0指向的RAM单元。如果主程序或更高优先级中断也在使用这些资源中断返回后这些资源的值已被改变导致主程序运行出错。正确做法在ISR入口处将要用到的寄存器如ACC, PSW, DPTR, B以及R0-R7压栈保护在ISR退出前以相反顺序出栈恢复。TIMER_ISR: PUSH ACC PUSH PSW PUSH 00H ; 假设R0是0组寄存器其地址为00H ; ... 中断处理逻辑 ... POP 00H POP PSW POP ACC RETI注意PUSH和POP的操作对象是直接地址。对于工作寄存器R0-R7需要根据当前使用的寄存器组确定其对应的RAM地址00H-07H对应第0组08H-0FH对应第1组以此类推。5. 常见问题排查与调试技巧在实际编程和实验过程中中断相关的问题往往比较隐蔽。下面列出常见的问题现象和排查思路。5.1 中断完全不响应现象按键按下LED无反应定时时间到程序无动作。排查清单总中断开关是否打开检查EA位是否设置为1。这是最容易被忽略的一步。特定中断允许位是否打开检查EX0、ET0等相应位是否设置为1。中断触发方式设置是否正确检查IT0/IT1。如果是边沿触发确保信号有下降沿如果是电平触发确保低电平持续时间足够长。中断向量地址是否正确检查ORG伪指令是否写错地址以及跳转指令LJMP或AJMP是否写对了中断服务程序的标号。堆栈空间是否足够中断响应和现场保护需要压栈如果堆栈指针SP初始设置过小可能导致堆栈溢出覆盖程序数据引发不可预知的错误。通常将SP初始化为60H或更高。硬件连接是否正确用万用表或逻辑分析仪检查中断引脚的电平变化是否符合预期。5.2 中断只响应一次或响应异常现象按键第一次按下有效后续无效或者LED疯狂闪烁不受控制。排查清单中断标志是否被正确清除这是最常见的原因。对于串口中断必须用CLR TI或CLR RI在ISR中手动清除标志。对于电平触发的外部中断必须在ISR中等待外部信号恢复高电平否则会不断重复进入中断。对于边沿触发的外部中断和定时器中断硬件会自动清除一般无需软件干预。但如果中断被禁止EA0或EXx0时发生了中断请求标志位会被置1并保持直到中断被允许。这种情况需要在初始化时手动清除可能遗留的标志位CLR IE0等。中断服务程序执行时间是否过长如果ISR执行时间超过了中断事件的间隔可能会丢失中断。例如定时器50ms溢出一次但ISR执行需要60ms那么第二次溢出时CPU还在执行第一次的ISR且由于同级中断不能嵌套第二次中断请求可能被忽略。优化ISR代码或将耗时操作移到主循环。是否存在中断嵌套冲突检查IP寄存器设置。如果高优先级中断的ISR执行时间很长可能会“饿死”低优先级中断。5.3 现场保护导致的数据错乱现象主程序中的变量值在中断发生后莫名其妙地改变。排查清单是否保护了所有被修改的寄存器仔细检查ISR凡是用到的ACC、PSW、B、DPTR、Rn以及直接地址单元如果主程序也可能使用就必须保护。PUSH和POP是否成对且顺序相反必须遵循“先进后出”原则。是否错误地改变了工作寄存器组PSW中的RS1和RS0位决定了当前使用哪组R0-R7。如果在ISR中改变了PSW且未妥善保护返回主程序后主程序使用的R0-R7就变成了另一组导致数据错乱。一个常见的做法是在ISR开始时通过设置PSW切换到一个专用于中断的寄存器组这样就不需要保护R0-R7但退出前要恢复原PSW。6. 最佳实践与扩展方向6.1 中断编程最佳实践保持ISR短小精悍中断服务程序应只处理最紧急、最核心的任务如置标志位、读数据、清中断等。复杂的计算、延时、通信等操作应放到主循环中基于标志位来处理。使用软件标志进行通信ISR与主程序之间通过软件标志位变量或字节变量来传递信息。这是最安全、最清晰的异步通信方式。注意重入问题避免在ISR和主程序中共用非原子操作的全局变量。如果共用应考虑使用关中断CLR EA和开中断SETB EA来保护临界区但关中断时间要尽可能短。初始化时清除残留中断标志在开启中断前先清除TCON、SCON中可能残留的中断请求标志位避免一开中断就误入中断。合理规划堆栈空间根据中断嵌套层数和现场保护的数据量预留足够的堆栈空间通常SP初始值设为60H或更高。6.2 扩展方向中断与低功耗设计在许多单片机应用中低功耗是关键指标。中断是实现低功耗休眠-唤醒模式的基石。休眠模式通过执行特定指令如8051的ORL PCON, #01H进入Idle模式CPU停止工作但外设定时器、串口、外部中断仍可运行。中断唤醒当使能的中断事件发生时CPU被唤醒退出休眠模式执行对应的ISR之后继续执行进入休眠模式指令之后的代码。编程模式主程序完成初始化后进入循环处理任务 - 进入休眠 - 被中断唤醒- 处理中断 - 返回循环。这样CPU只在有事件需要处理时才工作极大降低了平均功耗。掌握中断系统不仅是应对考试更是为后续学习更复杂的单片机应用如实时操作系统RTOS的基础打下坚实基础。建议在理解本文示例的基础上尝试修改代码实现中断嵌套、用中断方式扫描矩阵键盘、用中断方式实现串口数据收发等实验从而真正融会贯通。