STM32单片机中断机制揭秘:NVIC和SysTick深入剖析
发布时间: 2024-07-04 00:55:29 阅读量: 219 订阅数: 43
![STM32单片机中断机制揭秘:NVIC和SysTick深入剖析](https://img-blog.csdnimg.cn/e1a4d1d5416043dab1948cc56fc38e61.png)
# 1. STM32中断机制概览**
STM32单片机采用嵌套向量中断控制器(NVIC)和系统滴答定时器(SysTick)实现中断机制。NVIC负责管理中断优先级、向量表和中断处理,而SysTick则提供精确的定时中断。
中断机制是STM32单片机的重要组成部分,它允许外部事件或内部操作触发中断处理程序,从而实现对事件的快速响应。中断处理程序可以执行特定的任务,例如处理外部中断、更新数据或控制外设。
# 2. NVIC中断控制器
### 2.1 NVIC结构与配置
#### 2.1.1 NVIC寄存器概述
NVIC(Nested Vectored Interrupt Controller)是STM32单片机中断控制器的核心,负责管理和处理所有中断请求。NVIC寄存器位于STM32的系统控制外设(SCB)中,主要包括:
- **ISERx(中断使能寄存器):**用于使能或禁止特定中断源。
- **ICERx(中断禁止寄存器):**用于禁止特定中断源。
- **ISPRx(中断挂起寄存器):**用于挂起或解除挂起特定中断源。
- **ICPRx(中断清除寄存器):**用于清除特定中断源的挂起状态。
- **IPRxy(中断优先级寄存器):**用于配置特定中断源的优先级。
#### 2.1.2 中断优先级配置
NVIC支持中断优先级配置,允许开发者根据中断的重要性设置中断处理顺序。STM32的NVIC支持4位优先级,共16个优先级等级(0-15)。优先级较高的中断源将优先于优先级较低的中断源处理。
中断优先级配置通过IPRxy寄存器进行,其结构如下:
```
IPRxy = [PRI_n:0]
```
其中,PRI_n:0表示中断源n的优先级,范围为0-15。
### 2.2 中断向量表
#### 2.2.1 向量表地址和结构
中断向量表是存储中断处理函数地址的数组,当发生中断时,NVIC会自动跳转到向量表中相应的中断处理函数处。STM32的向量表位于SRAM的起始地址(通常为0x0000 0000)。
向量表结构如下:
```
| 向量表地址 | 中断源 | 中断处理函数地址 |
|---|---|---|
| 0x0000 0000 | 复位中断 | Reset_Handler |
| 0x0000 0004 | 非屏蔽中断 | NMI_Handler |
| 0x0000 0008 | 硬故障中断 | HardFault_Handler |
| ... | ... | ... |
| 0x0000 0FFF | 最后一个中断 | Last_Handler |
```
#### 2.2.2 中断处理函数
中断处理函数是响应特定中断源的中断服务例程。中断处理函数的名称必须以"Handler"结尾,并且必须符合以下格式:
```
void Handler_Name(void)
{
// 中断处理代码
}
```
中断处理函数中应包含中断处理逻辑,例如读取中断标志寄存器、清除中断挂起状态、执行中断处理操作等。
# 3. SysTick定时器
### 3.1 SysTick寄存器与配置
#### 3.1.1 SysTick寄存器概述
SysTick定时器是STM32单片机中集成的16位可编程定时器,主要用于系统定时和延时操作。其寄存器组位于SCB(系统控制块)中,包括以下寄存器:
- **SysTick_CSR**:控制和状态寄存器,用于控制定时器的配置和状态。
- **SysTick_RVR**:重载值寄存器,用于设置定时器的重载值。
- **SysTick_CVR**:当前值寄存器,用于读取定时器的当前值。
- **SysTick_CALIB**:校准值寄存器,用于校准定时器的时钟频率。
#### 3.1.2 定时器配置与启动
配置SysTick定时器需要以下步骤:
1. **设置重载值:**通过写入SysTick_RVR寄存器设置定时器的重载值,即定时器计数到0后重新加载的值。
2. **使能定时器:**通过设置SysTick_CSR寄存器的ENABLE位使能定时器。
3. **选择时钟源:**通过设置SysTick_CSR寄存器的CLKSOURCE位选择定时器的时钟源,可以是系统时钟或外部时钟。
4. **设置中断:**通过设置SysTick_CSR寄存器的TICKINT位使能定时器中断。
```c
// 配置SysTick定时器
void SysTick_Config(uint32_t ticks)
{
// 设置重载值
SysTick->LOAD = ticks - 1;
// 使能定时器
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
// 选择时钟源为系统时钟
SysTick->CTRL &= ~SysTick_CTRL_CLKSOURCE_Msk;
// 使能中断
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}
```
### 3.2 SysTick中断处理
#### 3.2.1 中断处理函数
SysTick定时器中断处理函数通常定义为`SysTick_Handler`,在中断发生时执行。该函数可以执行以下操作:
- 清除中断标志位
- 执行定时器相关操作(例如更新计数器、触发事件等)
- 执行用户自定义代码
```c
// SysTick中断处理函数
void SysTick_Handler(void)
{
// 清除中断标志位
SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk;
// 执行定时器相关操作
// 执行用户自定义代码
}
```
#### 3.2.2 定时器中断应用
SysTick定时器中断可以用于多种应用,包括:
- **系统定时:**提供精确的系统定时,用于调度任务或测量时间间隔。
- **延时操作:**通过等待SysTick中断发生来实现延时操作。
- **PWM输出:**通过周期性更新SysTick_RVR寄存器来实现PWM输出。
- **时钟校准:**通过测量SysTick中断的频率来校准系统时钟。
# 4. STM32中断机制实践**
**4.1 中断配置与处理示例**
**4.1.1 外部中断配置**
外部中断是STM32中断机制中常用的中断类型,用于响应外部事件。以GPIO中断为例,配置外部中断需要以下步骤:
1. **配置GPIO引脚为中断模式:**
```c
// 使能GPIO时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// 设置GPIO引脚为输入模式
GPIOA->MODER &= ~(GPIO_MODER_MODER0);
// 设置GPIO引脚为中断模式
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_1;
```
2. **配置NVIC中断控制器:**
```c
// 设置中断优先级
NVIC_SetPriority(EXTI0_IRQn, 2);
// 使能中断
NVIC_EnableIRQ(EXTI0_IRQn);
```
3. **编写中断处理函数:**
```c
void EXTI0_IRQHandler(void)
{
// 清除中断标志位
EXTI->PR |= EXTI_PR_PR0;
// 执行中断处理逻辑
// ...
}
```
**4.1.2 定时器中断配置**
定时器中断是STM32中断机制中另一种常用的中断类型,用于产生周期性中断。以TIM2定时器为例,配置定时器中断需要以下步骤:
1. **配置定时器:**
```c
// 使能TIM2时钟
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
// 设置定时器参数
TIM2->PSC = 1000 - 1; // 分频系数
TIM2->ARR = 1000 - 1; // 自动重装载值
```
2. **配置NVIC中断控制器:**
```c
// 设置中断优先级
NVIC_SetPriority(TIM2_IRQn, 1);
// 使能中断
NVIC_EnableIRQ(TIM2_IRQn);
```
3. **编写中断处理函数:**
```c
void TIM2_IRQHandler(void)
{
// 清除中断标志位
TIM2->SR &= ~TIM_SR_UIF;
// 执行中断处理逻辑
// ...
}
```
**4.2 中断嵌套与优先级管理**
**4.2.1 中断嵌套机制**
中断嵌套是指在中断处理过程中又发生新的中断。STM32中断机制支持中断嵌套,但嵌套层数有限。嵌套层数由NVIC中的ISER寄存器控制,每个中断向量都有一个对应的ISER位。
**4.2.2 中断优先级管理**
中断优先级用于确定当多个中断同时发生时,哪个中断优先处理。STM32中断机制采用优先级抢占式调度算法,即优先级高的中断可以打断优先级低的中断。中断优先级由NVIC中的IPR寄存器控制,每个中断向量都有一个对应的IPR位。
**优先级管理示例:**
假设有外部中断和定时器中断,且外部中断优先级高于定时器中断。当外部中断发生时,即使定时器中断正在处理,外部中断也会打断定时器中断,优先执行外部中断处理。
# 5. STM32中断机制优化
### 5.1 中断响应时间优化
**5.1.1 中断向量表优化**
中断向量表是中断处理程序的入口点,其优化可以减少中断响应时间。优化方法包括:
- **使用汇编代码实现向量表:**汇编代码比C语言代码执行速度更快,因此使用汇编代码实现向量表可以缩短中断响应时间。
- **将向量表放置在高速存储器中:**中断向量表通常存储在Flash存储器中,而高速存储器(如SRAM)访问速度更快。将向量表放置在高速存储器中可以减少中断响应时间。
**5.1.2 中断处理函数优化**
中断处理函数是中断响应过程中的关键部分,其优化可以减少中断响应时间。优化方法包括:
- **尽量减少中断处理函数中的代码量:**中断处理函数中的代码量越大,中断响应时间就越长。因此,应尽量减少中断处理函数中的代码量,只执行必要的任务。
- **使用内联函数:**内联函数可以在编译时直接插入到调用它的代码中,避免函数调用的开销。在中断处理函数中使用内联函数可以减少中断响应时间。
- **避免使用浮点运算:**浮点运算比整数运算耗时更长。在中断处理函数中避免使用浮点运算可以减少中断响应时间。
### 5.2 中断能耗优化
**5.2.1 中断唤醒优化**
当STM32处于低功耗模式时,中断可以唤醒MCU。优化中断唤醒可以减少功耗。优化方法包括:
- **使用低功耗中断源:**一些中断源在唤醒MCU时功耗较低。例如,外部中断源在唤醒MCU时功耗比定时器中断源低。
- **使用中断屏蔽:**当不需要中断时,可以屏蔽中断以减少功耗。
**5.2.2 中断退出优化**
当中断处理完成后,MCU需要退出中断模式。优化中断退出可以减少功耗。优化方法包括:
- **使用中断返回指令:**中断返回指令可以快速退出中断模式,减少功耗。
- **避免使用中断嵌套:**中断嵌套会增加退出中断模式的开销,从而增加功耗。因此,应尽量避免使用中断嵌套。
0
0