GPIO和PIN

发布于:2024-07-03 ⋅ 阅读:(14) ⋅ 点赞:(0)

1 GPIO和Pin

1.1 GPIO和Pin基础概念

​ 单片机有很多的引脚,为了操控每一个引脚,我们对引脚进行分组,例如GPIOA,GPIOB,…,GPIOG等等(Group),这一个组就称为一个GPIO端口,一般一个端口包含十六个PIN引脚[0~15]。(一个引脚占2bits,而stm32是32位的,所以一组是16个)。GPIO引脚具有可复用和重映射的特点。

  • GPIO复用功能:即一个管脚可以有不同的功能,但是同一时间的同一管脚只能占有一个功能。
  • GPIO重映射功能:将复用引脚功能重定义到其他引脚,例如USART可能默认使用GPIOA2引脚,但是你可以重映射到GPIOD5使用。

GPIO硬件示意图:

在这里插入图片描述

1.2 GPIO输入模式

输入模式有四种,分别是浮空输入,上拉输入,下拉输入,模拟输入:

  1. 浮空输入:不接入上拉电阻或者下拉电阻,直接由触发器输入,该模式内部电路呈现高阻态,该模式必须有明确的电平输入。该模式利用施密特触发器的滞回特性,可以用于进行波形整形,用于抗干扰。如果该引脚悬空,读出的值不确定。同时也可以用来输入微弱的信号。
    在这里插入图片描述

  2. 上拉输入:即用上拉电阻将输入拉到高电平。 在这里插入图片描述

  3. 下拉输入:即用下拉电阻将输入拉到低电平。 在这里插入图片描述

  4. 模拟输入:把电压信号直接传送到片上外设模块,如ADC,他和浮空输入的区别是它不经过TTL施密特触发器,是直接将模拟信号传输到外设模块上。 在这里插入图片描述

1.3 GPIO输出模式

  1. 推挽输出:即两个电平,0和1。推挽电路工作时,两只对称功率管轮流导通。所以导通损耗小,效率高。输出既可向负载灌电流,也可向负载抽取电流,提高了电路的负载能力和开关速度。
  2. 开漏输出:开漏输出没有高电平,他的两个电平分别是0电平和(1)高阻态(输出1高电平时,即是高阻态)。常常用于电平匹配或者形成“线与”逻辑关系。(电平匹配:例如单片机最高只能输出5v电压,但是输出的外设需要15v电压,这时候就需要使用开漏输出来提高输出电平)。
  3. 复用推挽输出:I/O端口被用做复用功能,即第二功能时的I/O引脚配置,设置为推挽模式。USART,PWM就是典型的复用推挽输出模式。
  4. 复用开漏输出:I/O端口被用做复用功能,即第二功能时的I/O引脚配置,设置为开漏模式。I2C可以使用复用开漏输出模式。

1.4 GPIO的HAL库

1.4.1 一些HAL库表示

//在HAL库之中,端口的类型,和pin的类型分别是
GPIO_TypeDef				*group;			 //用GPIO_TypeDef的指针定义端口
uint16_t						pin;				//引脚用无符号整形uint16_t定义

//未使用宏定义的时候,例如表示GPIOA Pin12引脚。使用:
GPIOA 和 GPIO_PIN_12  //表示
  
//若在CubeMX中起了名字,即有宏定义,例如重命名为GreenLED,那么表示为:
GreenLED_GPIO_Port 和 GreenLED_Pin //表示
  
//电平状态用GPIO_PinState定义
GPIO_PinState 有两个,分别是GPIO_PIN_RESET和GPIO_PIN_SET

1.4.2 HAL库常用GPIO函数

//根据GPIO_InitTypeDef结构体的参数初始化GPIO端口
void HAL_GPIO_Init (GPIO_TypeDef * GPIOx, GPIO_InitTypeDef * GPIO_Init);
//将GPIO端口的功能恢复到初始状态
void HAL_GPIO_DeInit (GPIO_TypeDef * GPIOx, uint32_t GPIO_Pin);

//读出GPIOx中输入寄存器的值
GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
//将数据写入GPIOx中输出寄存器
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);

//锁定GPIOx寄存器,锁定后将无法修改直到复位
HAL_StatusTypeDef HAL_GPIO_LockPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);

1.4.3 GPIO点亮led灯程序例子

在CubeMX中使能相应的LED灯的引脚。
之后我们开始写程序

//led.h文件
#ifndef __LED_H__
#define __LED_H__

#include "gpio.h"

#define ON 1
#define OFF 0

enum{
	red_led,
	blue_led,
	green_led,
	max_led,
};

extern int turn_led(int which, int status);
extern int blink_led(int which, int interval, int num);
#endif

//led.c文件
#include "led.h"

typedef struct gpio_s{
	GPIO_TypeDef				*group;
	uint16_t						pin;
}gpio_t;

gpio_t leds[max_led]={
	{ RedLED_GPIO_Port, RedLED_Pin },
	{	BlueLED_GPIO_Port, BlueLED_Pin},
	{	GreenLED_GPIO_Port, GreenLED_Pin},
};

int turn_led(int which, int status)
{
	if (which >= max_led)
	{
		return -1;
	}
	
	GPIO_PinState				level;
	
	level = (status==OFF) ? GPIO_PIN_SET : GPIO_PIN_RESET;
	
	HAL_GPIO_WritePin(leds[which].group, leds[which].pin, level);
	
	return 0;
}

int blink_led(int which, int interval, int num)
{
  while(num--)
  {
		turn_led (which, ON);
		HAL_Delay(interval);
	
		turn_led (which, OFF);
		HAL_Delay(interval);
	}
	return 0;
}

之后在main函数中引入led.h头文件,之后调用led的函数就可以实现跑马灯,改变灯的状态等功能了。