STM32教程之外部中断应用
【STM32系列文章】
STM32-01-认识单片机
STM32-02-基础知识
STM32-03-HAL库
STM32-04-时钟树
STM32-05-SYSTEM文件夹
STM32-06-GPIO
文章目录
STM32 中断系统
1. 中断
- 实时控制
- 故障处理
- 数据传输
2. NVIC
什么是NVIC?
Nested vectored interrupt controller
即嵌套向量中断控制器,属于内核。
支持256个中断,其中包含了16个系统中断和240个外部中断,并且具有256级的可编程中断设置。
对于STM32F103ZET6的系统中断有10
个,外部中断有60
个,16
个中断优先级。
特性:
NVIC相关寄存器介绍
NVIC相关寄存器 | 位数 | 寄存器个数 | 备注 |
---|---|---|---|
中断使能寄存器(ISER) | 32 | 8 | 每个位控制一个中断 |
中断失能寄存器(ICER) | 32 | 8 | 每个位控制一个中断 |
应用程序中断及复位控制寄存器(AIRCR) | 32 | 1 | 位[10:8]控制优先级分组 |
中断优先级寄存器(IPR) | 8 | 240 | 8个位对应一个中断,而STM32只使用高4位 |
工作原理
内核中断是不可屏蔽中断,直接由SHPR
决定优先级,外部中断过来以后,会首先经过ISER
和ICER
寄存器进行使能或者失能,之后由IPR
寄存器确定优先级,然后去抢占CPU执行中断。
中断优先级
优先级分组
优先级分组 | AIRCR[10:8] | IPRx bit[7:4]分配 | 分配结果 |
---|---|---|---|
0 | 111 | None :[7:4] | 0位抢占优先级,4位响应优先级 |
1 | 110 | [7] :[6:4] | 1位抢占优先级,3位响应优先级 |
2 | 101 | [7:6] :[5:4] | 2位抢占优先级,2位响应优先级 |
3 | 100 | [7:5] :[4] | 3位抢占优先级,1位响应优先级 |
4 | 011 | [7:4] :None | 4位抢占优先级,0位响应优先级 |
NVIC的使用
- 设置中断分组
SCB_AIRCR
- 设置中断优先级
NVIC_IPRx
- 使能中断
NVIC_ISER
3. EXTI
什么是EXTI?
External interrupt/event Controller
即外部中断/事件控制器,由20个产生事件/中断请求的边沿检测器组成,非互联型产品有19个边沿检测器。每个输入线可以独立地配置输入类型和对应的触发事件。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。
特性:
框图
功能框图包含两条主线:一是由输入线到NVIC中断控制器,二是由输入线到脉冲发生器。这就是EXTI的两大功能,产生中断与产生事件,两者从硬件上就存在不同。
输入线是线路的信息输入端,它可以通过配置寄存器设置为任何一个GPIO口,或者是一些外设的事件。输入线一般都存在电平变化的信号。
①:边缘检测,上升沿触发选择寄存器(EXTI_RTSR
)和下降沿触发选择寄存器(EXTI_FTSR
)。边沿检测电路以输入线作为信号输入端,如果检测到边缘跳变,就输出有效信号1,有效信号1会传输到②电路。
②:软件触发,两个信号输入端分别为软件中断事件寄存器(EXTI_SWIER)和边沿检测电路的输入信号。或门电路只要输入有效信号1,就会把有效信号输入到③和④电路。通过对软件中断事件寄存器的读写操作就可以启动中断/事件线。
③:中断屏蔽/清除,两个信号输入端分别为中断屏蔽寄存器(EXTI_IMR
)和②电路,与门电路要求输入都为‘1’才输出‘1’,这样子的情况下,如果中断屏蔽寄存器EXTI_IMR)设置为0时,不管从标号②电路输出的信号特性如何,最终标号③电路输出的信号都是0;假如中断屏蔽寄存器(EXTI_IMR)设置为1时,最终标号③电路输出的信号才由标号②电路输出信号决定,这样子就可以简单控制EXTI_IMR来实现中断的目的。标号④电路输出‘1’就会把请求挂起寄存器(EXTI_PR)对应位置1。
④:事件屏蔽,请求挂起寄存器(EXTI_PR
)的内容就输出到 NVIC 内,实现系统中断事件的控制。
4. AFIO
Alternate Function IO
,即复用功能IO,主要用于重映射和外部中断映射配置
寄存器AFIO_EXTICR1~4
,配置EXTI中断线0~15具体对应哪个IO口
EXTI与IO对应关系
5. 中断配置步骤
EXTI配置步骤:
1. 使能GPIO时钟
2. 设置GPIO工作模式
3. 使能AFIO
4. 设置EXTI和IO对应关系
5. 设置EXTI屏蔽,上下沿
6. 设置NVIC
7. 设计中断服务函数
HAL库配置步骤:
-
使能GPIO时钟
__HAL_RCC_GPIOx_CLK_ENABLE();
-
GPIO/AFIO/EXTI配置
HAL_GPIO_Init();
-
设置中断分组
HAL_NVIC_SetPriorityGrouping();
-
设置中断优先级
HAL_NVIC_SetPriority();
-
使能中断
HAL_NVIC_EnableIRQ();
-
设计中断服务函数
EXTIx_IRQHandler();
-
编写中断处理回调函数
HAL_GPIO_EXTI_Callback();
中断回调处理机制
6. 外部中断代码
Exti.h
#ifndef _EXTI_H
#define _EXTI_H
#include "./SYSTEM/sys/sys.h"
void exti_init(void);
#endif
EXTI.c
#include "./BSP/EXTI/exti.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
//外部中断初始化
void exti_init(void)
{
GPIO_InitTypeDef gpio_init_struct;
//1.打开GPIO的时钟
__HAL_RCC_GPIOE_CLK_ENABLE();
//2.配置GPIO
gpio_init_struct.Pin = GPIO_PIN_4;
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
gpio_init_struct.Pin = GPIO_PIN_3;
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
gpio_init_struct.Pin = GPIO_PIN_2;
gpio_init_struct.Mode = GPIO_MODE_IT_FALLING;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
gpio_init_struct.Pin = GPIO_PIN_0;
gpio_init_struct.Mode = GPIO_MODE_IT_RISING;
gpio_init_struct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
//4.设置中断优先级
HAL_NVIC_SetPriority(EXTI4_IRQn, 2, 0);
HAL_NVIC_SetPriority(EXTI3_IRQn, 3, 0);
HAL_NVIC_SetPriority(EXTI2_IRQn, 4, 0);
HAL_NVIC_SetPriority(EXTI0_IRQn, 5, 0);
//5.使能中断
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
HAL_NVIC_EnableIRQ(EXTI0_IRQn);
}
void EXTI4_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_4);
}
void EXTI3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3);
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_3);
}
void EXTI2_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_2);
}
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
__HAL_GPIO_EXTI_CLEAR_FLAG(GPIO_PIN_0);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(20);
switch(GPIO_Pin)
{
case GPIO_PIN_0:
if(KEY_UP == 1)
LED0(0);
break;
case GPIO_PIN_2:
if(KEY2 == 0)
LED0(1);
break;
case GPIO_PIN_3:
if(KEY1 == 0)
LED1(0);
break;
case GPIO_PIN_4:
if(KEY0 == 0)
LED1(1);
break;
default :
break;
}
}
main.c
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/EXTI/exti.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
key_init(); //按键初始化
beep_init(); //蜂鸣器初始化
exti_init(); //外部中断初始化
while(1)
{
}
}
声明:资料来源(战舰STM32F103ZET6开发板资源包)
- Cortex-M3权威指南(中文).pdf
- STM32F10xxx参考手册_V10(中文版).pdf
- STM32F103 战舰开发指南V1.3.pdf
- STM32F103ZET6(中文版).pdf
- 战舰V4 硬件参考手册_V1.0.pdf
作者:turbosqi