基础知识
了解GPIO基础知识更有益于我们使用它。
框图
GPIO(通用输入输出)是指一种通用的数字输入/输出接口,用于与外部电子元件或设备进行通信。它通常存在于微处理器、微控制器和其他嵌入式系统中。
物理电路结构如下图所示:
I/O pin: 微控制器或微处理器中的实际硬件接口,用于连接外部设备。每一个GPIO引脚都可以被编程为输入或输出模式 。
保护二极管(protection diode): 特殊类型二极管,用于保护微控制器或微处理器的输入/输出引脚不受电压反冲或静电放电的影响 。
上拉下拉电阻: 用于设定GPIO引脚在空闲或无输入信号时的状态 。 上拉电阻将GPIO引脚连接到正电源,从而将其设定为默认高电平状态;下拉电阻将GPIO引脚连接到地线,从而将其设定为默认低电平状态。 由软件配置寄存器控制。
P-MOS管和N-MOS管:由P-MOS管和N-MOS管组成的单元电路使得GPIO具有“推挽输出”和“开漏输出”的模式。
TTL施密特触发器: 用于处理噪声或不稳定的输入信号。它通过设定两个不同的阈值(上阈值和下阈值)来消除数字信号的噪声,从而提供更准确的数字信号 。
输出驱动器: 控制GPIO引脚在输出模式下的电压和电流。
输入接收器: 处理来自GPIO引脚的输入信号。在许多情况下,它可能包括一个施密特触发器,用于消除数字信号的噪声。
工作模式
浮空输入
也称为 Hi-Z 或高阻抗状态。 这意味着 GPIO 引脚不会被拉至任何逻辑电平,而是悬空。 在这种状态下,GPIO 引脚很容易拾取电噪声并可能读取随机值,因此通常会避免使用它,除非有特定原因使用它。
黄色的高亮部分显示了数据传输通道,外部的电平信号通过左边编号①的I/O 端口进入芯片内部经过编号②的施密特触发器整形以后送入编号③的“输入数据寄存器”在“输入数据寄存器”的另一端(编号④) ,CPU通过内部的数据总线可以随时读出I/O 端口的电平变化的状态
上拉输入
GPIO 引脚和电源电压 (VDD) 之间连接有上拉电阻。 因此,当 GPIO 引脚未被设备主动驱动时,它会被“上拉”至逻辑高电平。 当需要 GPIO 引脚的默认状态为高电平时,需配置为上拉模式。
与前面介绍的浮空输入模式相比,仅仅是在数据通道上面,接入了一个上拉电阻,这个上拉电阻阻值一般介于30K~50KΩ。在I/O口无信号输入的情况下,输入端的电平可以保持在高电平(VDD经过上拉电阻);并且在I/O端口输入为低电平的时候,输入端的电平就是低电平(可以理解为电阻分压)。
下拉输入
GPIO 引脚与地 (VSS) 之间连接有下拉电阻。 当 GPIO 引脚未被设备主动驱动时,这会将其拉至逻辑低电平。 当需要GPIO 引脚的默认状态为低电平时,需配置为下拉模式。
对于输入下拉模式的输入,是在数据通道的下部,接入了一个下拉电阻。这个下拉电阻阻值一般介于30K~50KΩ。
模拟输入
无上下拉电阻,电信号不经过施密特触发器,直接进入模拟输入通道,一般用于ADC数据采集。
开漏输出
在开漏(Open-Drain)输出模式下,GPIO引脚只能主动将电压拉低(通过连接到地线),不能主动将电压拉高。要实现电压的拉高,需要配合一个外部的上拉电阻连接到电源。 开漏输出的一个常见应用是I²C通信,其中多个设备可以共享同一条数据线。
当CPU 在编号① 端通过“位设置/ 清除寄存器”或“输出数据寄存器”写入数据后,该数据位将通过编号②的输出控制电路传送到编号④ 的I/O端口。如果CPU 写入的是逻辑“1 ”,则编号③ 的N-MOS管将处于关闭状态,此时I/O 端口的电平将由外部的上拉电阻决定。如果CPU 写入的是逻辑“0 ”,则编号③的N-MOS管将处于开启状态,此时I/O端口的电平被编号③ 的N-MOS管拉到了“地”的零电位。
在图中的上半部,施密特触发器处于开启状态,这意味着CPU 可以在“输入数据寄存器”的另一端,随时可以监控I/O端口的状态,通过这个特性,还可以实现了虚拟的I/O端口双向通信:假如CPU 输出逻辑“1 ”,由于编号③ 的N-MOS管处于关闭状态,I/O 端口的电平将完全由外部电路决定。因此,CPU 可以在“输入数据寄存器”读到外部电路的信号,而不是它自己输出的逻辑“1 。
推挽输出
在推挽(Push-Pull)输出模式下,GPIO引脚可以主动驱动高电平或低电平。这意味着GPIO可以"推"电压到高电平,也可以"拉"电压到低电平。推挽输出可以提供较强的驱动能力,适合驱动LED、电机等负载。
推挽输出的最大特点是可以真正能真正的输出高电平和低电平,在两种电平下都具有驱动能力。
中断框图
中断屏蔽寄存器(Interrupt Mask Register):此寄存器用于屏蔽或禁用特定的中断,使其不会触发中断服务例程。当某个位设置为1时,对应的中断将被屏蔽。
请求挂起寄存器(Interrupt Pending Register):此寄存器用于存储当前挂起的中断请求。如果对应位为1,则表明相应的中断是挂起状态。
软件中断事件寄存器(Software Interrupt Event Register):此寄存器允许软件生成中断。通过写入此寄存器,可以触发与特定中断源相关联的中断服务例程。
上升沿触发选择寄存器(Rising Edge Trigger Selection Register):此寄存器选择在信号的上升沿时触发中断。
下降沿触发选择寄存器(Falling Edge Trigger Selection Register):此寄存器选择在信号的下降沿时触发中断。
边沿检测电路(Edge Detection Circuit):这是硬件电路,用于检测信号边沿的变化(上升沿或下降沿),从而触发中断。
时间屏蔽寄存器(Timing Mask Register):此寄存器用于屏蔽在特定时间内发生的中断,通常用于消除误触发的中断。
脉冲发生器(Pulse Generator):在硬件中,脉冲发生器可以生成一系列的脉冲,用于触发定时或同步的事件,包括中断。
NVIC(Nested Vectored Interrupt Controller):是ARM Cortex-M核心的一部分,用于管理中断。它支持优先级嵌套的中断,以及中断向量,即指向中断服务例程的指针。
功能复用
嵌入式系统中,包括许多微控制器和处理器中,一些特定的物理引脚可以配置成不同的功能,这就是所谓的引脚复用(Pin Multiplexing)。理解引脚复用的关键是理解一些引脚可以在不同的硬件模块间切换,这样可以在硬件设计时提供更大的灵活性。引脚复用的目的主要是节省空间和成本,因为这样可以减少物理引脚的数量。
一个嵌入式芯片的物理引脚可能被设计为在以下几种功能之间切换:
- 作为 GPIO,进行通用的数字输入/输出;
- 作为 SPI 接口的一部分,用于与其他 SPI 设备通信;
- 作为 UART 接口的一部分,用于串行通信;
- 或者,它可能有一些其他特定的功能,如 ADC 输入,PWM 输出等。
在设计嵌入式系统时,你可以根据你的硬件和软件需求配置这些引脚。一些嵌入式平台还允许你在运行时动态切换这些引脚的功能,这为嵌入式系统设计提供了极大的灵活性。
当然,引脚复用也有其局限性。例如,一个引脚不能同时执行两种或更多的功能,因此在设计系统时需要考虑到这一点。引脚复用的管理也可能增加系统的复杂性,并可能需要更多的软件支持来正确配置和使用这些引脚。
消抖
按键消抖是在电子系统中处理机械按键输入时的常见问题。由于机械按键的接触特性,当按键被按下或释放时,接触点可能会快速打开和关闭多次,导致短时间内的多次电平变化。这被称为“抖动”。如果不处理抖动,系统可能会误认为按键被多次按下或释放。因此,需要采取措施消除或至少减少这种抖动的影响。
消抖的方法主要分为两类:硬件消抖和软件消抖。
硬件消抖
硬件消抖的主要目标是处理机械按键产生的抖动,从而使电路得到一个稳定、无干扰的电平信号。以下是几种常用的硬件消抖方法:
RC滤波器
构成:
- 电阻(R): 连接于按键的一端。
- 电容(C): 从按键的另一端连接到地线。
特性:
- 低通滤波器: 由于其构造,RC滤波器允许低频信号通过而过滤高频信号。
工作原理:
- 当按键被按下或释放,电容C会开始充电或放电。因此,对于快速的电压变化(如由于接触抖动导致的),RC滤波器会平滑这些变化,从而防止误判。
- 这种平滑效果的强度由RC时间常数(τ = R×C)决定。此时间常数表示电容充电到其初始电压的63.2%所需的时间。
优点:
- 简单性: 仅需要两个基本组件。
- 经济性: 电阻和电容都是低成本元件。
- 有效性: 对于大多数常规应用,其消抖能力足够。
缺点:
- 延迟: 过大的RC时间常数可能导致按键响应的不必要延迟。
- 环境敏感性: 温度和湿度的变化可能影响电容的值,进而影响消抖效果。
- 不适用于所有应用: 对于需要快速响应的应用,RC滤波器可能不是最佳选择。
在使用RC滤波器作为按键硬件消抖策略时,关键在于选择合适的R和C值,使得滤波器能够有效地过滤掉抖动,同时不会引入过多的响应延迟。在设计阶段,可能需要进行实验,测试不同的R和C组合,以找到最佳的消抖效果。
Schmitt触发器:
构成:
- Schmitt触发器 本质上是一个带有双阈值的电压比较器。它可以是独立的组件,也可以是微控制器内部的一部分。
特性:
- 双阈值: Schmitt触发器的主要特性是其具有两个阈值 — 上阈值(Vt+)和下阈值(Vt-)。
工作原理:
- 当输入电压上升并超过上阈值(Vt+)时,输出切换到高状态。
- 当输入电压下降并低于下阈值(Vt-)时,输出切换到低状态。
- 这种特性可以确保在输入电压发生微小变化(如因抖动)时,输出状态不会改变,从而有效地过滤抖动。
常用参数:
- 上阈值(Vt+) 和 下阈值(Vt-): 这两个阈值之间的差距称为滞后或死区。
优点:
- 消抖效果好: 由于双阈值特性,Schmitt触发器对输入噪声和抖动具有很强的容忍性。
- 明确的输出: 输出始终是一个明确的高或低电平,不会在两者之间浮动。
- 广泛可用: 很多微控制器的GPIO输入都内置了可选的Schmitt触发器。
缺点:
- 可能的延迟: 在某些情况下,如果输入信号的变化速度较慢,触发器可能导致轻微的延迟。
- 不适合快速信号: 对于频率较高的信号,Schmitt触发器可能不是最佳选择,因为它可能会导致信号失真。
- 成本: 虽然许多微控制器都内置了Schmitt触发器,但如果需要外部触发器,则可能会增加成本。
注意点:
- 选择的消抖方法和组件值应考虑按键的抖动频率和持续时间。
- 如果使用RC滤波器,需要确保RC时间常数既可以消除抖动,又不会过度延迟按键响应。
- 当在噪音环境中工作时,可能需要考虑其他因素,如外部电磁干扰。
- 测试是关键:在设计完成后,应该对系统进行足够的测试,以确保消抖电路在所有预期条件下都能正常工作。
RS触发器
构成:
- RS触发器 通常是由两个NAND门或NOR门构成的基础双稳态电路。
- 有两个输入: R (Reset) 和 S (Set)。
- 有两个输出: Q 和 ~Q (Q的反相)。
特性:
- 双稳态: RS触发器在任何时候都有两个稳定的输出状态。
工作原理:
- 当 S 输入为1且 R 输入为0时,Q 输出为1,而 ~Q 输出为0。
- 当 R 输入为1且 S 输入为0时,Q 输出为0,而 ~Q 输出为1。
- 当两个输入都为0时,RS触发器保持在当前状态。
- 当两个输入都为1时,是不被允许的状态,并可能导致不确定的输出。
为了消除按键抖动,RS触发器可以配置为只有在按键真正按下或释放时才改变其状态。与按键相关的任何短暂抖动都不会导致RS触发器的输出发生更改,从而有效地消除了抖动。
常用参数:
- 输入逻辑级别: 对于NAND版本的RS触发器,正常逻辑级别为1,对于NOR版本的RS触发器,正常逻辑级别为0。
优点:
- 高效消抖: RS触发器为按键提供了稳定的输出,无论输入多么嘈杂。
- 明确的输出状态: 在任何给定时间,都有一个明确的高或低输出。
- 低成本: RS触发器可以使用基础的逻辑门构建。
缺点:
- 复杂性: 相对于简单的电容并联或Schmitt触发器方法,这需要更多的组件和更复杂的布线。
- 不允许的状态: RS触发器有一个不允许的输入状态,需要小心设计以避免。
- 电源需求: 需要为触发器提供适当的电源。
软件消抖
软件消抖是通过在软件层面使用算法和逻辑来消除按键抖动。与硬件消抖方法相比,软件消抖方法对于不同的应用和条件提供了更多的灵活性,但它也增加了一些处理负担。
以下是一些常见的嵌入式软件消抖技术:
延时
工作原理:
当检测到按键的状态改变(例如从未按下变为按下状态),而不是立即响应这一改变,程序会等待一个预定的延迟时间。在这段延迟时间结束后,程序再次检测按键的状态。如果按键状态保持不变,那么这个按键动作被认为是有效的,程序则会响应这一按键动作;否则,它会认为是误报或抖动,所以不会产生响应。
优点:
- 简单实现:延时消抖是最简单和直接的软件消抖技术。只需在按键状态改变后添加一个延迟函数,然后再次检测状态。
- 不需要额外资源:与其他方法相比,如使用计数器或有限状态机,延时消抖不需要额外的存储或计数资源。
缺点:
- 响应延迟:由于需要等待预定的延迟时间来确认按键动作,这会导致用户感知的响应延迟。
- CPU时间浪费:如果使用的是忙等待(busy-waiting)来实现延迟,那么CPU将在这段时间里无法进行其他任务,这在资源受限的嵌入式系统中是不可接受的。
- 不够可靠:如果抖动的时间超过了预定的延迟时间,这种方法可能仍然会误报。另外,如果设置的延迟时间太长,可能会错过快速的连续按键动作。
计数器
工作原理:
当检测到按键状态改变时,系统并不立刻确认这一改变。相反,它启动一个计数器。在连续的几次检测中,如果按键状态持续保持改变状态,计数器就增加;如果按键返回到原始状态,计数器则重置。只有当计数器值达到一个预设的阈值时,按键状态的改变才被认为是真正的按键动作,并由系统响应。这样,短暂的抖动不会让计数器达到阈值,因此不会被误判为有效的按键动作。
优点:
- 可靠性高:与简单的延时消抖相比,计数器消抖能够更可靠地滤除短时间的抖动。
- 响应性好:如果按键确实被持续按下,系统可以在较短的时间内确认按键动作,从而提供较好的响应性。
- 灵活性:可以根据需要调整计数器的阈值,以适应不同的按键和抖动特性。
缺点:
- 资源消耗:需要为每个按键使用一个计数器或为系统使用一个全局计数器。这可能会消耗额外的存储资源和计时资源。
- 复杂性增加:相较于简单的延时消抖,计数器消抖在实现上稍微复杂一些,特别是在有多个按键需要处理的场合。
- 可能的延迟:如果设定的计数器阈值过高,可能导致系统响应的延迟,降低用户体验。