1. GPIO输入模式
上图为GPIO输入的基本示意图,其中包含了上拉电路,下拉电路,模拟信号处理,数字逻辑信号接收。
TTL(Transistor-Transistor Logic)施密特触发器是一种数字电路元件,常用于去除输入信号的噪声和抖动,并提供稳定的输出信号。它的作用在于消除输入信号的不稳定性,确保在输入信号发生变化时,输出信号能够产生可靠的、干净的转换。
TTL施密特触发器的主要作用有以下几个方面:
- 消除噪声和抖动:在数字电路中,输入信号可能受到噪声的干扰或产生抖动(快速的信号变化)。这可能导致触发器在边沿变化时产生不稳定的输出。TTL施密特触发器使用了一个双阈值比较器,只有当输入信号超过一定的阈值范围时,才会引发输出状态变化。这样可以防止在噪声或抖动情况下触发误动作。
- 提供干净的信号转换:TTL施密特触发器能够确保输入信号的干净转换,即使输入信号存在一些不稳定性或较慢的上升/下降时间。它的阈值范围内,输入信号的微小变化都不会引起输出变化,从而产生更加可靠的输出信号。
- 信号整形:TTL施密特触发器可用于整形输入信号的波形。如果输入信号具有不规则的上升和下降时间,触发器可以将其整形为规整的方波信号,以便后续电路处理。
- 边沿检测器:由于TTL施密特触发器对输入信号的变化非常敏感,它常被用作边沿检测器。当输入信号的上升沿或下降沿发生变化时,触发器可以产生输出脉冲,用于触发其他数字电路中的特定操作。
总之,我们简单的理解就是,输入的电压值被转化为了逻辑的0和1.
1.1 浮空输入
浮空输入,就是将模拟信号,上拉,下拉全部断开。只接收外部电路的输入信号。
这里会存在一个问题,如果外部没有输入信号,那么这个逻辑信号是未知的,不确定的。
1.2 上拉输入
上拉输入,就是将模拟信号,下拉全部断开,同时将上拉开关闭合。然后接收外部电路的输入信号。
此时如果外部引脚不接任何VCC或GND,等同于接了空气(电阻无限大),那么测试引脚得到的电压也就等同于VCC,即起到了VCC上拉到高电平的作用。
1.3 下拉输入
下拉输入,就是将模拟信号,上拉全部断开,同时将下拉开关闭合。然后接收外部电路的输入信号。
当输入信号未连接时,下拉电阻将确保输入信号保持在低电平状态,从而避免浮空输入。当外部信号连接到输入引脚时,外部信号可以通过下拉电阻的电流被拉高到高电平。
1.4 模拟输入
在真实的物理世界中,我们外部输入的是电压值,这个属于模拟信号。其他的几种输入就是把模拟信号变为逻辑的0和1。通常输入的电压在1v以下我们认为是逻辑的0,1v以上是逻辑的1。(不同的芯片处理信号方式不同,这里简单的举例为1v上下)。
模拟输入的是物理世界中的真实电压,模拟信号的处理不同与逻辑电路的转换,逻辑转换只有两种值。模拟信号则是线性的值,电压多大,就转换一个数字值,也就是将物理世界中的模拟数据转换为数字值,这个值是线性,有范围的。
2. ARM系列GPIO
2.1 寄存器
每个GPI/O端口有7个相关的:
- 2个32位配置寄存器(GPIOx_CRL,GPIOx_CRH)。
- 2个32位数据寄存器(GPIOx_IDR和GPIOx_ODR)。
- 1个32位置位/复位寄存器(GPIOx_BSRR)。
- 1个16位复位寄存器(GPIOx_BRR)。
- 1个32位锁定寄存器(GPIOx_LCKR)。
简单来说:
- 配置寄存器:配置输入输出,上拉下拉
- 数据寄存器:读取输入输出的状态
- 复位寄存器:输出高低电平
- 复用寄存器:配置复用功能
2.2 保护二极管
在线与,或者电压过大的情况下,将电压进行钳制,防止芯片烧毁。(当然这个是有限度的,得参考芯片手册内部的二极管特性)。
2.3 GPIO的8种工作模式
GPIO端口的每个位(引脚)可以由软件分别配置成8种模式,当然对同一个引脚同一时间只能处于某一种模式中
模式 | 性质 |
浮空输入 | 数字输入 |
上拉输入 | 数字输入 |
下拉输入 | 数字输入 |
模拟输入 | 模拟输入 |
开漏输出 | 数字输出 |
推挽输出 | 数字输出 |
复用开漏输出 | 数字输出 |
复用推挽输出 | 数字输出 |
3. GD32/STM32系列GPIO工作模式
3.1 浮空输入
// 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 配置GPIO模式
gpio_mode_set(GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN_x);
3.2 上拉输入
// 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 配置GPIO模式
gpio_mode_set(GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_x);
3.3 下拉输入
// 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 配置GPIO模式
gpio_mode_set(GPIOx, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_x);
3.4 模拟输入
// 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 配置GPIO模式
gpio_mode_set(GPIOx, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_x);
3.5 推挽输出
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_x);
// 3. 配置GPIO 模式的操作方式
gpio_output_options_set(GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_x);
3.6 开漏输出
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_x);
// 3. 配置GPIO 模式的操作方式
gpio_output_options_set(GPIOx, GPIO_OTYPE_OD, GPIO_OSPEED_MAX, GPIO_PIN_x);
3.7 复用推挽输出
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_x);
// 3. 配置GPIO 模式的操作方式
gpio_output_options_set(GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, GPIO_PIN_x);
// 4. 复用功能
gpio_af_set(GPIOx, GPIO_AF_x, GPIO_PIN_x);
3.8 复用开漏输出
// 1. 时钟初始化
rcu_periph_clock_enable(RCU_GPIOx);
// 2. 配置GPIO 输入输出模式
gpio_mode_set(GPIOx, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_x);
// 3. 配置GPIO 模式的操作方式
gpio_output_options_set(GPIOx, GPIO_OTYPE_OD, GPIO_OSPEED_MAX, GPIO_PIN_x);
// 4. 复用功能
gpio_af_set(GPIOx, GPIO_AF_x, GPIO_PIN_x);
通常开漏时,需要外部上拉,当然内部电路也可以控制上拉。