嵌入式系统 - 中断
中断是由硬件或软件发给处理器的信号,指示需要立即处理的事件。每当发生中断时,控制器都会完成当前指令的执行,并开始执行中断服务程序 (ISR) 或中断处理程序。ISR 告诉处理器或控制器中断发生时该做什么。中断可以是硬件中断或软件中断。
硬件中断
硬件中断是由外部设备(如磁盘控制器或外部外设)发送给处理器的电子警报信号。例如,当我们按下键盘上的键或移动鼠标时,它们会触发硬件中断,导致处理器读取按键或鼠标位置。
软件中断
软件中断是由异常情况或指令集中导致处理器执行时中断的特殊指令引起的。例如,如果处理器的算术逻辑单元运行将数字除以零的命令,则会导致除以零异常,从而导致计算机放弃计算或显示错误消息。软件中断指令的工作方式类似于子程序调用。
什么是轮询?
持续监控的状态称为轮询。微控制器不断检查其他设备的状态;在此过程中,它不执行其他操作,并消耗所有处理时间进行监控。这个问题可以通过使用中断来解决。
在中断方法中,控制器仅在发生中断时才响应。因此,控制器不需要定期监控接口和内置设备的状态(标志、信号等)。
中断与轮询
这里有一个比喻,可以区分中断和轮询:
中断 | 轮询 |
---|---|
中断就像一个店主。如果需要服务或产品,他会去找他,并告知他自己的需求。在中断的情况下,当收到标志或信号时,它们会通知控制器需要对其进行服务。 | 轮询方法就像一个销售人员。销售人员挨家挨户地请求购买产品或服务。类似地,控制器逐一监控所有设备的标志或信号,并为需要其服务的任何组件提供服务。 |
中断服务程序
对于每个中断,都必须有一个中断服务程序 (ISR) 或中断处理程序。当发生中断时,微控制器会运行中断服务程序。对于每个中断,内存中都有一个固定的位置保存其中断服务程序 ISR 的地址。预留用于保存 ISR 地址的内存位置表称为中断向量表。
中断向量表
8051 中有六个中断,包括复位。
中断 | ROM 位置 (十六进制) | 引脚 |
---|---|---|
中断 | ROM 位置 (十六进制) | |
串行 COM (RI 和 TI) | 0023 | |
定时器 1 中断 (TF1) | 001B | |
外部硬件中断 1 (INT1) | 0013 | P3.3 (13) |
外部硬件中断 0 (INT0) | 0003 | P3.2 (12) |
定时器 0 (TF0) | 000B | |
复位 | 0000 | 9 |
当复位引脚被激活时,8051 会跳转到地址位置 0000。这是上电复位。
为定时器预留了两个中断:一个用于定时器 0,另一个用于定时器 1。在中断向量表中,内存位置分别为 000BH 和 001BH。
为硬件外部中断预留了两个中断。端口 3 中的引脚 12 和引脚 13 分别用于外部硬件中断 INT0 和 INT1。在中断向量表中,内存位置分别为 0003H 和 0013H。
串行通信有一个属于接收和发送的单个中断。内存位置 0023H 属于此中断。
执行中断的步骤
当中断被激活时,微控制器会执行以下步骤:
微控制器关闭当前正在执行的指令,并将下一条指令的地址 (PC) 保存到堆栈中。
它还会在内部保存所有中断的当前状态(即,不在堆栈中)。
它跳转到中断向量表中保存中断服务程序地址的内存位置。
微控制器从中断向量表中获取 ISR 的地址并跳转到它。它开始执行中断服务子程序,即 RETI(从中断返回)。
执行 RETI 指令后,微控制器返回到中断发生的位置。首先,它通过将堆栈的顶部字节弹出到 PC 中来获取程序计数器 (PC) 地址。然后,它从该地址开始执行。
边沿触发与电平触发
中断模块有两种类型:电平触发或边沿触发。
电平触发 | 边沿触发 |
---|---|
电平触发中断模块只要中断源的电平被置位就会始终产生中断。 | 边沿触发中断模块仅在其检测到中断源的置位边沿时才产生中断。当中断源电平实际变化时,边沿被检测到。它也可以通过周期性采样并在前一个样本被取消置位时检测到置位电平来检测。 |
如果中断源在固件中断处理程序处理中断时仍然被置位,则中断模块将重新生成中断,导致再次调用中断处理程序。 | 边沿触发中断模块可以立即采取行动,无论中断源的行为如何。 |
电平触发中断对于固件来说很麻烦。 | 边沿触发中断使固件的代码复杂性保持较低,减少了固件的条件数量,并在处理中断时提供了更大的灵活性。 |
启用和禁用中断
复位后,即使中断被激活,所有中断也会被禁用。必须使用软件启用中断,以便微控制器响应这些中断。
IE(中断启用)寄存器负责启用和禁用中断。IE 是一个按位寻址的寄存器。
中断启用寄存器
EA | - | ET2 | ES | ET1 | EX1 | ET0 | EX0 |
---|
EA - 全局启用/禁用。
- - 未定义。
ET2 - 启用定时器 2 中断。
ES - 启用串口中断。
ET1 - 启用定时器 1 中断。
EX1 - 启用外部 1 中断。
ET0 - 启用定时器 0 中断。
EX0 - 启用外部 0 中断。
要启用中断,我们执行以下步骤:
IE 寄存器的位 D7 (EA) 必须为高电平才能使寄存器的其余部分生效。
如果 EA = 1,则将启用中断,如果它们在 IE 中的相应位为高电平,则将对其进行响应。如果 EA = 0,则任何中断都不会响应,即使它们在 IE 寄存器中的关联引脚为高电平。
8051 中的中断优先级
我们可以通过将更高优先级分配给任何一个中断来更改中断优先级。这是通过编程名为IP(中断优先级)的寄存器来实现的。
下图显示了 IP 寄存器的位。复位后,IP 寄存器包含全 0。要将更高优先级赋予任何中断,我们将 IP 寄存器中的相应位设置为高电平。
- | - | - | - | PT1 | PX1 | PT0 | PX0 |
---|
- | IP.7 | 未实现。 |
- | IP.6 | 未实现。 |
- | IP.5 | 未实现。 |
- | IP.4 | 未实现。 |
PT1 | IP.3 | 定义定时器 1 中断优先级。 |
PX1 | IP.2 | 定义外部中断 1 优先级。 |
PT0 | IP.1 | 定义定时器 0 中断优先级。 |
PX0 | IP.0 | 定义外部中断 0 优先级。 |
中断中的中断
如果 8051 正在执行属于一个中断的中断服务程序,而另一个中断被激活会发生什么?在这种情况下,高优先级中断可以中断低优先级中断。这称为中断中的中断。在 8051 中,低优先级中断可以被高优先级中断中断,但不能被任何其他低优先级中断中断。
通过软件触发中断
有时我们需要通过模拟来测试 ISR。这可以通过简单的指令来实现,这些指令将中断设置为高电平,从而导致 8051 跳转到中断向量表。例如,将定时器 1 的 IE 位设置为 1。指令SETB TF1 将中断 8051 当前正在执行的操作,并强制其跳转到中断向量表。