GPIO 是 General Purpose Input Output 的缩写,意思是通用输入输出。
它是单片机最基础的外设,几乎所有外设交互都离不开它。
上一篇我们用库函数点亮了 LED,本篇将深入 GPIO 的 8 种工作模式。
并从寄存器层面理解它的工作原理。
一、STM32F1 的 8 种 GPIO 模式
STM32F1 的 GPIO 分为输入 4 种加输出 4 种,共 8 种模式。
输入模式有以下 4 种。
第一种是浮空输入。
它的配置值是 GPIO_Mode_IN_FLOATING。
特点是无上下拉电阻,电平由外部信号决定。
常用于串口 RX 和 SPI MISO 等复用输入引脚。
第二种是上拉输入。
它的配置值是 GPIO_Mode_IPU。
特点是悬空时默认高电平。
常用于一端接 GND 的按键。
第三种是下拉输入。
它的配置值是 GPIO_Mode_IPD。
特点是悬空时默认低电平。
常用于一端接 VCC 的按键。
第四种是模拟输入。
它的配置值是 GPIO_Mode_AIN。
特点是关闭数字输入电路,纯模拟通道。
用于 ADC 电压采集。
输出模式有以下 4 种。
第一种是推挽输出。
它的配置值是 GPIO_Mode_Out_PP。
特点是可以输出强高低电平。
常用于 LED 和继电器等。
第二种是开漏输出。
它的配置值是 GPIO_Mode_Out_OD。
特点是高电平为高阻态,需要外部上拉。
常用于 I2C 总线和线与结构。
第三种是复用推挽。
它的配置值是 GPIO_Mode_AF_PP。
特点是由外设硬件控制输出,推挽结构。
常用于串口 TX 和 PWM 输出。
第四种是复用开漏。
它的配置值是 GPIO_Mode_AF_OD。
特点是由外设硬件控制输出,开漏结构。
常用于 I2C 的 SDA 和 SCL 引脚。
二、模式选择速查
不同场景需要选择不同的 GPIO 模式。
点灯或者控制 LED,用推挽输出 Out_PP。
读按键,用上拉输入 IPU。
ADC 电压采集,用模拟输入 AIN。
I2C 通信,用复用开漏 AF_OD。
PWM 输出,用复用推挽 AF_PP。
需要注意一个易错点。
开漏输出如果不接上拉电阻,高电平实际上是高阻态,无法驱动外部电路。
三、寄存器级配置 GPIO
库函数本质上是对寄存器的封装。
理解寄存器可以帮助我们更深入地掌握 GPIO。
STM32F1 的 GPIO 主要有以下几个寄存器。
第一个是 CRL 寄存器。
它用于配置 PIN0 到 PIN7 的模式和速度。
每个引脚占 4 位,其中 2 位配置模式,2 位配置速度。
第二个是 CRH 寄存器。
它用于配置 PIN8 到 PIN15 的模式和速度。
结构和 CRL 相同。
第三个是 IDR 寄存器。
它是输入数据寄存器,只读。
用于读取引脚的当前电平状态。
第四个是 ODR 寄存器。
它是输出数据寄存器,可读写。
用于设置引脚输出的电平。
第五个是 BSRR 寄存器。
它是位设置或清除寄存器。
高 16 位用于清除对应的 ODR 位,低 16 位用于设置对应的 ODR 位。
写 1 有效,写 0 不影响。
第六个是 BRR 寄存器。
它是位清除寄存器。
用于清除 ODR 对应的位,相当于 BSRR 高 16 位的功能。
四、位操作技巧
在嵌入式开发中,位操作是基本功。
常用的位操作有以下几种。
置位操作,将某一位置 1,其他位不变。
通常用按位或运算实现。
清零操作,将某一位清 0,其他位不变。
通常用按位与运算配合取反实现。
翻转操作,将某一位取反,其他位不变。
通常用按位异或运算实现。
读取操作,读取某一位的值。
通常用按位与运算配合右移实现。
STM32 还支持位带操作。
位带操作就是把一个位映射到一个单独的地址。
通过读写这个地址,就可以直接操作对应的位。
这样可以实现原子操作,不会被中断打断。
位带区包括 SRAM 位带区和外设位带区。
五、按键扫描实战
按键是嵌入式最常见的输入设备。
机械按键在按下和松开时会产生抖动,需要做消抖处理。
消抖的方法有硬件消抖和软件消抖两种。
硬件消抖是通过 RC 滤波电路实现。
优点是不占用 CPU 资源,缺点是增加硬件成本。
软件消抖是在检测到按键状态变化后,延时一段时间再重新检测。
如果两次状态一致,说明按键状态稳定。
优点是无需额外硬件,缺点是占用 CPU 时间。
按键扫描的基本流程如下。
第一步,配置按键引脚为输入模式,通常用上拉输入。
第二步,读取引脚电平,判断按键是否按下。
第三步,如果检测到按下,延时消抖。
第四步,再次读取引脚电平,确认按键状态。
第五步,执行按键对应的功能。
第六步,等待按键松开,防止重复触发。
六、常见误区
误区一,开漏输出不接上拉电阻。
开漏输出的高电平是高阻态,必须外接上拉电阻才能输出高电平。
误区二,忘记开启 GPIO 时钟。
STM32 所有外设默认时钟关闭,使用 GPIO 前必须开启对应总线的时钟。
误区三,按键不做消抖。
机械按键的抖动会导致一次按下被识别为多次,必须做消抖处理。
误区四,混用输入输出模式。
同一个引脚不能同时配置为输入和输出。
需要根据实际功能选择正确的模式。
误区五,忽略引脚的 5V 容忍特性。
STM32F1 大部分引脚是 5V 容忍的,但不是全部。
使用前需要查看数据手册确认。
小结
本篇我们深入学习了 GPIO 的 8 种工作模式和寄存器级配置方法。
掌握了位操作技巧和按键扫描的基本流程。
下一篇我们将学习 C 语言在嵌入式开发中的实用技巧。
敬请期待。