这个巧妙的设计利用了数字电路的特性实现两个按键(干簧管)的状态检测,只用到了2个GPIO口。理解它的关键在于状态编码和或非门的逻辑特性。
我分析一下图中的原理和对比传统方法的优势:
? 电路原理分析 (两个IO + 两个或非门)
IO口配置:
- GPIO1 和 GPIO2 通常被配置为 输入模式 (Input)。
- 在初始化时,微控制器可能会将它们暂时设为输出低电平 (Output Low) 或者确保或非门输入有确定状态(尤其是刚上电时)。
或非门 (NOR Gate) 原理:
- 或非门的输出是:
输出 = NOT (输入A OR 输入B)
- 简单来说:只要任意一个输入是高电平,输出就是低电平。只有当所有输入都是低电平时,输出才是高电平。
干簧管状态与电路状态对应关系:
假设干簧管闭合为"导通" (ON),断开为"断开" (OFF)。我们来看每个开关状态组合下,GPIO1 和 GPIO2 读到的电平。
干簧管1状态 |
干簧管2状态 |
U1A输出 |
U1B输出 |
U1A输入B / GPIO1 (读入值) |
U1B输入B / GPIO2 (读入值) |
检测到的状态编码 |
|---|
OFF (断开) |
OFF (断开) |
高 (接VCC) |
高 (接VCC) |
高 (上拉输入) |
高 (上拉输入) |
11 (SW1 OFF, SW2 OFF) |
ON (闭合) |
OFF (断开) |
低 (接地) |
高 (接VCC) |
低 (来自U1A输出) |
高 (上拉输入) |
01 (SW1 ON, SW2 OFF) |
OFF (断开) |
ON (闭合) |
高 (接VCC) |
低 (接地) |
高 (上拉输入) |
低 (来自U1B输出) |
10 (SW1 OFF, SW2 ON) |
ON (闭合) |
ON (闭合) |
低 (接地) |
低 (接地) |
低 (来自U1A输出) |
低 (来自U1B输出) |
00 (SW1 ON, SW2 ON) |
- 当一个开关断开 (OFF) 时: 它连接的或非门输入悬空(相当于输入低电平?)。但关键点在于:只要一个开关是断开的,它所连接的或非门输入就失去了有效驱动。这时,该或非门的状态由其另一个输入(另一个或非门的输出)决定。
- 当一个开关闭合 (ON) 时: 它会将其连接的或非门的一个输入直接拉低 (接地)。
- 或非门输出的逻辑: 从表中可以看出,每个或非门的输出状态不仅取决于它连接的开关,还间接受另一个开关和另一个或非门输出的影响。这导致了每个开关状态组合在GPIO1和GPIO2上产生了唯一的二进制编码:
11, 01, 10, 00。软件只需要读取这两个GPIO的状态,就可以唯一确定两个干簧管是都断开了,还是S1闭合S2断开,还是S1断开S2闭合,还是都闭合。
? 为什么不用每个干簧管直接对GND检测?
直接对GND检测是传统的按键检测方法(一个IO + 一个上拉电阻 + 按键到GND):
- 单个干簧管: 需要1个GPIO + 1个上拉电阻。
- 两个干簧管: 需要 2个GPIO + 2个上拉电阻 + 2根独立的地线(或者共用GND)。
- 可能的"状态模糊"问题: 如果微控制器的IO口内部上拉不够强,或者受到噪声干扰,在开关断开时读到的电平可能不确定(是内部上拉的高电平?还是外部干扰?)。但在设计良好时,这个问题通常不严重。
✅ 为什么图中方案更优?
**显著节省GPIO资源!**
- 直接检测2个开关需要 2个GPIO。
- 本方案检测2个开关也只需要 2个GPIO。看起来一样?不对!
- 关键优势在于扩展性: 这个设计的精髓在于状态编码。它用2个GPIO 唯一检测了2^2=4种状态(两个开关的组合)。如果微控制器有N个IO口使用这种交叉或非门编码电路,理论上最多可以检测 2^N - 1 个按键(因为状态
11...1通常是所有按键断开的默认状态,需要用到所有IO口)。直接检测N个按键需要N个IO口。在按键较多时,本方案的效率优势(节省IO口)就非常明显了。虽然在2个按键时只节省了布线,但在资源受限的STM8L上,即使省一个IO也可能意义重大。
硬件消抖与状态锁定:
- 或非门是由晶体管构成的门电路,具有一定的输入/输出转换延迟和驱动能力。这种特性一定程度上(虽然不强)能抑制开关触点抖动导致的快速电平变化,使得输入到GPIO的信号毛刺更少、更稳定。在临界状态(如开关断开瞬间),门电路的固有延迟和逻辑阈值能提供微弱的"滤噪"效果。而GPIO内部的上拉电阻可能对这个作用不大。
消除状态模糊/悬浮:
- 在"双断开"状态 (
11),虽然两个输入都悬空,但或非门输出高电平通过电阻上拉至VCC,为GPIO提供了确定的高电平驱动(比纯靠内部弱上拉要强)。在"单闭合"状态,闭合开关的低电平路径提供了强驱动(接地),断开侧的GPIO由另一个或非门的有源输出驱动(高电平)。在"双闭合"状态,接地提供了最强驱动。这意味着在任何有效状态下,两个GPIO的输入电平都不是靠内部弱上拉维持的悬空高阻状态,而是由低阻路径(VCC或GND或门电路输出)明确驱动,大大增强了抗干扰能力,避免了悬空时易受噪声影响导致误判的问题。这是我认为最大的优势。
简化PCB布线:
- 虽然图中看起来有点复杂,但在实际布线中,两个或非门(通常是单个7402/4001等芯片)可能集成在一个很小的封装里(如SOIC-14、甚至更小的封装)。最关键的是,只需要将干簧管的地线连接到一起(不需要两条独立接地线到微控制器),然后引到公共地。相比直接接地法简化了连线(尤其当物理位置分离时)。电路公共节点更少。
? 总结
这个设计的核心是利用或非门交叉连接构成的简单编码网络:
- 目标: 用最少的GPIO口检测多个按键状态。
- 核心原理: 每个开关的组合状态在2个GPIO上产生唯一的二进制编码 (
00, 01, 10, 11)。软件只需读取一次这两个IO的状态,就能直接判断出哪个/哪些开关按下了。
- 主要优势 (相比直接接地检测):
- 更省GPIO (在多按键时): N个IO理论上能检测最多 (2^N - 1) 个按键。
- 更高的抗干扰能力: GPIO在每种有效状态下都由低阻路径(VCC、GND或门电路输出)强驱动,消除悬空输入问题,不易受噪声干扰。
- 潜在的硬件消抖作用: 门电路的延迟特性有助于减弱开关抖动。
- 可能的布线简化: 开关地线可集中接到一处公共地。
- 代价: 需要增加两个或非门(一个小芯片),比纯GPIO方案增加了一点硬件成本。
这个设计在GPIO资源受限、抗干扰性要求高或需要按键扩展的场合是非常巧妙的选择。? 对于干簧管这种开关元件,它稳定可靠的特性也特别适合这类逻辑检测电路。如果你在设计资源紧张或对可靠性要求高的产品,这种编码方法非常值得参考。
这个巧妙的设计利用了数字电路的特性实现两个按键(干簧管)的状态检测,只用到了2个GPIO口。理解它的关键在于状态编码和或非门的逻辑特性。
我分析一下图中的原理和对比传统方法的优势:
? 电路原理分析 (两个IO + 两个或非门)
IO口配置:
- GPIO1 和 GPIO2 通常被配置为 输入模式 (Input)。
- 在初始化时,微控制器可能会将它们暂时设为输出低电平 (Output Low) 或者确保或非门输入有确定状态(尤其是刚上电时)。
或非门 (NOR Gate) 原理:
- 或非门的输出是:
输出 = NOT (输入A OR 输入B)
- 简单来说:只要任意一个输入是高电平,输出就是低电平。只有当所有输入都是低电平时,输出才是高电平。
干簧管状态与电路状态对应关系:
假设干簧管闭合为"导通" (ON),断开为"断开" (OFF)。我们来看每个开关状态组合下,GPIO1 和 GPIO2 读到的电平。
干簧管1状态 |
干簧管2状态 |
U1A输出 |
U1B输出 |
U1A输入B / GPIO1 (读入值) |
U1B输入B / GPIO2 (读入值) |
检测到的状态编码 |
|---|
OFF (断开) |
OFF (断开) |
高 (接VCC) |
高 (接VCC) |
高 (上拉输入) |
高 (上拉输入) |
11 (SW1 OFF, SW2 OFF) |
ON (闭合) |
OFF (断开) |
低 (接地) |
高 (接VCC) |
低 (来自U1A输出) |
高 (上拉输入) |
01 (SW1 ON, SW2 OFF) |
OFF (断开) |
ON (闭合) |
高 (接VCC) |
低 (接地) |
高 (上拉输入) |
低 (来自U1B输出) |
10 (SW1 OFF, SW2 ON) |
ON (闭合) |
ON (闭合) |
低 (接地) |
低 (接地) |
低 (来自U1A输出) |
低 (来自U1B输出) |
00 (SW1 ON, SW2 ON) |
- 当一个开关断开 (OFF) 时: 它连接的或非门输入悬空(相当于输入低电平?)。但关键点在于:只要一个开关是断开的,它所连接的或非门输入就失去了有效驱动。这时,该或非门的状态由其另一个输入(另一个或非门的输出)决定。
- 当一个开关闭合 (ON) 时: 它会将其连接的或非门的一个输入直接拉低 (接地)。
- 或非门输出的逻辑: 从表中可以看出,每个或非门的输出状态不仅取决于它连接的开关,还间接受另一个开关和另一个或非门输出的影响。这导致了每个开关状态组合在GPIO1和GPIO2上产生了唯一的二进制编码:
11, 01, 10, 00。软件只需要读取这两个GPIO的状态,就可以唯一确定两个干簧管是都断开了,还是S1闭合S2断开,还是S1断开S2闭合,还是都闭合。
? 为什么不用每个干簧管直接对GND检测?
直接对GND检测是传统的按键检测方法(一个IO + 一个上拉电阻 + 按键到GND):
- 单个干簧管: 需要1个GPIO + 1个上拉电阻。
- 两个干簧管: 需要 2个GPIO + 2个上拉电阻 + 2根独立的地线(或者共用GND)。
- 可能的"状态模糊"问题: 如果微控制器的IO口内部上拉不够强,或者受到噪声干扰,在开关断开时读到的电平可能不确定(是内部上拉的高电平?还是外部干扰?)。但在设计良好时,这个问题通常不严重。
✅ 为什么图中方案更优?
**显著节省GPIO资源!**
- 直接检测2个开关需要 2个GPIO。
- 本方案检测2个开关也只需要 2个GPIO。看起来一样?不对!
- 关键优势在于扩展性: 这个设计的精髓在于状态编码。它用2个GPIO 唯一检测了2^2=4种状态(两个开关的组合)。如果微控制器有N个IO口使用这种交叉或非门编码电路,理论上最多可以检测 2^N - 1 个按键(因为状态
11...1通常是所有按键断开的默认状态,需要用到所有IO口)。直接检测N个按键需要N个IO口。在按键较多时,本方案的效率优势(节省IO口)就非常明显了。虽然在2个按键时只节省了布线,但在资源受限的STM8L上,即使省一个IO也可能意义重大。
硬件消抖与状态锁定:
- 或非门是由晶体管构成的门电路,具有一定的输入/输出转换延迟和驱动能力。这种特性一定程度上(虽然不强)能抑制开关触点抖动导致的快速电平变化,使得输入到GPIO的信号毛刺更少、更稳定。在临界状态(如开关断开瞬间),门电路的固有延迟和逻辑阈值能提供微弱的"滤噪"效果。而GPIO内部的上拉电阻可能对这个作用不大。
消除状态模糊/悬浮:
- 在"双断开"状态 (
11),虽然两个输入都悬空,但或非门输出高电平通过电阻上拉至VCC,为GPIO提供了确定的高电平驱动(比纯靠内部弱上拉要强)。在"单闭合"状态,闭合开关的低电平路径提供了强驱动(接地),断开侧的GPIO由另一个或非门的有源输出驱动(高电平)。在"双闭合"状态,接地提供了最强驱动。这意味着在任何有效状态下,两个GPIO的输入电平都不是靠内部弱上拉维持的悬空高阻状态,而是由低阻路径(VCC或GND或门电路输出)明确驱动,大大增强了抗干扰能力,避免了悬空时易受噪声影响导致误判的问题。这是我认为最大的优势。
简化PCB布线:
- 虽然图中看起来有点复杂,但在实际布线中,两个或非门(通常是单个7402/4001等芯片)可能集成在一个很小的封装里(如SOIC-14、甚至更小的封装)。最关键的是,只需要将干簧管的地线连接到一起(不需要两条独立接地线到微控制器),然后引到公共地。相比直接接地法简化了连线(尤其当物理位置分离时)。电路公共节点更少。
? 总结
这个设计的核心是利用或非门交叉连接构成的简单编码网络:
- 目标: 用最少的GPIO口检测多个按键状态。
- 核心原理: 每个开关的组合状态在2个GPIO上产生唯一的二进制编码 (
00, 01, 10, 11)。软件只需读取一次这两个IO的状态,就能直接判断出哪个/哪些开关按下了。
- 主要优势 (相比直接接地检测):
- 更省GPIO (在多按键时): N个IO理论上能检测最多 (2^N - 1) 个按键。
- 更高的抗干扰能力: GPIO在每种有效状态下都由低阻路径(VCC、GND或门电路输出)强驱动,消除悬空输入问题,不易受噪声干扰。
- 潜在的硬件消抖作用: 门电路的延迟特性有助于减弱开关抖动。
- 可能的布线简化: 开关地线可集中接到一处公共地。
- 代价: 需要增加两个或非门(一个小芯片),比纯GPIO方案增加了一点硬件成本。
这个设计在GPIO资源受限、抗干扰性要求高或需要按键扩展的场合是非常巧妙的选择。? 对于干簧管这种开关元件,它稳定可靠的特性也特别适合这类逻辑检测电路。如果你在设计资源紧张或对可靠性要求高的产品,这种编码方法非常值得参考。
举报