HAL库配置GPIO

HAL库与标准库不同的特点:

标准库中初始化外设使用结构体变量+Init函数实现,结构体变量作为局部变量,仅包含外设的基础参数。

HAL库中结构体变量Handler句柄作为全局变量配置中断其他功能的过程中给被广泛引用。

与标准库不同,HAL中的中断服务函数按HAL的处理机制统一处理,不需要我们编写具体内容

在中断函数中完成标志位的重置和修改,并调用回调函数(Callback),可以在main.c重写相应外设的回调函数,实现需要完成的功能。(原回调函数有由_weak修饰,支持重复定义)

使用CubeMX配置GPIO底层参数:

  1. 在配置GPIO_Input时需要明确IO的检测方式

    GPIO Pull-up:IO的初始电平被上拉电阻拉高,检测低电平信号作为输出信号。

    GPIO Pull-down : IO的初始电平被下拉电阻拉低,检测高电平信号作为输入信号。

  2. 在配置GPIO_Output时,GPIO模式(Mode)在**开漏(Open Drain)模式和推挽(Push-Pull)**之间选择。

    推挽模式下,高低电平具有一定的驱动能力(相对低阻抗,输出电流的能力较强

    开漏模式下,高电平没有驱动能力,需要借助外部上拉电阻完成对外驱动。

    详细参考文章 GPIO输入输出各种模式(推挽、开漏、准双向端口)详解.

    所以我们使用IO一般设为推挽输出。

     

总结HAL库中GPIO的相关功能:

  1. 函数库:

    void  HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init);
    void  HAL_GPIO_DeInit(GPIO_TypeDef  *GPIOx, uint32_t GPIO_Pin);
    GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
    void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//实现
    HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
    void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin);
    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
    

    对应函数的功能可以从函数名中直观看出。

GPIO的寄存器:

STM32的寄存器都是32位,对应每个寄存器由4个地址组成。(一个地址为八位,通常指字节地址)

在STM32f4系列中对应GPIO的12个寄存器,其地址偏移为48(0x2c)。
在这里插入图片描述
在这里插入图片描述

 

具体分析各个寄存器:

  1. IDR与ODR:两个16位的端口状态寄存器,对应每组GPIO的16个IO的输入输出

    IDR标明管脚状态,是只读寄存器。可以使用GPIOx->IDR & 0x0001去探明GPIO_PIN_1的电平状态。

    ODR标明端口输出数据,是可读写寄存器。可以使用GPIOx->ODR=1<<13为特定位赋值。(如PIN_13)

    示例:读出PA1的状态赋值给PA13(先定义uint16_t temp(unsigned short))

    uint16_t temp;
    temp=GPIOA->IDR&0x0001;
    GPIOA->ODR|=temp<<13;
    
  2. MODER,OTYPER,OSPEEDR与PUPDR:分别为32位,低16位,32位和32位寄存器,配置IO的基本参数

    MODER为可读写的端口配置寄存器,由低到高每两位控制一个管脚的四种模式

    顺序排布为:00:输入(复位状态),01:通用输出状态,10:复用功能模式,11:模拟模式

    OTYPER为可读写输出模式配置寄存器,由低到高每一位控制一个IO的输出模式。

    顺序排布为:0:输出推挽(复位状态),1:输出开漏

    注意:OTYPER寄存器仅用于输出状态,在MODER[1:0]=00/10时不起作用。

    OSPEEDR为可读写输出速度配置寄存器,由低到高每两位控制一个IO的输出速度。

    顺序排布为:00:2MHz(低速),01:25MHz(中速),10:50MHz(快速),11:100MHz/80MHz(高速)

    注意:OSPEEDR寄存器仅用于输出状态,在MODER[1:0]=00/10时不起作用。

    PUPDR为可读写电平状态寄存器,由低到高每两位控制一个IO的上拉/下拉。

    顺序排布为:00:无上拉或下拉,01:上拉,10:下拉,11:保留

void GPIO_Set(GPIO_TypeDef* GPIOx,u32 BITx,u32 MODE,u32 OTYPE,u32 OSPEED,u32 PUPD)
{  
	u32 pinpos=0,pos=0,curpin=0;
	for(pinpos=0;pinpos<16;pinpos++)
	{
		pos=1<<pinpos;	//逐个位进行检查
		curpin=BITx&pos;//检查引脚是否需要设置
		if(curpin==pos)	//需要设置
		{ 
			GPIOx->MODER&=~(3<<(pinpos*2));	//先清除原来的模式
			GPIOx->MODER|=MODE<<(pinpos*2);	//设置新的模式
			if((MODE==0X01)||(MODE==0X02))	//若为输出模式/复用模式
			{  
				GPIOx->OSPEEDR&=~(3<<(pinpos*2));	//清除原来的设置
				GPIOx->OSPEEDR|=(OSPEED<<(pinpos*2));//设置新的速度  
				GPIOx->OTYPER&=~(1<<pinpos) ;		//清除原来的设置
				GPIOx->OTYPER|=OTYPE<<pinpos;		//设置新的输出模式
			}  
			GPIOx->PUPDR&=~(3<<(pinpos*2));	//清除原来的设置
			GPIOx->PUPDR|=PUPD<<(pinpos*2);	//设置新的上下拉
		}
	}
} 
//对应的宏定义
#define GPIO_MODE_IN    	0		//输入
#define GPIO_MODE_OUT		1		//输出
#define GPIO_MODE_AF		2		//复用
#define GPIO_MODE_AIN		3		//模拟

#define GPIO_SPEED_2M		0		//2Mhz
#define GPIO_SPEED_25M		1		//25Mhz
#define GPIO_SPEED_50M		2		//50Mhz
#define GPIO_SPEED_100M		3		//100Mhz

#define GPIO_PUPD_NONE		0		//无上下拉
#define GPIO_PUPD_PU		1		//上拉
#define GPIO_PUPD_PD		2		//下拉
#define GPIO_PUPD_RES		3		//保留

#define GPIO_OTYPE_PP		0		//推挽
#define GPIO_OTYPE_OD		1		//开漏

//GPIO引脚编号
#define PIN0				1<<0
#define PIN1				1<<1
#define PIN2				1<<2
#define PIN3				1<<3
#define PIN4				1<<4
#define PIN5				1<<5
#define PIN6				1<<6
#define PIN7				1<<7
#define PIN8				1<<8
#define PIN9				1<<9
#define PIN10				1<<10
#define PIN11				1<<11
#define PIN12				1<<12
#define PIN13				1<<13
#define PIN14				1<<14
#define PIN15				1<<15 
  1. AFRL与AFRH:控制IO的复用功能,两个32位可读写寄存器。

    **AFR每四位控制一个IO,对应0~15个不同的复用功能。**对应每组16个IO需要64位进行控制,所以由低到高位分为AFRL与AFRH两个寄存器。

//BITx:0~15,代表 IO 引脚编号.
//AFx:0~15,代表 AF0~AF15.
//可以直接以整型数的形式输入BITS和AFx
void GPIO_AF_Set(GPIO_TypeDef* GPIOx,u8 BITx,u8 AFx)
{
GPIOx->AFR[BITx>>3]&=~(0X0F<<((BITx&0X07)*4));//清空AFR中IO引脚编号对应的四位寄存器内容
GPIOx->AFR[BITx>>3]|=(u32)AFx<<((BITx&0X07)*4);//通过神奇的计算方法设置IO引脚编号对应的四位寄存器内容
}
  1. **BSRR:控制ODR寄存器的端口设置或清除。**分为高16位和低16位,并且只能以字(16位)的形式操作。

    低16位从低到高对应一组IO的16个管脚的ODR位,写入的内容如下0:对应位无影响,1:对应ODR位置1

    高16位从低到高对应一组IO的16个管脚的ODR位,写入的内容如下0:对应位无影响,1:对应ODR位清0

SRR:控制ODR寄存器的端口设置或清除。**分为高16位和低16位,并且只能以字(16位)的形式操作。

低16位从低到高对应一组IO的16个管脚的ODR位,写入的内容如下在这里插入图片描述
0:对应位无影响,1:对应ODR位置1

高16位从低到高对应一组IO的16个管脚的ODR位,写入的内容如下0:对应位无影响,1:对应ODR位清0
 

总结

HAL库GPIO的端口复用,模拟输入和外部中断等功能封装的都比较全面,个人感受不方便进行修改,但是如果需要对GPIO的数据位进行操作,使用ODR和IDR寄存器即可,感觉BRSS寄存器并不直观。

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值