【STM32F407学习笔记】点亮一个LED
1. STM32 GPIO简介
1.1 GPIO简介
GPIO是通用输入输出端口的简称,GPIO的最基本功能是输出和输出。它也是芯片内部和外部电路连接的唯一接口。
GPIO的基本功能是输入和输出,但是STM32本身就是一个很复杂的系统,内部外设繁多,基本的GPIO功能是无法满足外设需求的,因此将GPIO分为8种模式。
- 输入浮空
- 输入上拉
- 输入下拉
- 模拟输入
- 具有上拉或下拉功能的开漏输出
- 具有上拉或下拉功能的推挽输出
- 具有上拉或下拉功能的复用功能推挽
- 具有上拉或下拉功能的复用功能开漏
这八种模式对应外设不同的工作要求。
1.2 GPIO内部结构
GPIO内部结构分为上下两大部分,输入部分位于图的上半部分1、2、3、4,输出部分为下半部分5、6、7、8。
- 上、下拉电阻
图中部分1,引脚舢板部分上拉电阻接VDD,下半部分下拉电阻接Vss。上下拉电阻有对应的开关配置。可以通过打开或者关闭对应电阻的开关,来控制引脚默认状态的电压。开启上拉时引脚位高电平,开启下拉时引脚为低电平。这样就可以在没有外接器件时,使得引脚处于一个确定的电平状态,而不是处于一个不稳定电平状态。当然也有时需要将引脚电平设置成既不上拉也不下拉的浮空模式。串口的输入引脚一般就配置成浮空输入模式。 - 模拟输入
图中部分2,信号经过引脚进入输入通道,然后不经过施密特触发器,直接进入模拟输入,这就是“模拟输入模式”。一般ADC采集电压时它的输入通道就会配置成模拟输入模式。电信号经过施密特触发器之后只有0、1两种状态,这也是为什么模拟信号输入源需要在施密特触发器前。 - 复用功能输入
图中部分3,输入信号经过施密特触发器之后有两条去处,一个通过“复用功能输入”到片上外设,另一个直接流入“输入数据寄存器”。输入信号同时只能有一个去处,不可能既进入复用通道又进入输入寄存器,这个去向是由“GPIO端口模式寄存器GPIOx_MODER”控制的。
复用指:片上其他外设对GPIO引脚进行控制,此时GPIO引脚可以视作该外设功能的一部分,也是内部外设与外部电路通信的接口。GPIO引脚信号经由复用功能输入通道,传输到STM32片上外设,由该外设获取引脚转台。 - 通用输入
图中部分4,GPIO引脚输入的信号经过上、下拉电阻后,又经过施密特触发器,将模拟信号转换为高低电平,然后存储在“输入数据寄存器GPIOx_IDR”中,读取该寄存器就可以获取GPIO引脚输入的电平状态。 - 开漏输出模式和推挽输出模式
图中部分5,输出信号经由“输出控制器”进入部分5。此部分是由P-MOS和N-MOS管组成的单元电路。所谓推挽和开漏,是根据这两个MOS管的工作方式来命名的。- 推挽输出:5部分中输入高电平时,上方的P-MOS导通,下方N-MOS关闭,对外输出高电平;5部输入低电平时,N-MOS管导通,上方P-MOS关闭,对外输出低电平。当引脚高低电平切换时,两MOS管轮流导通。推挽输出低电平0V,高电平3.3V。一般应用在输出电平为0V和3.3V而且需要高速切换开关状态的场景。
- 开漏输出:5部分上方的P-MOS完全不工作。控制输出为0,则P-MOS关闭,N-MOS导通;控制输出为1,则P-MOS和N-MOS都关闭,既不输出高电平,也不输出低电平,呈高阻态。所以“开漏输出模式”需要输出高电平时,必须要接上拉电阻。一般应用在I2C,SMBUS通讯等需要“线与”功能的总线电路。除此之外还可以应用在电平不匹配的场合如需要输出5V的高电平,可以在外部接一个上拉电阻,上拉电源5V。
- 通用输出
图中部分6,“置位/复位寄存器(GPIOx_BSSR)” 置位/复位输出数据寄存器相应的位,"输出数据寄存器(GPIOx_ODR)"为部分5的MOS管电路单元提供输出电平,从而控制GPIO引脚电平。 - 复用功能输出
图中部分7,使用复用功能时,片上外设输出的电平通过“复用功能输出”通道,进入部分5的MOS管电路单元,进而控制GPIO引脚电平。 - 模拟输出
图中部分8,为模拟输出通道,DAC外设输出通道一般会用此模式。
1.3 GPIO相关寄存器
GPIO外设一共有九个寄存器:
- GPIO端口模式寄存器(GPIOx_MODER)
- GPIO端口输出类型寄存器(GPIOx_OTYPER)
- GPIO端口输出速度寄存器(GPIOx_OSPEEDR)
- GPIO端口上拉/下拉寄存器(GPIOx_PUPDR)
- GPIO端口输入数据寄存器(GPIOx_IDR)
- GPIO端口输出数据寄存器(GPIOx_ODR)
- GPIO端口配置锁定寄存器(GPIOx_LCKR)
- GPIO端口复用功能低位寄存器(GPIOx_AFRL)高位寄存器(GPIOx_AFRH)
- GPIO端口置位/复位寄存器(GPIOx_BSRR)
GPIO的配置表如图中所示:
MODER:00(输入),01(输出),10(复用)
OTYPER:0(推挽),1(开漏)
OSPEEDER:00(低速 2MHz),01(中速 25MHz),10(快速 50MHz),11(高速 100MHz)
PUPDR:00(无上下拉,浮空),01(上拉),10(下拉),11(保留)
2. 硬件链接
在STM32F4Discovery的板载资源中,PD12~PD15连接着四个LED供用户编程使用。
如果想让LD4 ~ LD6点亮,则PD12 ~ PD15需要输出为高电平;熄灭LD4 ~ LD6,则PD12 ~ PD15 输出低电平。
3. 软件设计
GPIO初始化的基本流程:
- 使能GPIOD的时钟
- 配置GPIOD的端口12~15
- 配置PD12 ~ PD15的模式为输出 (GPIOD_MODER)
- 配置PD12 ~ PD15 的模式为推挽 (GPIOD_OTYPER)
- 配置输出速度为高速(GPIO_OSPEEDR)
- 初始化GPIOB(初始化相应寄存器)
点亮LED
#include "stm32f4xx.h"
void delay(uint32_t cnt)
{
uint32_t i,j;
for ( i = 0; i < cnt; i++)
{
for ( j = 0; j < 0xFFF; j++)
{
}
}
}
int main()
{
GPIO_InitTypeDef GPIOInitStructure;
// 使能GPIOD的时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
GPIOInitStructure.GPIO_Pin=GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;// 引脚号
GPIOInitStructure.GPIO_Mode=GPIO_Mode_OUT; // 通用输出
GPIOInitStructure.GPIO_OType=GPIO_OType_PP; // 推挽输出
GPIOInitStructure.GPIO_PuPd=GPIO_PuPd_UP; // 上拉(在推挽输出中配置上拉下拉,浮空都可以,上下拉主要是在输入中有用)
GPIOInitStructure.GPIO_Speed=GPIO_Speed_100MHz; // 速度100MHz
GPIO_Init(GPIOD,&GPIOInitStructure); // 初始化
while(1)
{
GPIO_SetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13);
delay(1000);
GPIO_ResetBits(GPIOD,GPIO_Pin_12|GPIO_Pin_13);
delay(1000);
}
}