51单片机教程中:若 CPU 正在执行高优先级的中断,则不能被任何中断源所中断,一直执行到结束,遇到返回指令 RETI,返回主程序后再执行一条指令后才能响应新的中断请求。(其他单片机处理器,没此规定)

发布时间:2026/6/27 6:31:48
51单片机教程中:若 CPU 正在执行高优先级的中断,则不能被任何中断源所中断,一直执行到结束,遇到返回指令 RETI,返回主程序后再执行一条指令后才能响应新的中断请求。(其他单片机处理器,没此规定) 若 CPU 正在执行高优先级的中断则不能被任何中断 源所中断一直执行到结束遇到返回指令 RETI返回主程序后再执行一条指令后才能响 应新的中断请求。一、这段话是标准 51 单片机中断嵌套规则逐句拆解1. 核心规则同优先级 / 低优先级不能打断高优先级中断51 单片机中断只有2 级优先级高优先级、低优先级当 CPU 正在执行高优先级中断服务程序时 任何中断源不管高、低优先级都无法打断当前中断不存在中断嵌套。 必须完整执行完该中断函数直到RETI中断返回指令才退出中断。2. RETI 执行完成后不是立刻响应新中断有一条指令延时执行完RETI返回主程序后CPU 必须先执行完主程序里紧接着的 1 条机器指令才会去查询、响应新的中断请求。为什么要等一条指令CPU 中断查询机制只在每条机器指令执行完毕后才采样中断标志、判断是否响应中断。RETI本身是一条指令执行完 RETI 只是回到主程序断点此时不会立刻查中断 要等断点处那一条指令完整跑完才会扫描中断标志。3. 对比补充完整 51 中断嵌套逻辑方便区分低优先级中断运行时高优先级中断可以打断它实现嵌套高优先级中断运行时所有中断都不能打断禁止嵌套同级中断之间互相不能打断中断响应时机仅每条指令结束后检测中断RETI 返回后也要先执行 1 条指令再响应中断。二、举个场景例子定时器 0 高优先级中断触发CPU 进入中断服务函数此时串口、外部中断 1哪怕设为高优先级同时产生中断标志CPU 不会切换继续跑完定时器 0 中断所有代码执行RETIRETI 返回主程序执行断点处一条完整指令比如i这条指令执行结束CPU 检测到串口 / 外部中断请求才跳转进新中断。三、考点简答总结高优先级中断执行期间所有中断源均无法打断直至 RETIRETI 返回主程序后需先完成一条主程序指令CPU 才会查询并响应新中断。执行完 RETI 返回主程序后CPU 必须先执行完主程序里紧接着的 1 条机器指令才会去查询、响应新的中断请求。执行新1条机器指令的时候PC程序指针加1吗1、先给结论执行这条紧跟 RETI 的机器指令时PC 一定会正常自增完整流程拆解51 内核 PC 工作逻辑步骤 1执行 RETI 指令RETI 是单条机器指令执行过程弹出栈里保存的断点地址赋值给 PC → PC 中断前断点地址也就是中断打断的那条指令的下一条指令地址清除内部中断优先级激活标记允许后续中断响应RETI 执行完毕PC 已经指向主程序待执行的第一条指令RETI 执行阶段 PC 完成跳转本条 RETI 自身执行时 PC 也会正常 1 走完这条指令步骤 2执行 RETI 返回后、中断查询前的那 1 条主程序指令CPU 取出 PC 指向的指令开始译码执行取指阶段PC 先送出地址随后硬件自动 PC PC 指令长度1/2/3 字节机器指令执行阶段完成后这条指令才算完整跑完 →整条指令执行完成前PC 持续正常累加和普通指令执行无任何区别步骤 3这条指令完全执行结束才会扫描所有中断标志只有这条指令从头到尾执行完毕、PC 已经更新完毕CPU 才会检查中断请求若有中断则跳中断服务程序修改 PC若无中断继续顺序取指执行下一条主程序代码。2、举直观例子假设中断发生时主程序正要执行地址0x1000的MOV A,#0x011 字节指令触发中断硬件把0x1000压栈PC 跳转到中断入口中断内执行到 RETI弹出0x1000送入 PC开始执行0x1000这条指令取指PC0x1000 送出地址 → 硬件 PC 0x1001完成运算操作整条指令执行完毕PC 当前 0x1001此时 CPU 才查询中断若有中断PC 被改写跳中断若无中断从 0x1001 继续顺序执行。3、关键补充考点区分为什么必须先执行 1 条指令再查中断51 内核规则仅在每条机器指令执行完毕的边界才检测中断请求RETI 只是恢复断点不算 “一条普通指令执行完成” 的边界所以必须再跑完一条普通指令才到中断检测节点。只有两种场景不会让 PC 正常 1跳转指令AJMP/LJMP/JB/JNC 等、调用 LCALL、中断跳转、RETI/RET执行结束后 PC 被强制改写不再单纯顺序自增 但跳转 / 改写 PC 发生在本条指令执行完成后指令取指阶段 PC 依然会先 1。你问的这条紧跟 RETI 的普通机器指令不属于跳转类执行全程 PC 按正常取指规则累加。同一个中断信号没消除中断子程序完成后是立即响应该中断还是在主程序中执行一条机器指令才响应中断呢结论51 单片机标准规则即便同一个中断标志一直有效没清除执行完RETI退出中断服务程序后不会立刻再次进中断必须先完整执行主程序中紧接着断点的 1 条机器指令这条指令执行完毕后CPU 才检测中断标志发现标志仍为 1再重新进入该中断。完整流程演示中断标志未清零中断触发 → 进入中断服务函数全程没有清除中断标志执行到RETI从堆栈弹出断点地址赋值给 PC清除中断优先级锁存RETI执行完毕回到主程序断点强制执行断点处那一条完整机器指令取指、运算、PC 正常自增全程不会检测中断这一条机器指令全部执行结束CPU 才扫描所有中断标志发现该中断标志依旧置 1满足中断响应条件马上跳转到对应中断入口再次执行中断服务程序。举个对比分清两个容易混淆的点普通指令执行完 → 立刻检测中断RETI指令执行完是特殊节点RETI 结束≠检测中断时机必须再多跑一条普通指令才到中断检测点。配套现象标志不清的死循环中断函数运行 → RETI 返回 → 执行 1 条主程序指令 → 检测到中断标志有效 → 再次进中断 → 循环往复。 不是 RETI 一结束马上冲回中断中间一定夹着一条主程序机器指令。考点简答背诵同一中断标志未清除时执行 RETI 返回后不会立即响应需要先执行主程序中一条完整机器指令指令执行完毕 CPU 查询到未清除的中断标志才会再次响应该中断。同一个中断信号没消除中断子程序完成后是立即响应该中断还是在主程序中执行一条机器指令才响应中断呢还是上次保存的PC计数器值不变立即响应中断呢标准 51 单片机标准答案分三层讲清楚解决你三个疑问1 核心规则必背执行RETI退出中断服务程序后不能立刻响应任何中断必须先完整执行 1 条主程序机器指令这条指令跑完CPU 才会检测中断标志。哪怕中断标志一直置 1 没清除也必须先跑一条主程序指令不会马上再次进中断。2 完整时序中断标志未清零场景假设中断打断主程序时正要执行地址ADDR这条指令硬件自动把ADDR压入堆栈保存这就是断点 PC进入中断服务程序全程没清除中断标志标志位始终 1执行RETI从栈里弹出之前保存的断点地址ADDR赋值给 PC解除高优先级中断屏蔽锁此时 PC ADDR指向被打断的那条主程序指令CPU 取出ADDR处指令完整执行这一条机器指令取指、运算、PC 正常增加这条指令全部执行完毕CPU 才扫描所有中断标志检测到中断标志仍为 1满足中断条件立刻跳转到中断入口再次进中断再次进中断前会把下一条指令的新 PC压栈保存旧断点丢弃更新堆栈。3 回答你的三个问题逐一拆解问题①会不会 RETI 后立即响应中断不会。强制先执行 1 条主程序指令中间有间隔不立即响应。问题②是否要先执行一条机器指令才响应是这是 51 硬件硬性规定RETI 执行完成不属于 “指令结束检测点”只有普通机器指令执行完才检测中断。问题③上次保存的 PC 计数器值不变直接立即响应错误。RETI 第一步就会把栈里保存的旧断点 PC 弹出PC 更新为上次保存的地址然后必须执行这条 PC 指向的指令PC 会随指令执行自动 1旧断点 PC 被修改等一条指令跑完再检测中断若再次触发中断会压入全新的 PC 断点原来保存的 PC 早已失效、不再保留。4 极简流程示例直观理解主程序执行到0x2000指令时中断触发 → 栈存 PC0x2000中断里没清标志执行 RETI → PC 0x2000执行 0x2000 这条指令PC 变成 0x2001指令结束检测到中断标志仍为 1跳转中断入口把新 PC0x2001 压栈保存重新执行中断。考试简答总结同一中断标志未清除RETI 返回后不会立即响应中断需先完整执行主程序一条机器指令指令结束后 CPU 检测到有效中断标志才再次响应RETI 会先恢复上次保存的断点 PC执行指令过程中 PC 会正常自增不会保持原有 PC 不变直接跳转中断。中断信号没有消除一直触发中断程序会卡在中断处吗不会往下进行了吗结论51 单片机会卡死主程序几乎完全无法正常持续运行但不是一直待在中断函数里不出来而是反复来回切换中断→RETI→跑 1 条主程序指令→立刻又进中断无限循环。完整过程中断标志未清除进入中断服务程序执行完所有中断内代码执行RETIRETI恢复断点 PC回到主程序只执行 1 条机器指令这条指令执行完毕CPU 检测中断标志发现标志依旧为 1马上再次跳回同一个中断服务程序重复上面 1~4 步骤无限往复。为什么说 “主程序走不下去”主程序里while(1)循环、LED 刷新、按键扫描、延时、串口发送等所有逻辑每次只能跑一条指令就被打断宏观上看起来程序卡在中断功能完全失效LED 不会持续闪烁按键检测完全没机会正常轮询屏幕不刷新喂狗代码长期得不到执行看门狗超时直接重启单片机。区分两种 “卡死” 表象1. 软件标志没清零TI/RI、电平外部中断不是停在中断里不动是频繁来回切换CPU 一直在中断和单条主指令之间横跳主程序无法连续执行。2. 如果是电平触发外部中断外部引脚持续有效低电平就算你在中断里手动IE00清标志硬件会立刻再次置 1 标志结果同上无限重复进出中断。 解决外部硬件撤销触发电平再清标志。3. 硬件自动清零中断边沿触发 INT0/INT1、T0/T1 溢出 TF只要只触发一次标志硬件自动清零不会反复进中断不会卡死 只有持续不断产生新的溢出 / 边沿信号才会频繁进中断。举个直观例子主循环c运行while(1) { LED ~LED; // 翻转LED delay_ms(500); }中断标志未清除时运行效果 RETI 返回后只跑LED ~LED这一条指令马上又进中断 延时函数根本没有机会执行LED 肉眼看不出闪烁程序看起来卡死不动。简答背诵中断标志未消除、持续有效时程序不会停在中断函数内部不退出而是执行 RETI 返回后主程序仅能执行一条机器指令就会再次进入中断无限循环主程序无法连续运行整体功能瘫痪等同于卡死。中断信号持续触发中断虽然反复发生但是pc会往下走一步才会再次响应中断完全正确51 单片机硬件机制就是如此分流程讲清楚完整循环过程中断标志一直有效、没清除触发中断 → 保存断点 PC跳中断服务程序执行完中断所有代码执行RETI从堆栈弹出之前保存的断点地址赋值给 PC放开中断优先级屏蔽PC 指向断点那条指令完整执行这 1 条机器指令取指时 PC 自动加上本条指令字节长度PC 实实在在向前走了一步这条指令全部执行完毕后CPU 才检测中断标志标志仍为 1满足中断条件立刻再次进入中断把更新后的 PC压栈作为新断点重复 2~5无限循环关键两点PC 确实会往下走一步执行一条完整机器指令、PC 自增不会停在原地直接重进中断但主程序只能单次执行一条指令无法连续运行后续代码宏观表现就是程序卡死、功能失效。举地址实例假设中断打断时 PC0x1000这条指令没执行完进中断栈存0x1000中断结束执行 RETIPC0x1000执行 0x1000 指令PC 变为0x1001PC 向前走一步指令结束检测中断标志有效再次进中断栈存入新断点0x1001下一轮 RETI 回来执行 0x1001PC 再变成 0x1002……能看到 PC 每次都会前进一条指令地址只是前进一步马上又被中断打断。考试一句话总结中断标志持续有效时执行 RETI 返回后PC 会先执行一条主程序机器指令并完成自增之后 CPU 检测到中断请求才再次响应中断PC 每次都会向下走一步不会原地直接重复进入中断。其他的处理器也是相同的机制吗搜索 4 个关键词参考 24 篇资料结论绝大多数通用规则一致但「RETI 返回后强制多跑 1 条指令」是 51 单片机独有的特殊限制其他处理器没有这条硬性规定分两层讲清楚通用共性、关键差异一、所有 CPU 通用的底层规则全部处理器都遵守任何中断必须等当前正在执行的整条指令完全跑完才会检测、响应中断不会指令执行一半跳中断保证指令原子完成51、STM32/Cortex-M、RISC-V、x86 全部统一。若中断标志持续置 1、没软件清除退出中断返回主程序后只要检测到 pending 中断会立刻再次进中断宏观卡死主程序每次只能跑一小段代码。中断检测窗口统一每条指令执行完毕的边界才扫描中断请求。二、51 单片机独有的特殊硬性约束其他芯片没有51 官方明确三条中断封锁条件第三条是独有特性若当前刚执行完RETI、或是操作 IE/IP 中断寄存器的指令必须额外再完整执行 1 条机器指令才允许检测新中断。流程RETI 恢复断点 PC → 执行断点那 1 条指令PC 正常 1→ 指令结束才查中断哪怕中断标志一直有效也不能 RETI 一返回就立刻进中断中间强制夹一条主程序指令。三、主流处理器对比无 51 这条特殊限制1. Cortex-M 系列STM32、GD32 等 ARM 单片机最常用中断返回指令BX LR异常返回执行完 BX LR、硬件恢复 PC 回到断点后不需要强制多跑一条指令下一个时钟周期、只要到达当前指令边界就直接检测中断场景中断标志没清除 → BX LR 返回断点刚恢复 PC还没取指执行断点指令就检测到 pending 中断直接再次跳中断PC 不会向前走一步。简单说51 是「先跑 1 条再查」Cortex-M 是「返回后立刻查不用跑那条指令」。2. RISC-V 内核单片机CH32V、GD32V 等中断返回mretmret 执行完毕、PC 恢复断点地址硬件立刻进入中断检测阶段无 “强制执行一条指令” 的锁死规则中断标志未清除会直接再次抢占断点指令不会执行。3. x86 电脑 CPUPC、工控机中断返回IRETIRET 完成上下文恢复后直接在下一条指令边界检测 INTR 中断没有额外延时一条指令的机制。4. 老式 ARM7/ARM9非 Cortex-M同样无 51 那种 RETI 专属锁中断返回后直接检测中断不用强制执行一条主程序指令。四、用 “中断标志没清除” 的场景直观对比场景 151 单片机你之前学的机制ISR 执行 RETI → PC 断点地址 →完整执行 1 条断点指令PC1→ 指令结束检测到标志 1 → 再次进中断。每次循环 PC 都会往前走一步。场景 2STM32 (Cortex-M)ISR 执行 BX LR → PC 断点地址 → 还没执行这条指令硬件检测到中断 pending → 直接重新进入中断服务程序。断点那条指令永远不会执行PC 不会前进。五、考点极简总结通用共性所有 CPU 都只能在单条指令执行完后检测中断不能打断正在执行的指令中断标志不清都会反复触发、主程序卡死。核心区别MCS-51 独有执行 RETI/IE/IP 指令后强制先执行1 条完整机器指令再检测中断PC 一定会向前走一步Cortex-M/RISC-V/x86 等绝大多数处理器中断返回后无需额外执行一条指令只要存在未清除的中断标志会直接再次响应断点指令不会执行。中断出栈是在中断返回之前进行吗结论分两种栈操作严格区分「中断进入压栈」和「中断返回出栈」1. MCS-51 单片机RETI1进入中断时自动硬件压栈CPU 响应中断跳转前硬件自动把当前断点 PC 压入堆栈SP 先 1再存 PC 低字节SP 再 1存 PC 高字节这一步发生在进中断服务程序之前不是返回阶段。2中断返回 RETI出栈操作在 RETI 指令内部完成是返回动作的第一步执行RETI的完整硬件流程先出栈从堆栈弹出保存的断点 PC先取高 8 位再取低 8 位SP 连续减 2将弹出的地址赋值给 PC回到主程序断点清除内部高优先级中断封锁标记RETI 指令执行完毕。出栈是 RETI 指令内部最先执行的动作在真正回到主程序、执行主程序指令之前完成。出栈 ≡ 返回操作的前置步骤没出栈就没法恢复 PC、返回主程序。2. Cortex-M / RISC-V 等现代内核进入中断硬件自动压栈进入异常 / 中断时CPU 自动把 R0~R3、LR、PC、xPSR 等寄存器压栈硬件自动完成。中断返回BX LR /mret先出栈再恢复现场异常返回指令执行时硬件自动从栈中弹出之前保存的全部寄存器恢复 PC 与状态寄存器之后才回到主程序。同样逻辑出栈动作发生在中断返回指令执行期间回到主程序代码之前。3. 补充关键区分考试易混点压栈响应中断跳转前自动完成保存断点防止返回后找不到程序执行位置。出栈中断返回指令RETI/BX LR/mret内部第一步操作在回到主程序之前完成不出栈就无法恢复 PC 断点地址无法返回。手动 PUSH/POP汇编自定义保存寄存器PUSH 写在中断函数开头进入中断后、业务逻辑前手动压寄存器POP 写在中断末尾、RETI 之前软件手动出栈必须写在 RETI 前面如果 POP 放在 RETI 之后程序直接跑飞。举 51 汇编例子直观看懂asmINT0_ISR: PUSH ACC ; 手动保存ACC先压栈 PUSH PSW ; 中断业务处理... POP PSW ; 手动出栈在RETI之前 POP ACC RETI ; 硬件自动弹出PC断点返回前硬件出栈一句话背诵硬件自动保存的断点 PC / 寄存器会在中断返回指令执行过程中、回到主程序之前完成出栈代码里手动 PUSH 的寄存器必须在 RETI 前用 POP 手动出栈。