EXTI的HAL库设置步骤

STM32中EXTI的HAL库设置步骤

使能GPIO时钟

用HAL库的使能函数启用所需GPIO

1
__HAL_RCC_GPIOx_CLK_ENABLE()

为了提高代码可读性,在头文件中用宏封装对应的函数,例如

1
2
#define KEY0_INT_GPIO_CLK_ENABLE()\
do{__HAL_RCC_GPIOE_CLK_ENABLE()}while(0)

然后在外部中断初始化函数中调用这些函数

设置GPIO/AFIO(SYSCFG)/EXTI

用HAL库的GPIO外设初始化函数一步到位

1
void HAL_GPIO_Init(GPIOTypeDef *GPIOx, GPIO_InitTypeDef *gpio_init_struct)

其中形参1是端口号,范围有GPIOA到GPIOG

形参2是给函数提供初始化信息的结构体,定义为

1
2
3
4
5
6
7
typedef struct
{
uint32_t Pin; /* 引脚号 */
uint32_t Mode; /* 模式设置 */
uint32_t Pull; /* 上拉下拉设置 */
uint32_t Speed; /* 速度设置 */
} GPIO_InitTypeDef;

第一个成员Pin引脚号范围有GPIO_PIN_0到GPIO_PIN_15,还有可选的GPIO_PIN_MASK和GPIO_PIN_ALL

第二个成员Mode为GPIO的各种工作模式,具体原理见开发指南

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define GPIO_MODE_INPUT (0x00000000U) /* 输入模式 */
#define GPIO_MODE_OUTPUT_PP (0x00000001U) /* 推挽输出 */
#define GPIO_MODE_OUTPUT_OD (0x00000011U) /* 开漏输出 */
#define GPIO_MODE_AF_PP (0x00000002U) /* 推挽式复用 */
#define GPIO_MODE_AF_OD (0x00000012U) /* 开漏式复用 */
#define GPIO_MODE_AF_INPUT GPIO_MODE_INPUT
#define GPIO_MODE_ANALOG (0x00000003U) /* 模拟模式 */
#define GPIO_MODE_IT_RISING (0x10110000u) /* 外部中断,上升沿触发检测 */
#define GPIO_MODE_IT_FALLING (0x10210000u) /* 外部中断,下降沿触发检测 */
/* 外部中断,上升和下降双沿触发检测 */
#define GPIO_MODE_IT_RISING_FALLING (0x10310000u)
#define GPIO_MODE_EVT_RISING (0x10120000U) /*外部事件,上升沿触发检测 */
#define GPIO_MODE_EVT_FALLING (0x10220000U) /*外部事件,下降沿触发检测 */
/* 外部事件,上升和下降双沿触发检测 */
#define GPIO_MODE_EVT_RISING_FALLING (0x10320000U)

第三个成员Pull用于配置上下拉电阻,根据电路原理图设置
1
2
3
#define GPIO_NOPULL (0x00000000U) /* 无上下拉 */
#define GPIO_PULLUP (0x00000001U) /* 上拉 */
#define GPIO_PULLDOWN (0x00000002U) /* 下拉 */

第四个成员Speed配置GPIO的速度
1
2
3
#define GPIO_SPEED_FREQ_LOW (0x00000002U) /* 低速 */
#define GPIO_SPEED_FREQ_MEDIUM (0x00000001U) /* 中速 */
#define GPIO_SPEED_FREQ_HIGH (0x00000003U) /* 高速 */

设置中断分组

HAL库已经在HAL_Init()函数里面设置好了,所以这一步不用管了

设置中断优先级

1
2
3
4
5
void HAL_NVIC_SetPriority(
IRQn_Type IRQn,
uint32_t PreemptPriority,
uint32_t SubPriority
);

形参1为中断号,范围在原理图和芯片头文件
形参2为抢占优先级,范围0到15
形参3为响应优先级,范围0到15

使能中断

调用中断使能函数

1
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);

形参为中断号,范围同上

设计中断服务函数

开启中断必须编写服务函数,否则死机

1
void EXTIx_IRQHandler()

为了开发方便,在头文件中用宏做封装,例如
1
#define KEY0_INT_IRQHandler EXTI4_IRQHandler

HAL库对中断服务处理过程做了封装,所以只需要在中断服务函数中直接调用HAL库提供的中断服务处理公用函数,例如
1
2
3
4
5
void KEY0_INT_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(KEY0_INT_GPIO_PIN);/* 调用中断处理公用函数 清除KEY0所在中断线 的中断标志位 */
__HAL_GPIO_EXTI_CLEAR_IT(KEY0_INT_GPIO_PIN);/* HAL库默认先清中断再处理回调,退出时再清一次中断,避免按键抖动误触发 */
}

这个中断服务处理公用函数已经由HAL库定义好,功能是先清除中断标志位,再调用中断处理回调函数,形参是触发中断的端口引脚号
1
2
3
4
5
6
7
8
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00U)
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin); /* 清中断标志位 */
HAL_GPIO_EXTI_Callback(GPIO_Pin); /* 外部中断回调函数 */
}
}

最后在外部中断回调函数中编写控制逻辑即可
1
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

形参是触发中断的端口引脚号,给不同的引脚编写不同的逻辑


EXTI的HAL库设置步骤
http://tsailooy.top/2023/08/03/EXTI的HAL库设置步骤/
作者
Tsailooy
发布于
2023年8月3日
更新于
2023年8月3日
许可协议