硬件环境:stm32f407zet6 软件环境:mdk5
1.GPIO概述
GPIO,翻译为通用输入输出,也就是软件可编程引脚,也就是MCU通过控制GPIO来完成一系列的功能。
GPIO属于引脚,但引脚还包含电源、晶振、下载、boot、复位等,这一部分组成的电路同时也叫做单片机最小系统
同一个GPIO可以作为多种外设功能的引脚,在芯片对应的数据手册中有比较详细的引脚功能说明
在STM32F407中,除了ADC引脚,其他引脚都是可以5V容忍
所谓5V容忍就是可以正常识别5V的逻辑电平信号而不至于因为逻辑电平电压高于自身的3.3V标准而损坏芯片
在STM32中,将GPIO分为多组,每组最多16个,每个GPIO都可以进行输出类型、模式、上下拉、输出速度的配置。
看图
在STM32中所有的GPIO操作均是围绕下图展开的。
- 输出类型
输出类型可以分为推挽输出和开漏输出。
推挽输出
当输出一个低电平,首先经过反相器变成一个高电平,当为高电平时,NMOS管工作,IO口与地线短接,从而输出低电平,此时电源电流输出到负载,也叫灌电流,可以理解为推
当输出一个高电平,首先经过反相器变成一个低电平,当为低电平时,PMOS管工作,IO口与VDD短接,从而输出高电平,此时负载电流流入到芯片,也叫拉电流,可以理解为挽
推挽输出电流驱动能力是很大的,因为MOS管在工作的时候,其内阻非常小,因此VDD输入电流可近似等于IO口输出电流
开漏输出
开漏模式下,PMOS管不工作,只能输出低电平,同推完输出,输出高电平时IO口将呈现高组态的状态。 - 模式
可以设置为输入、输出、复用、模拟四种工作模式
输入模式下,TTL施密特触发器工作,本质就是将引脚上电压转换成开关量,当电压低于一个值判断为逻辑0,高于一个值判断为逻辑1.
模拟模式分为输入和输出模式,分别工作在ADC采集和DAC输出的时候,配置为此模式时外设引脚直接连接到对应的模拟线路上
输出电平可以通过设置数据寄存器来控制,也可以用过置位复位寄存器控制,后者的优势在于不用考虑当前寄存器的值 - 上下拉
可以选择是否启用上下拉电阻,比如开漏模式下需要输出高电平,则需要外接上拉电阻来实现 - 输出速度
可以设置为 2M、25M、50M、100M(30 pF 时为 100 MHz(高速)(15 pF 时为 80 MHz 输出(最大速度)))。
100M输出速度是什么意思?
对于CMOS工艺的集成电路而言,输入阻抗是非常高的,主要功耗来自于绝缘栅等效的电容充放电效应。既然是电容的充放电,考虑信号源的内阻(基于标准CMOS电路的输出),根据RC充电常数和逻辑门限电平就能得出一个最小周期,其对应一个最高IO频率。
2.GPIO寄存器分析
直接看数据手册不就好了嘛,干嘛要抄一遍,费时费力又没有什么意义
3.GPIO编程实例
以标准的LED控制程序为例
- 固件库
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); //开启GPIOF的时钟
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //设置为输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //设置为推挽输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //设置为上拉模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //设置输出速度为100M
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_Init(GPIOF, &GPIO_InitStructure);
- BB库
//定义LED
typedef enum
{
LED1 = 0,
LED2
} LEDx_t;
//LED状态
typedef enum
{
LED_OFF = 0,
LED_ON
} LED_Status_t;
//LED引脚
typedef enum
{
LED1_PIN = BB_GPIO_PIN_9,
LED2_PIN = BB_GPIO_PIN_10
} LED_Pin_t;
//定义GPIO引脚
typedef enum
{
BB_GPIO_PIN_0 = 0,
BB_GPIO_PIN_1,
BB_GPIO_PIN_2,
BB_GPIO_PIN_3,
BB_GPIO_PIN_4,
BB_GPIO_PIN_5,
BB_GPIO_PIN_6,
BB_GPIO_PIN_7,
BB_GPIO_PIN_8,
BB_GPIO_PIN_9,
BB_GPIO_PIN_10,
BB_GPIO_PIN_11,
BB_GPIO_PIN_12,
BB_GPIO_PIN_13,
BB_GPIO_PIN_14,
BB_GPIO_PIN_15
} BB_GPIO_Pin_t;
BB_RCC_AHB1_PeriphClock_Enable(RCC_AHB1Periph_GPIOF); //开启GPIOF的时钟
BB_GPIO_Mode(GPIOF, (BB_GPIO_Pin_t)LED1_PIN, GPIO_Mode_OUT); //设置为输出模式
BB_GPIO_OType(GPIOF, (BB_GPIO_Pin_t)LED1_PIN, GPIO_OType_PP); //设置为推挽输出
BB_GPIO_Speed(GPIOF, (BB_GPIO_Pin_t)LED1_PIN, GPIO_Speed_100MHz); //设置输出速度为100M
BB_GPIO_PuPd(GPIOF, (BB_GPIO_Pin_t)LED1_PIN, GPIO_PuPd_UP); //设置为上拉模式
BB_GPIO_Mode(GPIOF, (BB_GPIO_Pin_t)LED2_PIN, GPIO_Mode_OUT);
BB_GPIO_OType(GPIOF, (BB_GPIO_Pin_t)LED2_PIN, GPIO_OType_PP);
BB_GPIO_Speed(GPIOF, (BB_GPIO_Pin_t)LED2_PIN, GPIO_Speed_100MHz);
BB_GPIO_PuPd(GPIOF, (BB_GPIO_Pin_t)LED2_PIN, GPIO_PuPd_UP);
BB_GPIO_SetBits(GPIOF, (BB_GPIO_Pin_t)LED1_PIN); //默认熄灭LED
BB_GPIO_SetBits(GPIOF, (BB_GPIO_Pin_t)LED2_PIN);