找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1676|回复: 0
打印 上一主题 下一主题
收起左侧

32位单片机中断深度理解

[复制链接]
跳转到指定楼层
楼主
ID:933150 发表于 2023-3-27 22:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


## 中断

### 简介

- 中断(Interrupt)是一种事件响应机制,可以使单片机在处理其他任务的同时及时响应并处理紧急事件,提高系统的实时性能和可靠性。
- 中断是一种异步事件响应方式,当指定的事件发生时,中断处理器会立即暂停当前程序执行,转而执行中断服务程序,处理完中断事件后再返回原来的程序执行流程。

### 组成部分

- 在单片机中,中断由中断源、中断控制器和中断服务程序组成。

#### 中断源

- 产生中断事件的硬件设备或软件程序,如定时器溢出、外部输入信号、串口接收数据等。

#### 中断控制器

- 负责检测中断源产生的中断请求,并向CPU发送中断信号,在CPU完成当前指令后跳转到相应的中断服务程序。

在32位单片机中,中断控制器通常由NVIC(Nested Vector Interrupt Controller)实现。NVIC支持多达240个中断源,可以灵活配置优先级、屏蔽中断等设置。

下面是一个在STM32F4单片机上使用NVIC实现中断初始化的示例代码:

```c
// 初始化中断
void init_interrupt(void) {
    // 使能IRQ中断
    NVIC_SetPriorityGrouping(NVIC_PriorityGroup_4);
    // 初始化中断优先级
    NVIC_Init(&NVIC_InitStructure);
}
```

#### 中断服务程序

- 是一个用于处理特定中断事件的程序。
- 包括清除中断标志位、保存现场、执行特定操作、恢复现场等步骤,最后通过返回指令返回到原来的任务流程。

在32位单片机中,中断服务程序通常由ISR(Interrupt Service Routine)实现。ISR是一种特殊的函数,具有固定的格式和命名规则,以便编译器正确地生成中断向量表和中断服务程序入口地址。例如,对于外部中断EXTI1的中断服务程序,其函数定义应该如下所示:

```c
// EXTI1中断服务程序
void EXTI1_IRQHandler(void) {
    // 处理中断事件
    // ...
    // 清除中断标志位
    EXTI_ClearITPendingBit(EXTI_Line1);
}
```

### 响应过程

- 中断响应过程主要包括中断源产生中断请求、中断控制器检测到中断请求、CPU暂停当前任务跳转到中断服务程序、中断服务程序处理中断事件、CPU返回原任务继续执行等几个步骤。

以下是中断响应过程的详细说明:

1. 中断源产生中断请求

当某个硬件设备或软件程序产生了一个需要CPU立即处理的事件时,会向中断控制器发送中断请求信号。例如,当定时器溢出时,定时器会向中断控制器发送一个定时器中断请求。

2. 中断控制器检测到中断请求

中断控制器不断检测是否有中断请求发生,当检测到中断请求时,会向CPU发送中断信号,通知CPU有中断事件需要处理。

在32位单片机中,中断控制器通常由NVIC实现。NVIC会根据中断优先级和屏蔽设置等信息来判断是否响应中断请求,并向CPU发送相应的中断信号。

3. CPU暂停当前任务,跳转到中断服务程序

当CPU收到中断信号后,会暂停正在执行的任务,并将当前指令的下一条指令地址(PC)保存到堆栈中,以便在中断服务程序执行完后返回原来的任务流程。然后,CPU会从中断向量表中读取相应中断源对应的中断服务程序入口地址,并跳转到该地址开始执行中断服务程序。

4. 中断服务程序处理中断事件

中断服务程序是用于处理特定中断事件的程序,它包括清除中断标志位、保存现场、执行特定操作、恢复现场等步骤,最后通过返回指令返回到原来的任务流程。

在中断服务程序中,需要清除中断标志位以便下一次中断响应,例如,对于外部中断EXTI1的中断服务程序,可以使用以下代码清除中断标志位:

```c
// 清除中断标志位
EXTI_ClearITPendingBit(EXTI_Line1);
```

5. CPU返回原任务继续执行

当中断服务程序执行完毕后,CPU会从堆栈中读取之前保存的PC值,恢复执行原来的任务流程,即返回到之前暂停的任务处,继续执行原来的指令。

### 中断向量表

- 中断向量表(Interrupt Vector Table)是一种特殊的数据结构,用于存储所有中断服务程序的入口地址。
- 在单片机启动时,中断向量表会被加载到固定的内存位置,并在中断响应时被CPU使用。
- 它通常是一个连续的存储区域,每个中断源都占据一个固定的位置。
- 当中断控制器检测到中断请求时,会将相应的中断编号作为索引,从中断向量表中读取对应的中断服务程序入口地址,并跳转到该地址开始执行中断服务程序。

以下是在STM32F4单片机上定义中断向量表的示例代码:

```c
// 中断向量表
void (* const InterruptVectorTable[]) (void) __attribute__ ((section(".isr_vector"))) = {
    (void (*)(void)) &_estack,    // 栈指针
    Reset_Handler,                // 复位中断
    NMI_Handler,                  // 非屏蔽中断
    HardFault_Handler,            // 硬件故障中断
    MemManage_Handler,            // 存储器管理中断
    BusFault_Handler,             // 总线错误中断
    UsageFault_Handler,           // 用法错误中断
    0,                            // 保留
    0,                            // 保留
    0,                            // 保留
    0,                            // 保留
    SVC_Handler,                  // 系统调用中断
    DebugMon_Handler,             // 调试监视中断
    0,                            // 保留
    PendSV_Handler,               // 挂起中断
    SysTick_Handler,              // 系统定时器中断
    // 外部中断0~15的中断服务程序
    EXTI0_IRQHandler,
    EXTI1_IRQHandler,
    EXTI2_IRQHandler,
    EXTI3_IRQHandler,
    EXTI4_IRQHandler,
    EXTI9_5_IRQHandler,
    EXTI15_10_IRQHandler,
    // 更多的外部中断服务程序
};
```

### 注意事项

- 在使用中断时,需要注意一些问题,如中断的优先级、中断嵌套、中断延迟等,以确保系统的稳定性和可靠性。

#### 中断优先级

- 中断优先级可以决定哪个中断优先处理。
- 在NVIC中,中断优先级分为4位或3位,越高的值表示越低的优先级。
- 在设计中,需要根据具体应用场景来设置合理的中断优先级,以避免因低优先级中断被屏蔽而导致紧急事件无法及时处理的情况。

以下是在STM32F4单片机上设置中断优先级的示例代码:

```c
// 设置某个中断的优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;    // 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;           // 子优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
```

#### 中断嵌套

- 中断响应时,如果又有新的中断请求产生,就会发生中断嵌套。
- 在处理中断嵌套时,需要注意保存现场和恢复现场的顺序,以免出现逆序恢复导致系统错误的情况。

以下是在STM32F4单片机上处理中断嵌套的示例代码:

```c
// 外部中断0服务程序
void EXTI0_IRQHandler(void) {
    // 保存现场
    NVIC_SystemHandlerPendingBitConfig(SYS_TICK, DISABLE);    // 禁用SysTick中断
    __disable_irq();                                          // 禁用所有中断
    // 处理中断
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) {
        EXTI_ClearITPendingBit(EXTI_Line0);
        // 触发外部中断1
        EXTI_GenerateSWInterrupt(EXTI_Line1);
    }
    // 恢复现场
    __enable_irq();                                           // 使能所有中断
    NVIC_SystemHandlerPendingBitConfig(SYS_TICK, ENABLE);     // 使能SysTick中断
}
```

#### 中断延迟

- 当中断服务程序执行时间过长或存在阻塞操作时,会导致其他中断响应受到影响,甚至出现错误。
- 在设计中,需要尽量避免中断延迟,并采取一些手段优化中断服务程序的执行效率,以确保系统实时性。

以下是降低一些常见中断延迟的方法:

- 将中断服务程序的执行时间尽量缩短;
- 禁止在中断服务程序中使用延时函数、锁存器等方式;
- 对于需要较长时间处理的中断事件,可以通过将其放在主循环中异步处理的方式来避免中断延迟。



#### 响应优先级和先占优先级
在中断处理中,常常涉及到两个概念:响应优先级和先占优先级。

响应优先级是指中断请求发生时,CPU按照一定的优先级顺序来处理多个中断请求。具有更高响应优先级的中断会在低优先级中断之前得到处理。

先占优先级是指在某个中断服务程序执行期间,不允许其他优先级低于其自身的中断干扰它的执行。如果此时发生了优先级更高的中断请求,则需要等待当前中断服务程序执行完成后再进行处理,这就是优先级抢占。

在STM32F4单片机中,中断响应优先级分为抢占优先级和响应优先级,其中抢占优先级用于决定同优先级中断之间的抢占关系,而响应优先级则用于决定不同优先级中断之间的响应顺序。

以下是在STM32F4单片机中设置中断优先级的示例代码:

```c
// 设置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;    // 抢占优先级为1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;           // 响应优先级为1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
```

在该示例中,抢占优先级为1,响应优先级为1,表示该中断服务程序的优先级比所有响应优先级为2及以下的中断都要高。

总之,在设计中断处理过程时,需要合理设置中断响应和抢占优先级,以满足系统实时性和稳定性的要求。


### 注意事项:

#### 中断开关

在使用中断前,需要先打开中断总开关,使得单片机可以响应中断请求。在STM32F4单片机中,可以通过以下代码打开中断总开关:

```c
// 打开中断总开关
__enable_irq();
```

在使用完中断后,需要关闭中断总开关,以避免产生其他不必要的中断响应。在STM32F4单片机中,可以通过以下代码关闭中断总开关:

```c
// 关闭中断总开关
__disable_irq();
```

#### 中断优先级

在使用中断时,需要根据实际需求设置中断优先级,以确保不同优先级中断的响应顺序和抢占关系符合设计要求。如果中断优先级设置不当,可能会导致系统性能下降或出现严重错误。

#### 中断嵌套

当多个中断同时发生时,可能会出现中断嵌套的情况,这会影响中断处理效率和正确性。因此,在编写中断服务程序时,需要考虑中断嵌套的情况,并采取相应的措施避免嵌套带来的问题。

#### 中断延迟

当中断服务程序执行时间过长或存在阻塞操作时,会导致其他中断响应受到影响,甚至出现错误。因此,在设计中,需要尽量避免中断延迟,并采取一些手段优化中断服务程序的执行效率,以确保系统实时性。

#### 中断与优先级反转

中断与优先级反转是一种由于中断优先级问题导致的系统问题,这可能会使得高优先级的任务被低优先级的中断事件阻塞。在设计中需要避免出现中断与优先级反转的情况,并采取一些手段解决该问题。

总之,在使用中断时,需要全面考虑系统的实时性、可靠性和稳定性,以确保中断处理能够达到预期的效果。

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表