STM32之GPIO

GPIO 全称 General Purpose Input Output,即通用输入输出端口
负责采集外部器件的信息或者控制外部器件工作

1. STM32 GPIO简介

2.1 特点

  1. 不同型号,IO口数量可能不一样,可通过选型手册快速查询
  2. 快速翻转,每次翻转最快只需要两个时钟周期(F1最高速度可以到50Mhz)
  3. 每个IO口都可以做中断
  4. 支持8种工作模式

2.2 电气特性

  1. 工作电压范围:2 V ≤ VDD ≤ 3.6 V
  2. 识别电压范围:-0.3 ≤ VIL ≤ 1.1641.833 ≤ VIH ≤ 3.6
  3. 输出电流,单个IO口最大输出电流:25mA

2.3 引脚分布

STM32引脚类型可分为:电源引脚、晶振引脚、复位引脚、下载引脚、BOOT引脚、GPIO引脚
下图为STM32F103C8T6引脚分布图:

不同芯片引脚分布情况:

IO引脚分布特点:按组存在、组数视芯片而定、每组最多16个IO引脚

2. IO端口基本结构

史密特触发器是一种整形电路,可以将非标准方波,整形成方波,其特点如下: 1. 有两个阈值,一个高电平阈值,一个低电平阈值
2. 当输入信号超过高电平阈值时,输出为高电平
3. 当输入信号低于低电平阈值时,输出为低电平
4. 当输入信号在两个阈值之间时,输出保持原状态

MOS管是压控型元件,通过控制栅源电压(Vgs)来实现导通或关闭。

3. GPIO的八种模式

GPIO八种模式 特点及应用
输入浮空 输入用,完全浮空,状态不定
输入上拉 输入用,上拉电阻,状态为高电平
输入下拉 输入用,下拉电阻,状态为低电平
模拟功能 ADC、DAC
推挽输出 驱动能力强,25mA(max),通用输出
开漏输出 软件IIC的SDA、SCL等,需要外部上拉电阻
开漏式复用功能 片上外设功能(硬件IIC 的SDA、SCL引脚等)
推挽式复用功能 片上外设功能(SPI 的SCK、MISO、MOSI引脚等)

电路原理分别如下:

  • F4/F7/H7系列和F1系列的GPIO差异点
    1. F1在输出模式,禁止使用内部上下拉
      F4/F7/H7在输出模式,可以使用内部上下拉
    2. 不同系列IO翻转速度可能不同
  • STM32能输出5V电平吗?
    1. STM32最大输出电压为3.3V,不能直接驱动5V器件
    2. 可以通过二极管、电阻、晶闸管等电路进行电平转换

4. GPIO寄存器

(F1系列)GPIO通用寄存器GPIOX_yyy
CRL CRH IDR ODR BSRR BRR LCKR
数配置工作模式,输出速度据类型 输入数据 输出数据 设置ODR寄存器的值 F4之后没有 配置锁定
(F4/F7/H7系列)GPIO通用寄存器GPIOX_yyy
MODER OTYPER OSPEEDR PUPDR IDR ODR BSRR LCKR
设置模式 设置类型 设置速度 设置上下拉电阻 输入数据 输出数据 设置ODR寄存器的值 配置锁定

具体设置可查阅参考手册。

  • ODR和BSRR寄存器控制输出的区别
    1. 使用ODR,在读和修改访问之间产生中断时,可能会发生风险;BSRR则无风险
    2. BSRR寄存器可以设置或清除某个IO口的输出电平,不影响其他IO口
1
2
3
4
GPIOB->ODR |= 1 << 3;          /* PB3 = 1 */
GPIOB->BSRR = 0x00000008; /* PB3 = 1 */
//ODR修改:读 -> 修改 -> 写
//BSRR修改:写
  1. 通用外设驱动模型(四步法)
初始化 时钟设置、参数设置IO设置、中断设置(开中断、设NVIC)(可选)
读函数(可选) 从外设读取数据(可选)
写函数(可选) 往外设写入数据(可选)
中断服务函数(可选) 根据中断标志,处理外设各种中断事务(可选)

6. GPIO配置步骤

步骤 HAL库驱动函数 主要寄存器 功能
1.使能时钟 __HAL_RCC_GPIOA_CLK_ENABLE() F1: RCC->APB2ENR
F4: RCC->AHB1ENR
F7: RCC->AHB1ENR
开启GPIOA时钟
2.设置工作模式 HAL_GPIO_Init() F1:CRL、CRH、ODR
F4/F7:MODER、OTYPER、OSPEEDR、PUPDR
初始化GPIO
3.设置输出状态(可选) HAL_GPIO_WritePin(...)
HAL_GPIO_TogglePin(...)
BSRR
BSRR
控制IO输出高/低电平
每次调用IO输出电平翻转一次
4.读取输入状态(可选) HAL_GPIO_ReadPin(...) IDR 读取IO电平

6.2 关键结构体

F1系列:

1
2
3
4
5
6
7
typedef struct 
{
uint32_t Pin; /* 引脚号 */
uint32_t Mode; /* 模式设置 */
uint32_t Pull; /* 上拉下拉设置 */
uint32_t Speed; /* 速度设置 */
} GPIO_InitTypeDef;

F4/F7/H7系列:

1
2
3
4
5
6
7
8
typedef struct 
{
uint32_t Pin; /* 引脚号 */
uint32_t Mode; /* 模式设置 */
uint32_t Pull; /* 上拉下拉设置 */
uint32_t Speed; /* 速度设置 */
uint32_t Alternate; /* 复用功能 */
} GPIO_InitTypeDef;

7. 点亮一个LED灯

0805贴片发光二极管: - 红色:压降范围1.82~1.88V,电流5~8mA - 绿色:压降范围1.75~1.85V,电流3~5mA - 蓝色:压降范围1.8~2.2V,电流8~10mA

连接原理图:

IO应设置为推挽输出模式,输出高电平点亮LED,输出低电平熄灭LED

led.h

1
2
3
4
5
6
7
//点亮一个LED灯
#ifndef __LED_H
#define __LED_H
#include "./SYSTEM/sys/sys.h"

void led_init(void);
#endif
led.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "./BSP/LED/led.h"

void led_init(void)
{
GPIO_InitTypeDef gpio_init_struct;//定义结构体

__HAL_RCC_GPIOB_CLK_ENABLE();//使能GPIOB时钟

gpio_init_struct.Pin = GPIO_PIN_5;//PB5
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;//低速
HAL_GPIO_Init(GPIOB, &gpio_init_struct);//初始化

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);//点亮LED
}

8. 按键控制LED

8.1 按键消抖

独立按键抖动波形图:

软件消抖:通过延时跳过抖动的时间段,再判断IO输入电平 key.h

1
2
3
4
5
6
7
8
9
//按键消抖
#ifndef __KEY_H
#define __KEY_H
#include "./SYSTEM/sys/sys.h"

void key_init(void);
uint8_t key_scan(void);

#endif
key.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"

void key_init(void) //
{
GPIO_InitTypeDef gpio_init_struct;//定义结构体

__HAL_RCC_GPIOE_CLK_ENABLE();//使能GPIOE时钟

gpio_init_struct.Pin = GPIO_PIN_2;//PE2
gpio_init_struct.Mode = GPIO_MODE_INPUT;//输入
gpio_init_struct.Pull = GPIO_PULLUP;//上拉
HAL_GPIO_Init(GPIOE, &gpio_init_struct);//初始化
}

uint8_t key_scan(void)
{
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_2) == 0)//按键按下
{
delay_ms(10); //延时10ms
if(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_2) == 0)//按键按下
{
while(HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_2) == 0); //等待按键释放
return 1; //按键按下
}
}
return 0; //按键未按下
}

8.2 按键控制LED

连接原理图:

按键在按下和释放时,应有两种稳定的电平输出,以便于判断按键状态
PA0应该设置为输入下拉
- 按键按下时,形成通路,为高电平
- 未按下时,为高阻态,通过下拉电阻,得到稳定的低电平
PE4/PE3/PE2应设置为输入上拉
- 按键按下时,为低电平(接地);
- 未按下时,通过上拉电阻,得到稳定的高电平

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/KEY/key.h"


int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */
delay_init(72); /* 延时初始化 */
led_init(); /* LED初始化 */
key_init(); /* KEY初始化 */
while(1)
{
if(key_scan())
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
}
else
{
delay_ms(10);
}
}
}

声明:本文内容来源正点原子如有侵权,请联系删除。