背景:
最近一直在学习HAL库,总结下STM32中HAL库的GPIO相关函数知识点。
内容:
在stm32l152xb.h头文件中定义了GPIO的相关寄存器,下面讲述的GPIO函数将会调用到这些寄存器。寄存器的结构体定义如下图:
下面解析stm32l1xx_hal_gpio.c文件中一些常用的GPIO函数:
(1)GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)函数
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIO_PinState bitstatus;
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));//检查确认是不是GPIO口,从GPIO_PIN_0到GPIO_PIN_ALL
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET) //判断输入数据寄存器是不是GPIO_PIN_SET
{
bitstatus = GPIO_PIN_SET;
}
else
{
bitstatus = GPIO_PIN_RESET;
}
return bitstatus;
}
(2)void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) 函数
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_PIN_ACTION(PinState));
if (PinState != GPIO_PIN_RESET)
{
GPIOx->BSRR = (uint32_t)GPIO_Pin;//如果是GPIO_PIN_SET,则将GPIO的BSRR寄存器低16位置为GPIO_Pin
}
else
{
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16 ;//如果是GPIO_PIN_RESET,则将GPIO的BSRR寄存器的高16位置为GPIO_Pin
}
}
例如函数输入的参数是GPIOA、GPIO_Pin_1和GPIO_PIN_SET,则GPIOA->BSRR=((uint32_t)0x0002U);即把二进制数0000000000000010转换为32位数赋值给BSRR,对应的GPIO_Pin_1管脚置高;
例如函数输入的参数是GPIOA、GPIO_Pin_1和GPIO_PIN_RESET,则GPIOA->BSRR=((uint32_t)0x0002U<<16);即把二进制数0000000000000010左移16位并转换为32位数赋值给BSRR,高16位对应的GPIO_Pin_1为1,对应管脚被清零,置低;
(3)void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)函数
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->ODR ^= GPIO_Pin;//输出数据寄存器与GPIO_Pin异或;
}
例如函数的输入参数是GPIOA、GPIO_Pin_1,则GPIOx->ODR与0000000000000010进行异或操作,0 ^ 1 =1,1 ^ 1 =0,异或运算后,原来的对应位被翻转。
(4)void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);函数
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
/* EXTI line interrupt detected */
if(__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != RESET) //若中断标志被置位
{
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);//清楚标志位
HAL_GPIO_EXTI_Callback(GPIO_Pin);//进入回调函数
}
}
(5)void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);函数
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
//_weak:__weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行__weak 声明的函数,并且编译器不会报错。
{
/* Prevent unused argument(s) compilation warning */
UNUSED(GPIO_Pin);//防止出现警告,#define UNUSED(x) ((void)(x)),x前面用void定义时,可以避免x定义了但没调用的错误
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_GPIO_EXTI_Callback could be implemented in the user file
*/
}