一、 GPIO定义
GPIO(General-purpose input/output),通用型输入输出的简称,功能类似8051的P0~P3,其接脚可以供使用者由程控自由使用,PIN按工程需求可作为通用输入(GPI)或通用输出(GPO)或通用输入与输出(GPIO)。既然一个引脚可以用于输入、输出或其他特殊功能,那么一定有寄存器用来选择这些功能。对于输入,一定可以通过读取某个寄存器来确定引脚电位的高低;对于输出,一定可以通过写入某个寄存器来让这个引脚输出高电位或者低电位;对于其他特殊功能,则有另外的寄存器来控制它们。
二、 GPIO结构
STM32的GPIO基本结构如图1所示,按输入输出方向可以分为两个区域,分别是输入区和输出区,详细地分为9个部分,包括二极管保护电路、推挽输出控制电路、输出数据寄存器、复用功能输出、输入数据寄存器、复用功能输入、模拟输入、施密特(肖特基)触发器和上/下拉电路。
图1 GPIO基本结构
各部分具体功能如下:
① 二极管保护电路:由两个保护二极管组成,芯片的引脚电平0~3.3V,部分引脚可以5V,引脚的两个保护二级管可以防止引脚外部过高或过低的电压输入;
② 推挽输出控制电路:由一个PMOS和一个NMOS共同组成,通过控制两个管子的工作状态可以将单片机设置为推挽、开漏或关闭;
③ 输出数据寄存器:双 MOS 管结构电路的输入信号,是由 GPIO“输出数据寄存器GPIOx_ODR”提供的,因此我们通过修改输出数据寄存器的值就可以修改 GPIO 引脚的输出电平。而“置位/复位寄存器 GPIOx_BSRR”可以通过修改输出数据寄存器的值从而影响电路的输出;
④ 复用功能输出:由于 STM32 的 GPIO 引脚具有第二功能,因此当使用复用功能的时候,也就是通过其他外设复用功能输出信号与 GPIO 数据寄存器一起连接到双 MOS 管电路的输入,其中梯形结构是用来选择使用复用功能还是普通 IO 口功能;
⑤ 输入数据寄存器:输入数据寄存器是由 IO 口经过上下拉电阻、施密特触发器引入。当信号经过触发器,模拟信号将变为数字信号 0 或 1,然后存储在输入数据寄存器中,通过读取输入数据寄存器 GPIOx_IDR 就可以知道 IO口的电平状态;
⑥ 复用功能输入:此模式与复用功能输出类似。在复用功能输入模式时,GPIO引脚的信号传输到 STM32其他片上外设,由该外设读取引脚的状态;
⑦ 模拟输入:当 GPIO 引脚用于 ADC 采集电压的输入通道时,用作“模拟输入”功能,此时信号是不经过施密特触发器的,因为经过施密特触发器后信号只有 0、1 两种状态,ADC 外设要采集到原始的模拟信号,信号源输入必须在施密特触发器之前;
⑧ 施密特(肖特基)触发器:施密特触发器(Schmitt Trigger)是一种具有两个阈值的比较器电路,其作用是将输入信号转换为稳定的数字输出信号。主要作用有以下几个方面:
a. 噪声滤除:施密特触发器具有滞后特性,当输入信号的幅度超过某个高阈值时,输出状态会翻转,而在输入信号的幅度低于某个低阈值时,输出状态再次翻转。这种滞后特性可以抑制输入信号中的瞬态噪声,使输出信号对噪声更加稳定和可靠。
b. 输入信号调整:施密特触发器可以调整输入信号的幅度范围。通过设置合适的高阈值和低阈值,可以将输入信号的波形范围限定在一个特定的范围内,并将较小的波动或幅度变化转换为稳定的数字输出。
c. 信号整形和判断:施密特触发器可以将不规则的输入信号转换为方波或脉冲信号。它可以在输入信号的上升或下降沿产生稳定的输出状态转换,用于触发其他数字逻辑电路的操作或判断条件。
d. 电压转换:施密特触发器可以将输入信号从一种电平转换为另一种电平。例如,将一个变化的模拟信号转换为二进制的高低电平表示,或者将一个非标准的输入信号转换为标准的逻辑电平。
总的来说,施密特触发器在数字电路中起到信号整形、噪声滤除和电平转换的作用;
⑨ 上/下拉电路:由一个上拉电阻和一个下拉电阻组成,上拉和下拉电阻上都有一个开关,通过配置上下拉电阻开关,可以控制引脚的默认状态电平。当开启上拉时引脚默认电压为高电平;开启下拉时,引脚默认电压为低电平,这样就可以消除引脚不定状态的影响;将上拉和下拉的开关都关断,这种状态称为浮空模式,该模式下引脚的电压是不确定的。STM32 上下拉及浮空模式的配置是通过GPIOx_CRL 和 GPIOx_CRH 寄存器控制的。STM32 内部的上拉其实是一个弱上拉,也就是说通过此上拉电阻输出的电流很小,如果想要输出一个大电流,那么就需要外接上拉电阻。
三、 GPIO工作模式
根据工程实际需要,通过配置相应寄存器STM32的GPIO可配置为8种工作模式,其特征如下表所示:
表1 GPIO工作模式
模式名称 | 方向 | 特征 |
---|---|---|
浮空输入 | 数字输入 | 可读取引脚电平,若引脚悬空,则电平为三态 |
上拉输入 | 数字输入 | 可读取引脚电平,内部连接上拉电阻,悬空默认为高 |
下拉输入 | 数字输入 | 可读取引脚电平,内部连接下拉电阻,悬空默认为低 |
模拟输入 | 数字输入 | GPIO无效,引脚直接接入内部ADC |
开漏输出 | 数字输出 | 可输出引脚电平,高电平为高阻态,低电平接VSS |
推挽输出 | 数字输出 | 可输出引脚电平,高电平为VDD,低电平接VSS |
复用开漏输出 | 数字输出 | 由片上外设控制,高电平为高阻态,低电平接VSS |
复用推挽输出 | 数字输出 | 由片上外设控制,高电平为VDD,低电平接VSS |
具体介绍如下:
- 输入模式:
① 浮空输入:输入引脚的上下拉电阻都不接,电平完全由外部的输入决定,但此时输入电平极易受外界的干扰,导致输入电平不确定;
② 上拉输入:输入引脚的上拉电阻接入,给一个默认的高电平,当没有外部输入时默认输入高电平;
③ 下拉输入:输入引脚的下拉电阻接入,给一个默认的低电平,当没有外部输入时默认输入低电平;
④ 模拟输入:此时输入电路不经过施密特触发器,用来采集外部的模拟信号,例如连续变化的电压,电流,温度等等。 - 输出模式:
输出结构如图2所示,由输出控制器及两个MOS管构成,一个PMOS一个NMOS。
图2 输出结构图
① 开漏输出:此模式下只有NMOS管工作,当输出寄存器输出高电平,则引脚输出高阻态;当输出寄存器输出低电平,则引脚输出低电平;
② 推挽输出:此模式下两个MOS管均工作,当输出寄存器输出高电平,则引脚也输出高电平;当输出寄存器输出低电平,则引脚也输出低电平;
③ 复用开漏/推挽输出:复用功能模式中,输出使能,输出速度可配置,可工作在开漏及推挽模式,但是输出信号源于其它外设,输出数据寄存器 GPIOx_ODR 无效;输入可用,通过输入数据寄存器可获取 I/O 实际状态,但一般直接用外设的寄存器来获取该数据信号。
另外,电路中VCC、VDD、VEE、VSS分别指什么呢?
VCC:C=circuit,表示电路的意思,即接入电路的电压。
VDD:D=device,表示器件的意思,即器件内部的工作电压。
VEE:E=Emitter,表示发射极电源电压,一般用于ECL电路的负电源电压。
VSS:S=series,表示公共连接的意思,通常指电路公共接地端电压。
一般来说VCC=模拟电源,VDD=数字电源,VSS=数字地,VEE=负电源
四、 常用应用场景
- 控制LED灯:GPIO可以用来控制LED灯的亮灭状态,通过设置GPIO引脚为输出模式,并控制引脚的电平状态,实现LED灯的开关和闪烁效果。
- 按键输入:GPIO可以作为输入接口,用于读取外部按键的状态。通过配置GPIO引脚为输入模式,并读取引脚的电平状态,可以实现按键的检测和触发相应的操作。
- 传感器接口:许多传感器(如温度传感器、湿度传感器等)可以通过GPIO与嵌入式系统进行通信。例如,通过I2C或SPI协议将传感器连接到特定的GPIO引脚,从而读取传感器提供的数据。
- 驱动电机:GPIO可以用作控制电机的引脚,通过控制引脚的电平状态和时序,实现电机的正转、反转、速度控制等功能。
- 触摸屏输入:某些嵌入式设备使用触摸屏作为主要的输入方式。GPIO可以用于读取触摸屏的输入信号,通过配置GPIO引脚为输入模式,并使用相应的驱动程序,实现触摸屏的触摸检测和坐标获取。
- 外部设备控制:除了上述应用场景,GPIO还可以用于与其他外部设备进行通信和控制。例如,与LCD显示屏、蜂鸣器、继电器等设备进行连接,通过GPIO控制这些设备的工作状态。
五、 例程分析
此处以驱动LED闪烁为例,步骤如下:
- 引入所需头文件;
- 主进程:
使能APB总线时钟;
定义GPIO结构体变量,并初始化:
选择推挽输出模式;
选择输出引脚;
选择引脚频率;
大循环中进行亮、延时、灭延时动作循环。
完整代码如下:
#include "stm32f10x.h" // Device header
#include "Delay.h"
int main(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
while (1)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
GPIO_SetBits(GPIOA, GPIO_Pin_0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_RESET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, Bit_SET);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)0);
Delay_ms(500);
GPIO_WriteBit(GPIOA, GPIO_Pin_0, (BitAction)1);
Delay_ms(500);
}
}
六、 总结
GPIO是学习一款单片机的基础,本文针对于STM32单片机GPIO的整体架构和工作模式进行了详细的介绍,在工程应用中需要根据需求选择合适的工作模式,最后结合一段代码对具体使用流程进行了拆解与分析。