本页目录

常见外围电路

学了元件和协议,最终要搭成能用的电路。以下是项目中最常出现的外围模块。


按键与消抖

问题

机械按键按下时不是干净的通断:
  V
  │ ┌─┐  ┌──┐
  │ │ │  │  │      ← 触点弹跳 (bounce)
  │ │ └──┘  └──────
  └──────────────── t
      ↑          ↑
    按下        稳定

弹跳时间: 典型 5~20ms
不消抖 → 一次按键触发几十次

硬件消抖 (RC)

Vcc
 │
 Rpullup (10k)
 │
 ├────── GPIO
 │
 ├── R1 (1k) ──┬── 按键 ── GND
               │
              C1 (0.1μF)
               │
              GND

RC 时间常数 τ = R1×C1 = 100μs (太短)
需要 τ ≈ 弹跳时间 ≈ 10ms
→ R1=10k, C1=1μF → τ=10ms

缺点: 占用额外元件, 但可靠
优点: 不耗 CPU, 适用于中断唤醒场景

软件消抖 (常用)

// 最简单有效的方法
if (digitalRead(BUTTON) == LOW) {
    delay(20);  // 等 20ms (或用定时器, 别用 delay)
    if (digitalRead(BUTTON) == LOW) {
        // 确认按下
        handle_press();
    }
}

// 更好的: 状态机 + 定时器, 不阻塞
// 记录上次变化时间, 间隔 > 20ms 才算有效

MOSFET 做负载开关

为什么用 MOSFET 而不是直接 GPIO 驱动

GPIO 最大电流: 典型 8~20mA
需要驱动: LED 灯带 (1A), 继电器 (100mA), 电机 (>1A)
→ GPIO 控制 MOSFET, MOSFET 驱动负载

低边开关 (N-MOSFET, 负载在 Drain 和 Vcc 之间):
  Vcc ── 负载 ──┬── Drain
                 │
  GPIO ── Rg ──── Gate
                 │
                Source ── GND

  优点: 简单, N-MOSFET Rds(on) 低
  缺点: 负载不接地 (某些场景不行)

高边开关 (P-MOSFET, 负载在 Drain 和 GND 之间):
         Source ── Vcc
           │
  GPIO ──┬─ Rg ── Gate
         │
        NPN/ NMOS (电平转换, 因为 GPIO 3.3V 关不断 P-MOS)
         │
        GND

         Drain ── 负载 ── GND

  优点: 负载一端接地 (安全)
  缺点: 需要电平转换, P-MOS Rds(on) 较高

栅极保护 (必须!)

            Rg (100Ω~1k)
  GPIO ───┤├─────── Gate
                   │
                   Rgs (10k~100k)
                   │
                  GND

Rg: 限制栅极充放电电流, 抑制振荡
Rgs: GPIO 未初始化/复位期间确保 Gate=GND (MOSFET 关闭!)
     没有 Rgs → 上电瞬间 Gate 浮空 → MOSFET 可能误导通

高压/感性负载: Gate 对地加 TVS 或齐纳二极管
  (防止漏极尖峰通过 Cgd 耦合回栅极 → 击穿栅极氧化层)

光耦隔离

什么时候需要光耦

- 高压与低压之间 (市电 220V ↔ MCU 3.3V)
- 长距离信号传输 (地电位差大)
- 需要消除地环路噪声
- 工业现场 (浪涌/雷击)

不需要光耦的场景:
  - 同板不同电压域 → 用电平转换芯片
  - 同板 I2C/SPI → 不需要隔离 (除非工业)

基本电路

MCU 侧 (3.3V)          被控侧 (12V/24V)
    │                       │
  GPIO                      R (限流)
    │                       │
    R (限流 LED 电流)     ┌──┴──┐
    │                    │光耦  │
   ┌┴┐                   │输出侧│
   │LED (内部)           │      │
   └┬┘                   └──┬──┘
    │                       │
   GND                     GND (被控侧)

典型: PC817 (便宜, 低速), 6N137 (高速, 10Mbps)

LED 侧: If = 5~20mA, R = (3.3V-1.2V)/If
输出侧: 根据负载计算限流

继电器驱动

续流二极管 — 绝对不能省!

               Vcc
                │
              ┌─┴─┐   ▸├ (续流二极管)
              │继电器│   │
              └─┬─┘   │
                │     │
              ┌─┴─┐   │
              │MOSFET│  │
              └─┬─┘   │
                │     │
               GND────┘

关断瞬间: 线圈电流不能突变 → 产生反向高压 (L×dI/dt)
          可能 >100V! → 没有续流二极管 → MOSFET 击穿

二极管方向: 反向并联 (阴极接 Vcc, 阳极接 MOSFET Drain)
  正常时反偏不导通
  MOSFET 关断时提供电流回路

选二极管: 1N4148 (小继电器), 1N4007 (大继电器)
         快恢复或肖特基 (减少 EMI)

完整电路

              Vcc (5V/12V/24V)
               │
              ┌┴┐
              │▸├ (续流)
              └┬┘
               │
              ┌┴┐
              │继电器│
              └┬┘
               │
             Drain
  GPIO ──Rg─── Gate  N-MOSFET
               │     (选 Rds(on) 低, Vds > Vcc×2)
             Source
               │
              GND

继电器线圈电流: I = Vcc/R_coil
  例: 5V 继电器 70Ω → 71mA

MOSFET 选型:
  Vds > Vcc × 1.5
  Id > I_coil × 1.5
  Vgs(th) < GPIO 高电平 (3.3V 系统选 2.5V 以下)
  推荐: AO3400 (30V/5.8A, Vth<1V, 便宜好用)

LED 驱动

方式电路适用
限流电阻R = (Vcc-Vf)/I_LED指示 LED
恒流 IC如 CAT4101, BCR401大功率/照明
PWM + MOSGPIO PWM → MOS → LED调光
恒流 LED 驱动如 WS2812B/SK6812可寻址 RGB

恒流 vs 限流电阻

限流电阻:
  I_LED = (Vcc - Vf) / R
  Vcc 波动 → 电流波动
  Vf 温度漂移 → 电流漂移
  大功率时电阻发热严重

恒流源:
  电流恒定, 不随 Vcc/Vf 变化
  多个 LED 串联也行 (电压累加, 电流不变)
  效率高

看门狗 (Watchdog)

为什么需要

嵌入式设备跑了 3 个月 → 死机了 → 用户只能拔电
原因: 内存泄漏、指针飞了、EMI 干扰、罕见 bug

看门狗 = 独立定时器
  固件正常: 定时"喂狗" (重置定时器)
  固件卡死: 不喂狗 → 超时 → 硬件复位

使用要点

❌ 在主循环里喂狗 (卡死在子函数里还是在喂)
✅ 在独立的监控任务里喂狗
   或: 多个任务必须全部签到才喂狗

❌ 用 delay/sleep 时忘记喂狗
✅ 长延时拆成多个短延时 + 喂狗

❌ 用很短的看门狗超时 (正常运行时可能来不及喂)
✅ 超时 > 最长任务执行时间的 2 倍

独立看门狗 (IWDG): 独立时钟源, 系统时钟挂了也能复位
窗口看门狗 (WWDG): 只能在特定时间窗口喂 (更严格)

关键词: 消抖, MOSFET开关, 光耦, 续流二极管, 继电器, LED驱动, 看门狗, GPIO