文章目录
- 1 GPIO和Pin
- 1.1 GPIO和Pin基础概念
- 1.2 GPIO输入模式
- 1.3 GPIO输出模式
- 1.4 GPIO的HAL库
- 1.4.1 一些HAL库表示
- 1.4.2 HAL库常用GPIO函数
- 1.4.3 GPIO点亮led灯程序例子
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输入模式
输入模式有四种,分别是浮空输入,上拉输入,下拉输入,模拟输入:
-
浮空输入:不接入上拉电阻或者下拉电阻,直接由触发器输入,该模式内部电路呈现高阻态,该模式必须有明确的电平输入。该模式利用施密特触发器的滞回特性,可以用于进行波形整形,用于抗干扰。如果该引脚悬空,读出的值不确定。同时也可以用来输入微弱的信号。
-
上拉输入:即用上拉电阻将输入拉到高电平。
-
下拉输入:即用下拉电阻将输入拉到低电平。
-
模拟输入:把电压信号直接传送到片上外设模块,如ADC,他和浮空输入的区别是它不经过TTL施密特触发器,是直接将模拟信号传输到外设模块上。
1.3 GPIO输出模式
- 推挽输出:即两个电平,0和1。推挽电路工作时,两只对称功率管轮流导通。所以导通损耗小,效率高。输出既可向负载灌电流,也可向负载抽取电流,提高了电路的负载能力和开关速度。
- 开漏输出:开漏输出没有高电平,他的两个电平分别是0电平和(1)高阻态(输出1高电平时,即是高阻态)。常常用于电平匹配或者形成“线与”逻辑关系。(电平匹配:例如单片机最高只能输出5v电压,但是输出的外设需要15v电压,这时候就需要使用开漏输出来提高输出电平)。
- 复用推挽输出:I/O端口被用做复用功能,即第二功能时的I/O引脚配置,设置为推挽模式。USART,PWM就是典型的复用推挽输出模式。
- 复用开漏输出: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的函数就可以实现跑马灯,改变灯的状态等功能了。