STM32 GPIO引脚配置与使用详解
一、GPIO简介
1. 基本介绍
GPIO是通用输入输出端口的简称,STM32芯片通过GPIO与外设连接,从而实现与外设的数据收发。
STM32的GPIO被分成了很多组/端口(Port),每个Port有16个引脚(Pin),如STM32F103ZET6芯片就有GPIOA~GPIOG 7个端口144个引脚,部分引脚除了作为GPIO使用之外,还有其它专用功能在复用。
2. 工作模式
GPIO有8中工作模式,如图所示
浮空输入:由于没有接上拉电阻或下拉电阻,电平的高低完全取决于外部的输入,所以浮空输入电平极易受到外界的干扰,一般接按键会用到这个模式。
开漏输出等效电路如下图
推挽输出等效电路如下图
3. 框图分析
1. 保护二极管
2. 输入、输出驱动器
3. 输出数据寄存器
通过写程序来设置输出数据寄存器GPIOx_ODR
的值,以此来实现输出控制高低电平
置位/复位寄存器GPIOx_BSRR
可以通过修改输出数据寄存器的值来影响电路的输出
4. 复用功能输出
5. 输入数据寄存器:就是将肖特基触发器转换后的0/1数字信号,存储到输入数据寄存器中GPIOx_IDR中
,通过读取该寄存器就可以知道该该GPIO引脚的电平
6. 复用功能输入与复用功能输出类似,不多介绍
7. 模拟输入:一般用于ADC采集电压,此时信号不经过肖特基触发器,从而得到ADC外设采集到的原始模拟信号
4. 寄存器
GPIO配置寄存器:GPIO的每个端口都有2个对应的端口配置寄存器,端口上的每个引脚需要4位来进行配置,因此每个寄存器只能配置8个引脚,所以每个端口的16个引脚需要2个寄存器来配置。
GPIOx_IDR
寄存器读取IO状态,此时GPIOx_ODR
无效。GPIOx_ODR
寄存器输出高低电平,此时输出速度配置的越高功耗越大。输出模式时,肖特基触发器是打开的,所以即便是输出模式也可以通过GPIOx_IDR
读取IO的实际状态。GPIOx_ODR
无效,但可以通过GPIOx_IDR
寄存器读取IO状态,一般直接用外设寄存器来获取。端口输入数据寄存器
端口输出数据寄存器
端口位设置/清除寄存器
二、程序示例
1. GPIO输出——点亮LED
1.1 原理图
1.2 配置寄存器
控制LED为输出
GPIOB_CRL
的[MODE0/1/5]配置为输出模式,最大速度50MHz(此处对最大速度无要求,随便选一个即可)GPIOB_CRL
的[CNF0/1/5]配置为通用推挽输出模式控制LED灯亮
GPIOB_ODR
的[ODR0/1/5]配置为0,或者对GPIOB_BSRR
的[BR0/1/5]置1并且对[BS0/1/5]清0控制LED灯灭
GPIOB_ODR
的[ODR0/1/5]配置为1,或者对GPIOB_BSRR
的[BS0/1/5]置11.3 程序示例
/* --------------------bsp_gpio_led.h--------------------- */
/* 自定义数据结构 */
#define LED_PORT GPIOB
typedef enum
{
LED_R = GPIO_Pin_5,
LED_G = GPIO_Pin_0,
LED_B = GPIO_Pin_1,
}LED_Typedef;
/* -------------------bsp_gpio_led.c--------------------- */
void GPIO_LED_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = LED_R;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(LED_PORT, &GPIO_InitStruct);
}
void GPIO_LED_On(LED_Typedef LED_Type)
{
GPIO_ResetBits(LED_PORT, (uint16_t)LED_Type);
}
void GPIO_LED_Off(LED_Typedef LED_Type)
{
GPIO_SetBits(LED_PORT, (uint16_t)LED_Type);
}
2. GPIO输入——检测按键
2.1 原理图
2.2 数据手册
2.3 示例代码
/* --------------------bsp_gpio_key.h--------------------- */
#define KEY1_PORT GPIOA
#define KEY2_PORT GPIOC
typedef enum
{
KEY1 = GPIO_Pin_0,
KEY2 = GPIO_Pin_13
}KEYNum_Typedef;
typedef enum
{
Key_Relase,
Key_Press
}KEYStatus_Typedef;
/* --------------------bsp_gpio_key.c--------------------- */
void GPIO_KEY_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Pin = KEY1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(KEY1_PORT, &GPIO_InitStruct);
}
/* 返回指定按键的状态 */
KEYStatus_Typedef GPIO_KEY_Status(KEYNum_Typedef KEYNum)
{
KEYStatus_Typedef ret_status;
if(KEYNum == KEY1)
ret_status = GPIO_ReadInputDataBit(KEY1_PORT, KEYNum);
else
ret_status = GPIO_ReadInputDataBit(KEY2_PORT, KEYNum);
return ret_status;
}