GPIO(通用输入输出接口)
1 GPIO 功能概述
GPIO 是通用输入/输出(General Purpose I/O)的简称,主要用于工业现场需要用到数字量输入/输出的场合,例如:
2 STM32 的 GPIO 特性
- 多种工作模式:输出/输入/复用/模拟
- 灵活的复用模式
- 5V 电压容限
- 外部中断功能
3 端口和引脚
GPIO 模块由端口 GPIOA、GPIOB、GPIOC 等多个独立的子模块构成。
例如:端口 GPIOA 包括 PA0 ~ PA15 这 16 个引脚,通过 10 个硬件寄存器控制引脚工作。
PA0,属于端口 GPIOA,输出电平由端口 GPIOA 的输出数据寄存器 GPIOA_ODR 的第 0 位决定。
4 GPIO 电路
5 GPIO 工作模式
- 输入模式:浮空输入/上拉输入/下拉输入
- 浮空输入:按键识别
- 上拉输入:IO 内部上拉电阻输入
- 下拉输入:IO 内部下拉电阻输入
- 输出模式:推挽输出/开漏输出
- 推挽输出时,P-MOS 管和 NMOS 管轮流工作,可以输出高电平或低电平。主要用于连接数字器件,如指示灯和继电器等模块;
- 开漏输出时,P-MOS 管关闭,只有 N-MOS 管工作,此时只能输出低电平。要输出高电平必须外加上拉电阻,主要用于 I2C 总线。
- 模拟模式
- 模拟状态:表示引脚功能选择为模拟模式,但不作为任何片内模拟外设的复用脚,只是为了减少系统功耗。
- 模拟外设复用引脚:表示引脚作为片内模拟外设(A/D 转换模块、D/A 转换模块、模拟比较器等)的复用脚,用于完成相应的功能操作。
- 复用模式
在 CubeMX 软件的引脚分配图中点击引脚即可弹出引脚的复用功能 - 复用推挽:片内外设功能(URAT 的 TX,RX,SPI 的 MOSI,MISO,SCK,SS );
- 复用开漏:片内外设功能( I2C 的 SCL,SDA )。
6 基于 HAL 库控制 GPIO
6.1 GPIO 外设的数据类型
- 引脚初始化: 采用结构体类型实现,用于定义引脚的序号、工作模式、输出速度等基本特性。
- 引脚电平状态: 采用枚举类型实现,用于定义引脚的电平状态:高电平和低电平。
- 引脚所属端口: 采用结构体指针实现,用于访问该端口所对应的寄存器组。
引脚初始化数据类型
成员变量 Pin 的取值范围:
GPIO_PIN_0
~GPIO_PIN15
成员变量 Pin 的取值范围:
GPIO_MODE_INPUT 浮空输入模式 GPIO_MODE_OUTPUT_PP 推挽输出模式 GPIO_MODE_OUTPUT_OD 开漏输出模式 GPIO_MODE_AF_PP 复用功能下的推挽模式 GPIO_MODE_AF_OD 复用功能下的开漏模式 GPIO_MODE_ANALOG 模拟模式 成员变量 Pull 的取值范围:
GPIO_NOPULL 没有上拉或下拉电阻激活 GPIO_PULLUP 上拉电阻激活 GPIO_PULLDOWN 下拉电阻激活 成员变量 Speed 的取值范围:
GPIO_SPEED_FREQ_LOW 引脚输出速度 2MHz GPIO_SPEED_FREQ_MEDIUM 引脚输出速度 12.5MHz ~ 50MHz GPIO_SPEED_FREQ_HIGH 引脚输出速度 25MHz ~ 100MHz GPIO_SPEED_FREQ_VERY_HIGH 引脚输出速度 50MHz ~ 200MHz 成员变量 Alternate 的取值范围
- Alternate 表示引脚的复用功能;
- 由于不同型号的 STM32 微控制器片内集成的外设不同,因此该成员变量的取值范围由芯片型号决定。
- 以 STM32F1 系列芯片为例,通过查阅
stm32f1xx_hal_gpio_ex.h
文件可以了解 Alternate 的取值范围; - 该成员变量的取值一般通过 CubeMX 软件分配,不需要用户手动设置;
引脚电平状态数据类型
端口数据类型:指向端口寄存器组的结构体指针
GPIOA
,GPIOB
,GPIOC
…
- 不同型号的 STM32 微控制器的端口数量各不相同;
- 端口数据类型的定义是在以芯片型号命名的.h 文件中.
6.2 使用 HAL 库的引脚初始化步骤
- 定义变量: 利用引脚初始化结构体类型
GPIO_InitTypeDef
定义一个结构体变量。 - 设置模式: 按照引脚的工作模式,依次对该结构体的成员变量赋值,如 pin、mode、pull 等。
- 调用函数: 调用初始化函数
HAL_GPIO_Init
将配置参数写入到对应的寄存器,入口参数为端口号和结构体变量。
6.3 GPIO 外设接口函数的概述
引脚初始化函数:
HAL_GPIO_Init
函数原型 复位引脚到初始状态 功能描述 引脚初始化 入口参数 1 GPIOx:引脚端口号,取值范围是 GPIOA ~ GPIOK 入口参数 2 GPIO_Init:指向引脚初始化类型 GPIO_InitTypeDef 的结构体指针,该结构体包含指定引脚的配置参数 返回值 无 注意事项 该函数可以由 CubeMX 软件自动生成 引脚复位函数:
HAL_GPIO_DeInit
函数原型 void HAL_GPIO_DeInit (GPIO_TypeDef * GPIOx, uint32_t GPIO_Pin) 功能描述 复位引脚到初始状态 入口参数 1 GPIOx:引脚端口号,取值范围是 GPIOA ~ GPIOK 入口参数 2 GPIO_Init:指向引脚初始化类型 GPIO_InitTypeDef 的结构体指针,该结构体包含指定引脚的配置参数 返回值 无 注意事项 该函数需要用户调用 读取引脚函数:
HAL_GPIO_ReadPin
函数原型 GPIO_PinState HAL_GPIO_ReadPin ( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin ) 功能描述 读取引脚的电平状态 入口参数 1 GPIOx:引脚端口号,取值范围是 GPIOA ~ GPIOK 入口参数 2 GPIO_Init:指向引脚初始化类型 GPIO_InitTypeDef 的结构体指针,该结构体包含指定引脚的配置参数 返回值 GPIO_PinState:表示引脚电平状态的枚举类型变量,可以是GPIO_PIN_SET 或 GPIO_PIN_RESET 注意事项 该函数需要用户调用 写入引脚函数:
HAL_GPIO_WritePin
函数原型 void HAL_GPIO_WritePin( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState ) 功能描述 设置引脚输出高/低电平 入口参数 1 GPIOx:引脚端口号,取值范围是 GPIOA ~ GPIOK 入口参数 2 GPIO_Init:指向引脚初始化类型 GPIO_InitTypeDef 的结构体指针,该结构体包含指定引脚的配置参数 返回值 GPIO_PinState:表示引脚电平状态的枚举类型变量,可以是 GPIO_PIN_SET 或 GPIO_PIN_RESET 注意事项 该函数需要用户调用 翻转引脚函数:
HAL_GPIO_TogglePin
函数原型 void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin) 功能描述 翻转引脚状态 入口参数 1 GPIOx:引脚端口号,取值范围是 GPIOA ~ GPIOK 入口参数 2 GPIO_Init:指向引脚初始化类型 GPIO_InitTypeDef 的结构体指针,该结构体包含指定引脚的配置参数 返回值 无 注意事项 该函数需要用户调用
任务实践
基于STM32F103C8T6,开发板原理图
采用查询方式检测按键KEY1状态,按键按下后执行操作:翻转指示灯 LED1 的状态。
注:本任务例程使用的开发板,LED1与STM32的PA1相连接,KEY1与PA0相连接。KEY1原理图如下:
使用按键时,需要设置PA0为输入上拉模式,这样在KEY1没有按下时,PA0可以读取到高电平,KEY1按下时PA0可以读取到低电平。
按键消抖:
通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。
抖动时间的长短由按键的机械特性决定,一般为5ms~10ms。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。
下图为按键按下时,电压波形的变化。
- 前沿抖动 5 ~ 10ms,后沿抖动 5 ~ 10ms
- 按键的抖动会导致一次按键动作被当成多次按键,为确保 MCU 对按键的一次闭合仅作一次处理,必须消除按键的抖动,在按键处于稳定状态时读取按键的状态。
- 硬件消抖:利用 RC 低通滤波器滤掉抖动
- 软件消抖:
- 检测出按键闭合后执行延时程序,延时时间为 5ms ~ 10ms,用于去掉前沿抖动;
- 再次检测按键状态,如果保持闭合状态,才认为按下,并执行相应的按键任务;
- 按键的释放可以采用延时或者循环检测的方式去掉后沿抖动。
- 配置 PA0 为 GPIO_Input,PA1 为 GPIO_Output
- PA1 保持默认 GPIO 输出模式即可
- PA0 配置为输入模式,上拉
以上步骤生成如下代码:
stm32f1xx_hal_gpio.c
中生成 GPIO 引脚初始化函数MX_GPIO_Init
,并在 main.c 中调用
- 开启外设时钟 RCC
- 配置 PA0,PA1 两个引脚结构
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : PA1 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
- 编写程序
在main.c
中编写程序
/* USER CODE BEGIN 3 */
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
HAL_Delay(10);
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET)
{
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
}
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET);
}
}
/* USER CODE END 3 */
-
继电器
+关注
关注
132文章
5332浏览量
148808 -
接口
+关注
关注
33文章
8575浏览量
151014 -
STM32
+关注
关注
2270文章
10895浏览量
355715 -
GPIO
+关注
关注
16文章
1204浏览量
52051 -
HAL库
+关注
关注
1文章
121浏览量
6216
发布评论请先 登录
相关推荐
评论