一、GPIO
1.1 基本概念
GPIO(General-purpose input/output)通用输入输出接口
--GP 通用
--I input输入
--o output输出
通用输入输出接口GPIO是嵌入式系统、单片机开发过程中最常用的接口,用户可以通过编程灵活的对接口进行控制,实现对电路板上LED、数码管、按键等常用设备控制驱动,也可以作为串口的数据收发管脚,或AD的接口等复用功能使用。其作用和功能是非常重要的。
1.2实际应用
input 输入-数据采集 按键、光照(光敏传感器)、ADC、各种传感器
output 输出 - 设备控制 LED灯、数码管、继电器(小控大)

二、功能描述
1、IO结构框图

保护二极管:(1)电压过大,有保护作用;(2)反向电动势。
上拉电阻:上拉电阻是一种用于数字电路中的电阻元件,它的作用是将信号线拉高到高电平(逻辑1)状态。当信号线不被其他元件拉低时,上拉电阻会将信号线连接到正电源,使其保持在高电平状态。
施密特触发器:电压比较器 例如 0 <= 0.7 1>=1.7
写------>置位/复位寄存器 :只能写1(0到15是置位,16到31是复位)
输出控制:使用反相器
问:VDD、VSS、VCC分别表示什么意思?
VCC :接入电路的电压
VDD : 元器件内部的工作电压
VSS : 公共接地端电压
问:施密特触发器的作用?
由于外部输入的信号,可能会出现脉冲等噪声的影响,为了让信号更加清晰,所以就设置了TTL施密特触发器来进行整形。
问:模拟信号和数字信号的区别?
1、时间连续性不同:
1)模拟信号时间上是连续的;
2)数字信号时间上不是连续的。
2、幅度变化不同:
1)模拟信号指幅度的取值是连续的(幅值可由无限个数值表示)。
2)数字信号指幅度的取值是离散的,幅值表示被限制在有限个数值之内。
3、信号传输方式不同:
1)模拟信号是用模拟量的电压或电流来表示的电信号;
2)数字信号是通过0和1的数字串所构成的数字流来传输的。
4、保密性不同:
1)模拟信号的微波通信和有线明线通信,很容易被窃听。只要收到模拟信号,就容易得到通信内容。
2)数字信号保密性较强,语音信号可以先进行加密处理,再进行传输,在接收端解密后再变换还原成模拟信号。
- 功能详述
浮空输入
IO端口 - 施密特触发器 - 输入数据寄存器 - 读

通俗讲就是让管脚什么都不接,悬空着。
此时VDD和VSS所在路径的两个开关同时断开。因为没有上拉和下拉,所以当IO口没有接输入的时候,此时的电平状态会是一个不确定的值,完全由外部输入决定。
由于浮空输入一般多用于外部按键输入,结合图上的输入部分电路,浮空输入状态下,IO的电平状态是不确定的,完全由外部输入决定,如果在该引脚悬空的情况下,读取该端口的电平是不确定的,易受干扰。
优势:
这一种输入模式的电平会完全取决于外部电路而与内部电路无关。
缺点:
在没有外部电路接入的时候,IO脚浮空会使得电平不确定
应用:
该模式是STM32复位之后的默认模式,一般用作对开关按键的读取或用于标准的通讯协议,比如IIC、USART的等。
上拉输入
IO端口 - 上拉电阻 - 施密特触发器 - 输入数据寄存器 - 读

输入的电平不会因上下浮动而导致输入信号不稳定,当外部没有信号输入时,上拉电阻会将输入信号钳在高电平,此时引脚始终读到高电平信号。
下拉输入
IO端口 - 下拉电阻 - 施密特触发器 - 输入数据寄存器 - 读

输入的电平不会因上下浮动而导致输入信号不稳定,当外部没有信号输入时,下拉电阻会将输入信号钳在低电平,此时引脚始终读到低电平信号。
模拟输入
IO端口 - 片上外设模块(电压信号)

信号进入后不经过上拉电阻或者下拉电阻,关闭施密特触发器,经由另一线路把电压信号传送到片上外设模块。 所以可以理解为模拟输入的信号是未经处理的信号,是原汁原味的信号。
应用: 当 GPIO 引脚用于 ADC 采集电压的输入通道时,则需要选择"模拟输入"功能,因为经过施密特触发器后信号只有 0、1 两种状态,所以 ADC 外设要采集到原始的模拟信号,信号源输入必须在施密特触发器之前。
开漏输出

推挽 开漏 高阻 这都是谁想出来的词??_哔哩哔哩_bilibili


开漏输出:PMOS不使用
输出寄存器上的的'0'激活 N-MOS,输出寄存器上的'1'将端口置于高阻状态 (P-MOS 从不被激活 )。
无法真正输出高电平,即高电平时没有驱动能力,需要借助外部上拉电阻完成对外驱动。
可以利用改变上拉电源的电压来适应所需,进而提高外部电路的驱动能力。
MOS管的漏极等于啥也没接,处于一个开路状态,所以这个模式称之为开漏模式。
优势1:
虽然我们可以看到开漏输出是没有办法在内部输出一个高电平,但是这一个看似是缺点。其实实际上是一种优点。当给一个低电平的时候,MOS管没有导通,此时电压不确定导致无法输出高电平,但是一旦我们在外部增加一个上拉,那么这一个缺点就会被有效避免。并且,因为是我们自己设计一个上拉,这个上拉的电压是由我们自己确定,这样我们就可以根据外部电路需要多少V的高电平来给这一个上拉的电压,可以更好的适应更多情况。如下图,我们可以给定任意的VDD电压,来适应我们实际所需要的情况。

优势2:
开漏输出的实质其实就是一个OD门(OD:漏极输出(Open Drain))。而在数电中,OD门有一个非常重要的特性就是可以实现线与的功能,简单来说,就是在像IIC这样的总线协议中,只要有一个给低电平,那么总线都会被拉低。
推挽输出


输出数据寄存器'0'------>输出控制'1'------>NMOS激活
输出数据寄存器'1'------>输出控制'0'------>PMOS激活
输出寄存器上的'0'激活N-MOS,而输出寄存器上的'1'将激活P-MOS。
具备输出高低电平的能力。
推挽输出就是可以需要利用两个不同的MOS管来实现输出。
推挽输出模式下(P-MOS管+N-MOS管),通过设置位设置/清除寄存器或者输出数据寄存器的值,途经P-MOS管和N-MOS管,最终输出到I/O端口。
开漏和推挽的区别

三、GPIO相关寄存器
4 个 32 位 配 置 寄 存 器
GPIOx_MODER 模式寄存器
GPIOx_OTYPER 输出模式寄存器
GPIOx_ OSPEEDR 输出速度寄存器
GPIOx_PUPDR 上拉下拉寄存器
2 个 32 位数据寄存器
GPIOx_IDR 输入数据寄存器
GPIOx_ODR 输出数据寄存器
1个 32 位置位 / 复位寄存器
GPIOx_BSRR 置位 / 复位寄存器
2 个 32 位复用功能寄存器
GPIOx_AFRH
GPIOx_AFRL
四、寄存器详细讲解
(英文参考手册151页)
使能时钟寄存器(RCC_IOPENR)

偏移地址:偏移地址就是计算机里的内存分段后,在段内某一地址相对于段首地址(段地址)的偏移量。
如8086存储系统中 20位的物理地址(就是数据存储的实际地址)=16位的段基地址*16+16位的偏移量 (0X34)
以下是STM32F051的 (101页)

GPIO端口模式寄存器(GPIOx_MODER)(x=A...D,F)
偏移地址:0x00
复位值:
0xEBFF FFFF 端口A
0xFFFF FFFF 其他口

GPIO 端口输出类型寄存器 (GPIOx_OTYPER) (x = A..D,F)
偏移地址:0x04
复位值: 0x0000 0000

GPIO 口输出速度寄存器 (GPIOx_OSPEEDR) (x = A..D,F)
偏移地址:0x08
复位值: 0x0000 0000

GPIO 口上拉 / 下拉寄存器 (GPIOx_PUPDR) (x = A..D,F)
偏移地址:0x0C
复位值:
0x2400 0000 端口 A
0x0000 0000 其它端口

GPIO 端口输入数据寄存器 (GPIOx_IDR) (x = A..D,F)
偏移地址:0x10
复位值: 0x0000 XXXX (X 表明不定 )

GPIO 端口输出数据寄存器 (GPIOx_ODR) (x = A..D,F)
偏移地址:0x14
复位值: 0x0000 0000

GPIO 端口置位 / 复位寄存器 (GPIOx_BSRR) (x = A..D,F)
偏移地址:0x18
复位值:0x0000 0000

端口位复位寄存器(GPIOx_BRR) (x=A..G)
偏移地址:0x28
复位值: 0x0000 0000

五、点亮一盏LED灯
1 实验步骤
1.查看开发板实物,找到LED灯

2.查看底板原理图

要让LED2亮,则为低电平



只要将PB2配置为低电平,灯就点亮
2 编程实现
寄存器分析

RCC->IOPENR |= 1<<1;

配置PB2为输出模式
GPIOB->MODER &= ~(0X3<<4); //先清零
GPIOB->MODER |= 1<<4; //后置位

选择推挽输出模式
GPIOB->OTYPER &= ~(1<<2);

GPIOB->ODR &= ~(1<<2);
MX配置



代码编写
` `//使能GPIO端口的时钟`
` RCC->IOPENR |=` `1<<1;`
`//配置GPIO为输出模式`
` GPIOB->MODER &=` `~(0X3<<4);` `//先清零`
` GPIOB->MODER |=` `1<<4;` `//后置位`
`//选择推挽输出模式`
` GPIOB->OTYPER &=` `~(1<<2);`
`//控制引脚输出低电平`
` GPIOB->ODR &=` `~(1<<2);`
`
版本2:使用STM32CubeMX工具




六、HAL库函数分析
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
功能: 设置或清除指定的端口位
参数:GPIO_TypeDef *GPIOx 端口号
uint16_t GPIO_Pin 引脚号
GPIO_PinState PinState 电平状态
GPIO_PIN_SET 1
GPIO_PIN_RESET 0
返回值:无
void HAL_GPIO_TogglePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
功能: 切换指定的引脚电平状态
参数:GPIO_TypeDef * GPIOx 端口号
uint16_t GPIO_Pin 引脚号
返回值:无
GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin)
功能: 读取指定的引脚电平状态
参数:GPIO_TypeDef * GPIOx 端口号
uint16_t GPIO_Pin 引脚号
返回值:GPIO_PinState 电平状态
GPIO_PIN_RESET 0
GPIO_PIN_SET 1
利用HAL库函数实现LED灯闪烁

练习:实现流水灯效果
方法一:

方法二:

- 实验:按键控制LED灯亮灭(输入)
- .查看实物找到按键和控制的LED灯
五向按键 - S1
- 查看原理图






MX配置

所有的机械元件都有抖动问题
关于消抖问题
写法一:延时消抖

写法二:抬手检测
