打印
[其他ST产品]

STM32 HAL库常用GPIO函数以及外部中断配置与响应流程

[复制链接]
216|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
HAL库常用GPIO函数:

void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)



这个函数主要用来初始化我们需要用到的引脚,设置其工作频率、工作模式、上下拉等参数。如果使用CubeMX配置工程,所有参数在Cube中调配,函数自动在工程中生成。

void HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin)

HAL_GPIO_Init能够实现对GPIO的初始化,那么HAL_GPIO_DeInit就是与其相反的操作,能够将GPIO口恢复至默认状态,即各个寄存器复位时的值。

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)



使用特权

评论回复
沙发
个百zz分点个|  楼主 | 2023-12-27 16:31 | 只看该作者
这个函数主要功能是读取我们想要知道的引脚的电平状态、函数返回值为0或1。

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)


该函数是让某个端口输出0或1。

使用特权

评论回复
板凳
个百zz分点个|  楼主 | 2023-12-27 16:31 | 只看该作者
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)



该函数的功能是翻转某个端口的电平状态。

使用特权

评论回复
地板
个百zz分点个|  楼主 | 2023-12-27 16:31 | 只看该作者
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)



该函数的功能是锁住某个端口的电平值,当该端口电平变化时,仍保持原本的值。注意的是:一旦锁住后,就不能再修改,只有复位后才可以重新配置。

使用特权

评论回复
5
个百zz分点个|  楼主 | 2023-12-27 16:31 | 只看该作者
这是GPIO的模式锁定,根本就不是电平锁定,简单来说就是有个GPIO已经设定为推挽输出模式,只要将该GPIO锁定,后面你的代码执行该GPIO变成输入模式的代码将不起作用,最主要作用是在强干扰环境下防止意外跑飞导致修改io的模式状态导致严重意外问题,只能说一般平常环境是用不上的。

使用特权

评论回复
6
个百zz分点个|  楼主 | 2023-12-27 16:32 | 只看该作者
究竟何用待摸索。

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)


该函数是用来相应外部中断的中断服务函数。(当发生中断的时候,程序就会执行中断服务函数。 每当一个事件发生,就会最终调用相应的中断处理回调函数,我们在回调函数中编写真正的控制逻辑即可。 中断服务函数就是终止程序运行的函数,回调函数是程序在终止之后希望执行的操作)

使用特权

评论回复
7
个百zz分点个|  楼主 | 2023-12-27 16:32 | 只看该作者
函数有两个功能:

1.clear IT,即清除中断标记位。

2.调用外部中断回调函数。

__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)


该函数是外部中断的中断回调函数,在函数中写入外部中断触发的内容。

使用特权

评论回复
8
个百zz分点个|  楼主 | 2023-12-27 16:32 | 只看该作者
需要注意的是:回调函数定义为弱函数( __weak ),故不需要在stm32l4xx_hal.c中对其进行修改。HAL_GPIO_EXTI_Callback可以在用户文件中实现。

__weak的使用:加上了__weak修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak声明的函数,并且编译器不会报错。所以我们可以在别的地方定义一个相同名字的函数,而不必也尽量不要修改之前的函数。

使用特权

评论回复
9
个百zz分点个|  楼主 | 2023-12-27 16:33 | 只看该作者
注意:

使用CubeMX创建外部中断时,中断服务函数和中断回调函数并不会在main函数中直接出现,需要到stm32f1xx_hal_gpio.h中去找到这两个函数。(不是gpio.h,gpio.h是用户文件,而stm32f1xx_hal_gpio.h是库文件)

使用特权

评论回复
10
个百zz分点个|  楼主 | 2023-12-27 16:33 | 只看该作者
然后到.c文件中找到回调函数,并且在其中写用户代码。


使用特权

评论回复
11
个百zz分点个|  楼主 | 2023-12-27 16:33 | 只看该作者
但是这样写的话,用户代码就不再main函数以及用户文件夹中了,可以采用以下写法:

由于该回调函数是_weak弱定义,所以我们可以直接在main函数中再定义一个相同的回调函数,并在其中撰写用户代码,这样就解决了上述问题。

使用特权

评论回复
12
个百zz分点个|  楼主 | 2023-12-27 16:33 | 只看该作者
其中中断服务函数最后会被stm32f1xx_it.c中的EXIT1_IRQHandler();函数调用。


然后接着调用中断回调函数。主要流程就简化为:

EXTI1_IRQHandler();

      调用

HAL_GPIO_EXTI_IRQHandler();

      调用

HAL_GPIO_EXTI_Callback();

即系统中断服务函数调用HAL库中断处理函数(使用HAL库函数的好处在下文有讲)。

使用特权

评论回复
13
个百zz分点个|  楼主 | 2023-12-27 16:34 | 只看该作者
GPIO外部中断执行流程:

1.打开外部中断:

首先是main函数中GPIO初始化函数:

使用特权

评论回复
14
个百zz分点个|  楼主 | 2023-12-27 18:58 | 只看该作者
其中HAL_NVIC_SetPriority();是设置中断优先级函数。

HAL_NVIC_EnabledIRQ();是中断开启函数。

外部中断线和引脚的映射配置在下文提及。

在stm32f1xx_hal_cortex.c文件中可找到HAL_NVIC_SetPriority();和HAL_NVIC_EnabledIRQ();函数,但是重点关注HAL_NVIC_EnabledIRQ();函数:

使用特权

评论回复
15
个百zz分点个|  楼主 | 2023-12-27 18:58 | 只看该作者

使用特权

评论回复
16
个百zz分点个|  楼主 | 2023-12-27 18:58 | 只看该作者
在stm32f1xx_hal_cortex.c文件中可找到HAL_NVIC_SetPriority();和HAL_NVIC_EnabledIRQ();函数,但是重点关注HAL_NVIC_EnabledIRQ();函数:

使用特权

评论回复
17
个百zz分点个|  楼主 | 2023-12-27 18:58 | 只看该作者
再往下就是寄存器的操作了:(在core_cm3.h文件中)

使用特权

评论回复
18
个百zz分点个|  楼主 | 2023-12-27 18:58 | 只看该作者
2.外部中断响应过程:

当外部中断引脚出现电平变化时,触发外部中断。

微控制器暂停当前程序的执行,根据中断向量表跳转到EXTI1_IRQHandler();函数。


使用特权

评论回复
19
个百zz分点个|  楼主 | 2023-12-27 18:59 | 只看该作者
其中中断向量表是在启动文件startup_stm32f103xb.s中由ST公司定义的:

使用特权

评论回复
20
个百zz分点个|  楼主 | 2023-12-27 18:59 | 只看该作者
其中由ST公司定义的中断服务函数默认为死循环,但是因为他们的函数属性都是_weak,所以在CubeMX中打开中断后,就会在stm32f1xx_it.c中自动生成同名的中断服务函数EXTI1_IRQHandler();

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

592

帖子

0

粉丝