目录
提示:其中的key和led程序后面我再写。
一、外部中断概述
1.STM32的每个IO口都可以作为外部中断输入。
2.每个外部中断线可以独立的配置触发方式(上升沿、下降沿、双边触发)。
3.STM32只有16个中断线,那如何才能跟上百个IO口对应呢?
寄存器中的PA0、PB0、PC0、...、PI0 都是映射到EXTI0中
寄存器中的PA15、PB15、PC15、...、PI15都是映射到EXTI15中
这样就可以用16个中断线来控制上百个IO口,但有一个小问题,IO口外部中断再中断向量表中只分配了7个中断向量,也就是只有7个中断服务函数,那如何用用7个控制15个呢?如图。
下图是中断服务函数
二、IO口外部中断HAL库配置方法
1.使能IO口时钟;
2.初始化IO口,设置触发方式;HAL_GPIO_Init();
3.设置中断优先级,并使能中断通道;HAL_NVIC_SetPriority(); HAL_NVIC_EnableIRQ();
4.编写中断服务函数,并调用外部中断通用处理函数;
void EXTIx_IRQHandler(void) // 中断服务函数
{
HAL_GPIO_EXTI_IRQHandler(); // 中断通用处理函数
}
5.编写外部中断回调函数。HAL_GPIO_EXTI_Callback;
三、按键中断程序
1、创建Exti.h头文件(避免重复引用)
#ifndef __EXIT_H
#define __EXIT_H
#include "sys.h"
void Exit_Init(void);
#endif
2、创建Exti.c
#include "Exit.h"
#include "LED.h"
#include "delay.h"
#include "KEY.h"
void Exit_Init(void)
{
// 时钟使能
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
// 初始化
GPIO_InitTypeDef GPIO_Strct;
GPIO_Strct.Mode = GPIO_MODE_IT_RISING; // 上升沿触发
GPIO_Strct.Pin = GPIO_PIN_0;
GPIO_Strct.Pull = GPIO_PULLDOWN; // 下拉
GPIO_Strct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_Strct);
GPIO_Strct.Pin = GPIO_PIN_13;
GPIO_Strct.Mode = GPIO_MODE_IT_FALLING; // 下降沿触发
GPIO_Strct.Pull = GPIO_PULLUP; // 下拉
HAL_GPIO_Init(GPIOC, &GPIO_Strct);
GPIO_Strct.Pin = GPIO_PIN_2 | GPIO_PIN_3;
HAL_GPIO_Init(GPIOH, &GPIO_Strct);
HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0); // 设置EXTI0抢占优先级
HAL_NVIC_EnableIRQ(EXTI0_IRQn); // 设置EXTI0使能
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 2, 1); // 设置EXTI13抢占优先级 EXTI13(在EXTI15_10)
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn); // 设置EXTI13使能
HAL_NVIC_SetPriority(EXTI2_IRQn, 2, 2); // 设置EXTI2抢占优先级
HAL_NVIC_EnableIRQ(EXTI2_IRQn); // 设置EXTI2使能
HAL_NVIC_SetPriority(EXTI3_IRQn, 2, 3); // 设置EXTI3抢占优先级
HAL_NVIC_EnableIRQ(EXTI3_IRQn); // 设置EXTI3使能
}
// 中断服务函数
void EXTI3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_3); // 中断函数
}
void EXTI2_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
}
void EXTI0_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
}
void EXTI15_10_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13);
}
// 回调函数
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
delay_ms(100); // 防抖
switch (GPIO_Pin)
{
case GPIO_PIN_3: // KEY0
if (KEY0 == 0)
{
LED0 = !LED0;
LED1 = !LED1;
}
break;
case GPIO_PIN_2: // KEY1
if (KEY1 == 0)
{
LED1 = !LED1;
}
break;
case GPIO_PIN_13: // KEY2
if (KEY2 == 0)
{
LED0 = !LED0;
}
break;
case GPIO_PIN_0: // KEY_WK_UP
if (KEY_WK_UP == 1)
{
LED1 = !LED1;
LED0 = !LED0;
}
break;
}
}
LED0、LED1是在"LED.h"里面定义的
KEY1、KEY2、KEY0、KEY_WK_UP是在"KEY.h"里定义的
之后我会写
3、主函数main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "Exit.h"
int main(void)
{
HAL_Init(); // HAL库初始化
Stm32_Clock_Init(360, 25, 2, 8); // 时钟初始化
delay_init(180); // 延时初始化
uart_init(115200); // 串口初始化
LED_Init(); // LED初始化
Exit_Init(); // 中断初始化
while (1)
{
printf("love\r\t"); // 输出love
delay_us(1500); // 延迟1.5s
}
}