总:STM32------学习总纲
一、什么是中断

1.1 作用与意义

1.2 STM32 GPIO 外部中断简图

二、NVIC
2.1 NVIC 基本概念
Nested vectored interrupt controller,嵌套向量中断控制器,属于内核(M3、M4、M7)

用不到很多的优先级,允许厂商裁剪

内核中断、外部中断,都有其对应的中断服务函数,是中断的入口。被定义在中断向量表中。
2.1.1 中断向量表

STM32 是 32位单片机每一次取地址32位,也就是4byte。


main函数优先级最低。


2.2 NVIC 相关寄存器


2.3 NVIC 工作原理
2.4 STM32 中断优先级基本概念


2.5 STM32 中断优先级分组

IPR寄存器只是用高四位 [7:4]分配优先级。x位表示 2^x 个优先级。

举例:

2.6 STM32 NVIC使用
|---|---------|---------------|------------------------------|
| 步骤 || 操作寄存器 | HAL库 |
| 1 | 设置中断分组 | AIRCR[10:8] | HAL_NVIC_SetPriorityGrouping |
| 2 | 设置中断优先级 | IPRx [7:4] | HAL_NVIC_SetPriority |
| 3 | 使能中断 | ISERx | HAL_NVIC_EnableIRQ |
除了这三个HAL库函数,还有其他不常用的NVIC函数。
一般在HAL_Init() 函数中设置分组2:NVIC_PRIORITYGROUP_2。
cpp
/**
* @brief This function is used to initialize the HAL Library; it must be the first
* instruction to be executed in the main program (before to call any other
* HAL function), it performs the following:
* Configure the Flash prefetch.
* Configures the SysTick to generate an interrupt each 1 millisecond,
* which is clocked by the HSI (at this stage, the clock is not yet
* configured and thus the system is running from the internal HSI at 16 MHz).
* Set NVIC Group Priority to 4.
* Calls the HAL_MspInit() callback function defined in user file
* "stm32f1xx_hal_msp.c" to do the global low level hardware initialization
*
* @note SysTick is used as time base for the HAL_Delay() function, the application
* need to ensure that the SysTick time base is always set to 1 millisecond
* to have correct HAL operation.
* @retval HAL status
*/
HAL_StatusTypeDef HAL_Init(void)
{
/* Configure Flash prefetch */
#if (PREFETCH_ENABLE != 0)
#if defined(STM32F101x6) || defined(STM32F101xB) || defined(STM32F101xE) || defined(STM32F101xG) || \
defined(STM32F102x6) || defined(STM32F102xB) || \
defined(STM32F103x6) || defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG) || \
defined(STM32F105xC) || defined(STM32F107xC)
/* Prefetch buffer is not available on value line devices */
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif
#endif /* PREFETCH_ENABLE */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
HAL_InitTick(TICK_INT_PRIORITY);
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
cpp
/**
* @brief Sets the priority grouping field (preemption priority and subpriority)
* using the required unlock sequence.
* @param PriorityGroup: The priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
* 4 bits for subpriority
* @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
* 3 bits for subpriority
* @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
* 2 bits for subpriority
* @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
* 1 bits for subpriority
* @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
* 0 bits for subpriority
* @note When the NVIC_PriorityGroup_0 is selected, IRQ preemption is no more possible.
* The pending IRQ priority will be managed only by the subpriority.
* @retval None
*/
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
cpp
/**
* @brief Sets the priority of an interrupt.
* @param IRQn: External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xx.h))
* @param PreemptPriority: The preemption priority for the IRQn channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority
* @param SubPriority: the subpriority level for the IRQ channel.
* This parameter can be a value between 0 and 15
* A lower priority value indicates a higher priority.
* @retval None
*/
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
IRQn_Type:是中断号枚举类型,对于中断向量表中断位置(STM32f1参考手册)。
PreemptPriority:抢占优先级
SubPriority:响应优先级
cpp
/**
* @brief Enables a device specific interrupt in the NVIC interrupt controller.
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
* function should be called before.
* @param IRQn External interrupt number.
* This parameter can be an enumerator of IRQn_Type enumeration
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
* @retval None
*/
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
三、EXTI
3.1 EXTI 基本概念
3.1.1 简介
External interrupt/event Controller,外部中断事件控制器
在H7中,称为 Extended interrupt/event Controller,扩展中断事件控制器。
包含20个产生 事件/中断请求 的边沿检测器,即总共:20条 EXTI 线(F1)
3.1.2 中断和事件的理解:
中断:要进入NVIC,有相应的中断服务函数,需要CPU处理。
事件:不进入NVIC,仅用于内部硬件自动控制,如 :TIM、DMA、ADC。
中断是计算机或单片机在执行程序时,因突发事件(如硬件信号、紧急任务等)暂停当前操作,转去处理新事件,完成后自动返回原程序继续执行的过程。
事件是 STM32 中实现硬件级快速响应的机制,适用于无需 CPU 干预的自动控制场景。
3.1.3 EXTI 支持的外部中断/事件请求

互联性的F1系列才包含以太网,所以非互联性STM32只有19条 EXTI 线(F1),不包含EXTI线19,以太网唤醒事件。
EXTI线16~...是内部中断/事件
学习中断的主要任务是学习 EXTI线 0~15。
3.2 EXTI 主要特性

挂起状态位是针对 中断 来说的,有一个寄存器进行选择。

3.3 EXTI 工作原理(F1)

主要使用 四个寄存器,一般不使用 ++软件触发++。
EXTI_RTSR 上升沿触发选择寄存器
(Rise Trigger Select Register)

EXTI_FTSR 下降沿触发选择寄存器
(Fall Trigger Select Register)

双边沿触发设置
双边沿则控制对应位的Fall&Rise寄存器位都置1,允许EXTI输入线x双边沿触发。
EXTI_IMR 中断屏蔽寄存器
(Interrupt Mask Register)

EXTI_PR 请求挂起寄存器
(Pending Request Register)

一般使用写入 '1'的方式清除这个寄存器,后边一个办法不常用。
3.4 F4/F7参考F1,H7 EXTI工作原理见B站视频
四、EXTI 与 IO 的映射关系
4.1 AFIO 简介(F1)

|---|----------|--------------------|-------------------------------------|
| 内容 || 寄存器 | 说明 |
| 1 | 调试IO配置 | AFIO_MAPR[26:24] | 配置JTAG/SWD的开关状态。可不关注 |
| 2 | 重映射配置 | AFIO_MAPR | 部分外设IO重映射配置,F1中并不是所有的IO都有重映射功能。可不关注 |
| 3 | 外部中断配置* | AFIO_EXTICR 1~4 | 配置EXTI中断线 0~15 对应到具体那个IO。重点 |
特别注意:
配置AFIO寄存器之前要使能AFIO时钟,方法如下:
__HAL_RCC_AFIO_CLK_ENABLE(); 对应RCC_APB2ENR寄存器位0。参考手册8.4.3、8.4.6
4.2 SYSCFG 简介(F4/F7/H7 使用,见B站)
【【正点原子】手把手教你学STM32 HAL库开发全集【真人出镜】STM32入门教学视频教程 单片机 嵌入式】第60讲

4.3 EXTI 与 IO 对应关系*
4.3.1 理论对应关系

右列 0 称为引脚号,中间A~K称为 IO分组号。
EXTI0 表示对应 引脚号为0 的 IO。

也就是说,EXTI0 如果被控制对应 PA0,那么别的 Px0 的IO就不能与EXTI0 对应了。
EXTIx 输入线只能一对一对应 IO。
参考手册 9.2.5
4.3.2 AFIO寄存器配置关系(F1)

一个AFIO外部中断配置寄存器可控制4条 EXTI线。
这样的寄存器有四个,,总共可配置 16条 EXTI线对应 16个 IO。
五、如何使用中断*
5.1 中断一图流

在本节中,主要学习GPIO外部中断,外设中断由外设本身配置,不由STM32寄存器配置。
5.2 STM32 EXTI的配置步骤(GPIO外部中断)
|---|-------------------------------|----------------------------------------------------------|---------------|
| 步骤 || 作用 | HAL库 |
| 1 | 使能GPIO时钟 | 使能GPIO时钟 | |
| 2 | 设置GPIO输入模式 | 上、下拉/浮空输入 | HAL_GPIO_Init |
| 3 | 使能 AFIO(F1)/ SYSCFG(F4/F7/H7) | 设置AFIO/SYSCFG 时钟开启寄存器 | HAL_GPIO_Init |
| 4 | 设置EXTI和IO对应关系 | 选择 PAx~PKx 一对一对应EXTI的x线,寄存器:AFIO_EXTICR/SYSCFG_EXTICR | HAL_GPIO_Init |
| 5 | 设置EXTI屏蔽,上、下沿 | 设置EXTI对应通道的屏蔽和上升沿、下降沿触发,寄存器:EXTI_IMR、EXTI_RTSR、EXTI_FTSR | HAL_GPIO_Init |
| 6 | 设置NVIC | 见 2.6 STM32 NVIC使用 | |
| 7 | 设计中断服务函数 | 编写对应中断的中断服务函数!需要清除中断标志! | |
5.3 SMT32 EXTI 的HAL库设置步骤(GPIO外部中断)
|---|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| 步骤 || HAL库 |
| 1 | 使能GPIO时钟 | __HAL_RCC_GPIOx_CLK_ENABLE |
| 2 | GPIO/AFIO(SYSCFG)/EXTI | HAL_GPIO_Init 一步到位配置 |
| 3 | 设置中断分组 | HAL_NVIC_SetPriorityGrouping 此函数只需要配置一次 |
| 4 | 设置中断优先级 | HAL_NVIC_SetPriority |
| 5 | 使能中断 | HAL_NVIC_EnableIRQ |
| 6 | 设计中断服务函数 | 编写 EXTIx_IRQHandler,清中断标志 |
| 6 | 设计中断服务函数 | STM32仅有7个外部中断服务函数,在.s文件中断向量表定义: EXTI 0~4:5条EXTI线单独的中断服务函数 EXTI 9_5:5~8EXTI线共用一个中断服务函数 EXTI 15_10: 10~15EXTI线共用一个中断服务函数 |
六、通用外设驱动模型

在此模型中,GPIO外部中断只使用了1,4两个步骤。
七、HAL库中断回调处理机制介绍


八、编程实战
通过外部中断控制一个灯亮灭