stm32f103zet6 总共有 7 个 GPIO 外设,有 112 个 GPIO 引脚 stm32f103xe 芯片集成了一个外部中断/事件
控制器(EXTI),有由 19 个能产生事件/中断请求的边沿检测器组成。
19 个中断/事件请求包括:
112 个 IO 可以做为 EXTI 线(0…15)
EXTI 线 16 连接到 PVD 输出
EXTI 线 17 连接到 RTC 警告事件
EXTI 线 18 连接到 USB 唤醒事件
后三个属于事件请求。
使用外部中断需要开启 AFIO 中对应的中断功能。
stm32f103zet6 芯片的 112 通用 IO 端口连接到 16 个外部中断/事件线上,连
接方式见。可见图 12-2,EXTI0 线的输入源可以通过外部中断配置寄存器
1(AFIO_EXTICR1)的 EXTI[3:0]四个位的值选择 PA0、PB0、PC0、PD0、PE0、PF0 或
者 PG0 的其中一个,这里也只能选择其中一个,无法同时选择两个,这样的最简
单结果就是 PA0 和 PB0 不能同时使用外部中断。其余 EXTI 线路情况都是与 EXTI0
原理相同的,参考理解就好
----------------------------------------------------------------------------------------------------------------------------------------------------**
案例解析**
该案例是按键中断控制led灯的开和关
首先不同于循环处理的程序,中断处理的程序在打开gpio时钟的基础上还需要打开AFIO复用时钟,该时钟是在stm32f1xx_hal_msp.c 文件的 HAL_MspInit 函数中使能了,该函数在HAL_Init 函数中被调用
01 void HAL_MspInit(void)
02 {
03 __HAL_RCC_AFIO_CLK_ENABLE();----------使能了afio时钟
04
05 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_2);
06
07 /* System interrupt init*/
08 /* MemoryManagement_IRQn interrupt configuration */
09 HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
10 /* BusFault_IRQn interrupt configuration */
11 HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
12 /* UsageFault_IRQn interrupt configuration */
13 HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
14 /* DebugMonitor_IRQn interrupt configuration */
15 HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
16 /* SysTick_IRQn interrupt configuration */
17 HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
18 }
然后我们来看key.h 文件内容
01 #define KEY1_RCC_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE------gpio时钟使能
02 #define KEY1_GPIO_PIN GPIO_PIN_0
03 #define KEY1_GPIO GPIOA
04 /* 根据原理图设计,KEY1 按下时引脚为高电平,所以这里设置为 1 */
05 #define KEY1_DOWN_LEVEL 1---------判断key1是否按下,按下为1
06 #define KEY1_EXTI_IRQn EXTI0_IRQn------中断类型
07 #define KEY1_EXTI_IRQHandler EXTI0_IRQHandler----中断函数
08
09 #define KEY2_RCC_CLK_ENABLE __HAL_RCC_GPIOC_CLK_ENABLE
10 #define KEY2_GPIO_PIN GPIO_PIN_13
11 #define KEY2_GPIO GPIOC
12 /* 根据原理图设计,KEY1 按下时引脚为低电平,所以这里设置为 0 */
13 #define KEY2_DOWN_LEVEL 0
14 #define KEY2_EXTI_IRQHandler EXTI15_10_IRQHandler
15 #define KEY2_EXTI_IRQn EXTI15_10_IRQ
然后接着看key.c 文件内容
01 void KEY_GPIO_Init(void)
02 {
03 /* 定义 IO 硬件初始化结构体变量 */
04 GPIO_InitTypeDef GPIO_InitStruct;
05
06 /* 使能(开启)KEY 引脚对应 IO 端口时钟 */
07 KEY1_RCC_CLK_ENABLE();
08 KEY2_RCC_CLK_ENABLE();
09
10 /* 配置 KEY1 GPIO:输入下拉模式 */
11 GPIO_InitStruct.Pin = KEY1_GPIO_PIN;
12 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;---按照电路图,按下按键从低电平变成高电平所以上升沿触发
13 GPIO_InitStruct.Pull = GPIO_PULLDOWN;-------按照电路图,key1的按键有个外部下拉电阻,所以我们用pulldown或者nopull也可以
14 HAL_GPIO_Init(KEY1_GPIO, &GPIO_InitStruct);
15
16 /* 配置 KEY2 GPIO:输入上拉模式 */
17 GPIO_InitStruct.Pin = KEY2_GPIO_PIN;
18 GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;---按照电路图,按下按键从高电平变成低电平所以下降沿触发
19 GPIO_InitStruct.Pull = GPIO_PULLUP;-------按照电路图,key2的按键有个外部上拉电阻,所以我们用pullup或者nopull也可以
20 HAL_GPIO_Init(KEY2_GPIO, &GPIO_InitStruct);
21
22 /* EXTI interrupt init*/
23 HAL_NVIC_SetPriority(KEY1_EXTI_IRQn, 1, 0);--------------EXTI_IRQn中断的优先级设置
24 HAL_NVIC_EnableIRQ(KEY1_EXTI_IRQn);-----使能nvic
25
26 HAL_NVIC_SetPriority(KEY2_EXTI_IRQn, 1, 1);
27 HAL_NVIC_EnableIRQ(KEY2_EXTI_IRQn);
28 }
接着就是处理中断函数,stm32f1xx_it.c 文件用于存放中断服务函数
01 void KEY1_EXTI_IRQHandler(void)
02 {
03 HAL_GPIO_EXTI_IRQHandler(KEY1_GPIO_PIN);------该函数是hal库内部函数,会执行中断回调函数,该函数一般写在main,c文件内
04 }
05
06 void KEY2_EXTI_IRQHandler(void)
07 {
08 HAL_GPIO_EXTI_IRQHandler(KEY2_GPIO_PIN);
09 }
最后我们来看main.c文件
01 int main(void)
02 {
03 /* 复位所有外设,初始化 Flash 接口和系统滴答定时器 */
04 HAL_Init();
05 /* 配置系统时钟 */
06 SystemClock_Config();
08 /* 板载 LED 初始化 */
09 LED_GPIO_Init();
10
11 /* 板载蜂鸣器初始化 */
12 BEEP_GPIO_Init();
13
14 /* 板子按键初始化 */
15 KEY_GPIO_Init();
16
17 /* 无限循环 */
18 while (1) {
19
20 }
21 }
01 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)-------回调函数
02 {
03 if (GPIO_Pin==KEY1_GPIO_PIN) {
04 HAL_Delay(20);/* 延时一小段时间,消除抖动 */
05 if (HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_GPIO_PIN)==KEY1_DOWN_LEVEL) {
06 BEEP_TOGGLE;
07 LED1_ON;
08 LED2_ON;
09 LED3_ON;
10 }
11 __HAL_GPIO_EXTI_CLEAR_IT(KEY1_GPIO_PIN);-------清楚中断位
12 } else if (GPIO_Pin==KEY2_GPIO_PIN) {
13 HAL_Delay(20);/* 延时一小段时间,消除抖动 */
14 if (HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_GPIO_PIN)==KEY2_DOWN_LEVEL) {
15 BEEP_TOGGLE;
16 LED1_OFF;
17 LED2_OFF;
18 LED3_OFF;
19 }
20 __HAL_GPIO_EXTI_CLEAR_IT(KEY2_GPIO_PIN);
21 }
22 }