STM32之GPIO
GPIO
全称General Purpose Input Output
,即通用输入输出端口
负责采集外部器件的信息或者控制外部器件工作
1. STM32 GPIO简介
2.1 特点
- 不同型号,IO口数量可能不一样,可通过选型手册快速查询
- 快速翻转,每次翻转最快只需要两个时钟周期(F1最高速度可以到50Mhz)
- 每个IO口都可以做中断
- 支持8种工作模式
2.2 电气特性
- 工作电压范围:
2 V ≤ VDD ≤ 3.6 V
- 识别电压范围:
-0.3 ≤ VIL ≤ 1.164
,1.833 ≤ VIH ≤ 3.6
- 输出电流,单个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差异点
- F1在输出模式,禁止使用内部上下拉
F4/F7/H7在输出模式,可以使用内部上下拉
- 不同系列IO翻转速度可能不同
- F1在输出模式,禁止使用内部上下拉
- STM32能输出5V电平吗?
- STM32最大输出电压为3.3V,不能直接驱动5V器件
- 可以通过二极管、电阻、晶闸管等电路进行电平转换
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寄存器控制输出的区别
- 使用ODR,在读和修改访问之间产生中断时,可能会发生风险;BSRR则无风险
- BSRR寄存器可以设置或清除某个IO口的输出电平,不影响其他IO口
1 | GPIOB->ODR |= 1 << 3; /* PB3 = 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
7typedef 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
8typedef 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灯
void led_init(void);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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//按键消抖
void key_init(void);
uint8_t key_scan(void);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
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
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);
}
}
}
声明:本文内容来源正点原子如有侵权,请联系删除。