GPIO
一.GPIO简介
<1>什么是GPIO
General Purpose Input Output,即通用输入输出端口,简称GPIO.
作用:负责采集外部器件的信息或者控制外部器件工作,即输入输出。
<2>STM32GPIO简介
1.GPIO特点
- 不同型号,IO口数量可能不一样,可通过选型手册快速查询;
- 快速翻转,每次翻转最快只需要两个时钟周期(F1最高速度可以达到50Mhz);
- 每个IO口都可以做中断;
- 支持8种工作模式。
2.GPIO工作特性
GPIO工作电压范围:2V≤VDD≤3,6V
GPIO识别电压范围:CMOS端口:-0.3V≤VIL(逻辑0)≤1.164V;1.833V≤VIH(逻辑1)≤3.6V.
注意:除了CMOS端口还有TTL端口,在数据手册标为FT则为TTL端口,其他都是CMOS端口。
GPIO输出电流:单个IO,最大25mA.
GPIO引脚分布:
电源引脚,晶振引脚,复位引脚,下载引脚,BOOT引脚,GPIO引脚。
二.IO端口基本结构
施密特触发器:就是一种整形电路,可以将非标准方波整形成方波。
特点:
- 当输入电压高于正向阀值电压,输出为高;
- 当输入电压低于负向阀值电压,输出为低;
- 当输入电压在正负向阀值电压之间,输出不改变。
P-MOS&N-MOS管简介:
MOS管是压控型元件,通过控制栅源电压(Vgs)来实现导通或关闭。
三.GPIO的八种工作模式
1.输入
输入浮空:空闲时(高阻态:外部不接任何东西),IO状态不确定,由外部环境决定。
- 上拉电阻关闭;
- 下拉电阻关闭;
- 施密特触发器打开;
- 双MOS管不导通。
输入上拉:空闲时(高阻态),IO呈现高电平。
- 上拉电阻打开;
- 下拉电阻关闭;
- 施密特触发器关闭;
- 双MOS管不导通。
输入下拉:空闲时(高阻态),IO呈现低电平。
- 上拉电阻关闭;
- 下拉电阻打开;
- 施密特触发器关闭;
- 双MOS管不导通。
模拟功能:专门用于模拟信号输入或输出,如:ADC和DAC.
- 上拉电阻关闭;
- 下拉电阻关闭;
- 施密特触发器关闭;
- 双MOS管不导通。
2.输出(配置为输出模式,是可以读取引脚的高低电平的。)
开漏输出:不能输出高电平,必须有外部(或内部)上拉才能输出高电平,常用于软件IIC。
- 上拉电阻关闭;
- 下拉电阻关闭;
- 施密特触发器打开;
- P-MOS管不导通;
- 往ODR对应位写0,N-MOS管导通,写1则N-MOS管不导通;
开漏式复用:不能输出高电平,必须有外部(或内部)上拉才能输出高电平;由其他外设控制输出,常用于硬件IIC。
- 上拉电阻关闭;
- 下拉电阻关闭;
- 施密特触发器打开;
- P-MOS管不导通。
推挽输出:可输出高低电平,驱动能力强。
- 上拉电阻关闭;
- 下拉电阻关闭;
- 施密特触发器打开;
- 往ODR对应位写0,N-MOS管导通,写1则P-MOS管导通;
推挽式复用:可输出高低电平,驱动能力强;由其他外设控制输出,常用于SPI。
- 上拉电阻关闭;
- 下拉电阻关闭;
- 施密特触发器打开。
四.GPIO寄存器介绍
F1系列每个IO口由4个位来控制模式和速度。
五.通用外设驱动模型
<1>初始化
1.时钟设置
使能时钟:_HAL_RCC_GPIOx_CLK_ENABLE()
2.参数设置
设置工作模式:HAL_GPIO_Init()
3.IO设置
设置输出状态:HAL_GPIO_WritePin();HAL_GPIO_TogglePin();
读取输入状态:HAL_GPIO_ReadPin()
4.中断设置(开中断,设NVIC)
<2>读函数(可选)
从外设读取数据(可选)
<3>写函数(可选)
往外设写入数据(可选)
<4>中断服务函数(可选)
六.点亮一个LED灯
led.c
#include "led.h"
void LED_Init(void)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOC_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_13;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC,&gpio_init_struct);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
}
led.h
#ifndef _LED_
#define _LED_
#include "./SYSTEM/sys/sys.h"
void LED_Init(void);
#endif
main.c
int main(void)
{
HAL_Init();
sys_stm32_clock_init(RCC_PLLMUL_4);
delay_init(72);
LED_Init();
while(1)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);
delay_ms(500);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);
delay_ms(500);
}
}
七.按键控制LED
软件消抖:通过延时跳过抖动的时间段,再判断IO输入电平。
我使用的按键电气特性:按下高电平,释放低电平。
key.c
#include "key.h"
#include "./SYSTEM/delay/delay.h"
void KEY_Init(void)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOC_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_15;
gpio_init_struct.Mode = GPIO_MODE_INPUT;
gpio_init_struct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOC,&gpio_init_struct);
}
uint8_t key_scan(void)
{
if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_15) == 1)
{
delay_ms(10);
if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_15) == 1)
{
while(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_15) == 1);
return 1;
}
}
return 0;
}
key.h
#ifndef _KEY_
#define _KEY_
#include "./SYSTEM/sys/sys.h"
void KEY_Init(void);
uint8_t key_scan(void);
#endif
main.h
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "led.h"
#include "key.h"
int main(void)
{
HAL_Init();
sys_stm32_clock_init(RCC_PLLMUL_4);
delay_init(72);
LED_Init();
KEY_Init();
while(1)
{
if(key_scan())
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
}
else
{
delay_ms(10);
}
}
}