上一站:嵌入式转型的五个阶段(总览) 这一篇:只做 S0 —— 硬件零基础破冰。 写给谁:能 SSH 登录、能改配置文件、能看日志,但从没接过一根杜邦线的人。 耗时:一周,每天 1–2 小时。
为什么 S0 不能跳
先说结论:没有硬件的嵌入式学习,100% 会半途而废。
不是意志力问题,是反馈回路断了。写 C 语言,编译过了没有报错,你并不知道自己写对没有;但灯亮了,这一下大脑立刻给多巴胺。学 C 的痛苦,只有被"灯亮了"抵消掉才扛得住。
S0 只干一件事:建立这条因果链的第一个闭环。
你敲一条命令 ──▶ 引脚电平变 ──▶ 电路通 ──▶ 灯亮
这条链一旦通了,后面所有的协议、并发、多节点,都只是在这条链上加点东西。
一、先买对东西(别一次买全)
最小起步约 ¥620–1,100。清单:
| # | 器件 | 规格 | 参考价 | 作用 | 能不能省 |
|---|---|---|---|---|---|
| 1 | 树莓派 | Pi 5 4GB / Pi 4B 2GB | ¥500–850 | 主角 | 不能 |
| 2 | microSD | 32GB Class10 A1/A2 | ¥30–45 | 系统盘 | 不能 |
| 3 | 读卡器 | microSD 读卡器 | ¥10–15 | 烧系统 | 不能 |
| 4 | 电源 | Pi 5 官方 27W USB-C / Pi 4B 5V3A | ¥40–90 | 供电 | 别省 |
| 5 | 面包板 | 830 孔 | ¥5–10 | 免焊接线 | 不能 |
| 6 | LED + 电阻 | 红/绿 LED 各 5 个、220Ω×10 | ¥5–10 | 你的第一个负载 | 不能 |
| 7 | 杜邦线 | 公对母 20 根 | ¥8–15 | 连接 | 不能 |
| 8 | 继电器模块 | 5V 单路,低电平触发 + 光耦隔离 | ¥8–15 | S1 才用 | 这次可以不买 |
⚠️ 省钱的唯一正确姿势:先买 1–7,灯亮了再买 8。 ⚠️ 最不该省的是第 4 项。供电不足会表现成各种玄学故障——随机重启、USB 掉线、Wi-Fi 断流,你会花三天以为是系统问题。
选 Pi 5 还是 Pi 4B
| Pi 5 | Pi 4B | |
|---|---|---|
| GPIO 电流能力 | 一样(3.3V / 单脚 16mA) | 一样 |
| 性能 | 强很多(编译 C 快一倍以上) | 够用 |
| 发热 | 热,必须带主动散热 | 温 |
| 价格 | 高 | 低 |
只做 S0/S1 的网关,Pi 4B 2GB 完全够。 但如果打算后面做交叉编译、跑 Docker,Pi 5 省下来的等待时间值这个钱。
二、只用一条公式:欧姆定律
V = I × R,变形:
R = (V电源 − V负载) / I目标
LED 为什么要串电阻?因为LED 不是电阻,它的伏安特性几乎是垂直的——电压稍微高一点,电流就暴涨,然后烧掉。电阻的作用是把电流摁住。
算一遍(红灯):
- 电源:GPIO 输出 3.3V
- 红灯正向压降:约 1.8–2.0V
- 想让它亮得舒服又不伤引脚:6mA 左右
R = (3.3 − 2.0) / 0.006 ≈ 217Ω
取标准值 220Ω,实际电流约 5.9mA —— 安全(单脚上限 16mA)。
换颜色要不要换电阻
要。 正向压降不一样:
| 颜色 | 正向压降 | 220Ω 下电流 | 结论 |
|---|---|---|---|
| 红 | ≈1.8–2.0V | ≈6mA | 合适 |
| 黄/绿 | ≈2.0–2.2V | ≈5mA | 合适 |
| 蓝/白 | ≈3.0–3.2V | ≈1mA | 偏暗,要换 100Ω |
⚠️ 蓝白 LED 用 220Ω 会觉得"是不是没接对",其实是电流太小。
这条是 S0 唯一必须真正理解的物理。后面所有"为什么带不动电机"“为什么要继电器”,都是同一件事的不同规模。
三、接线:三个连接,别接错
树莓派 40 针脚(Pi 5 与 Pi 4 物理完全一致,BCM 编号也一致)。这次只用三个:
| 物理引脚 | 名称 | 接到哪 |
|---|---|---|
| Pin 11 | GPIO17 | 220Ω 电阻一端 |
| Pin 6 | GND | LED 负极(短脚) |
| — | Pin 1 / 17 | 3.3V(这次不用) |
Pin 11 (GPIO17) ──[ 220Ω ]──▶|── Pin 6 (GND)
LED
(长脚进,短脚出)
要点:
- LED 有极性:长脚是正极(阳极),短脚是负极。反接不亮,但不会烧,翻过来就行。
- 电阻串在任意一端都行(正极侧或负极侧),效果一样。
- 别用 5V 引脚(Pin 2 / 4)。GPIO 是 3.3V 器件,5V 灌进 GPIO 会烧 SoC。
- 接线前先断电(拔掉电源)。这条规矩从今天开始,一辈子有效。
面包板怎么通电
面包板中间那条凹槽把上下两半分开了,两边不导通。上下各有一条带红蓝标记的"电源轨":
- 红线整条连通,蓝线整条连通
- 但上半区的红线和下半区的红线不连通
- 每个"孔列"(5 个孔一排)内部连通,跨凹槽不连通
本次只用杜邦线直连,可以完全不碰电源轨——初学最省事的做法就是少用面包板。
🔴 安全红线(贯穿整个嵌入式路线):只碰 5V / 12V 低压直流。 市电(220V)设备一律用成品智能插座替代。断电再接线。大功率负载必须经继电器或 MOSFET,GPIO 绝不直接驱动任何电机/灯泡/加热丝。
四、点亮它:三种方式,从最低层到最省事
方式 A:命令行 pinctrl(最快,一行搞定)
树莓派 OS(Bookworm 及以后)自带 pinctrl:
pinctrl get 17 # 看当前状态
# 17: ip -- | lo // GPIO17 = input
pinctrl set 17 op dh # 设为输出,驱动高电平 → 灯亮
pinctrl set 17 op dl # 驱动低电平 → 灯灭
看到 pinctrl get 17 变成 17: op -- -- | hi 就是成功了。
先确认 header 在哪个 chip 上:
gpiodetectPi 5 新内核(6.6.45 之后)的 40 针脚在gpiochip0(pinctrl-rp1);早期 Pi 5 镜像在gpiochip4,现在gpiochip4只作兼容别名保留。
方式 B:Python gpiozero(最直观,适合先跑通)
from gpiozero import LED
from time import sleep
led = LED(17)
for _ in range(5):
led.on(); sleep(0.5)
led.off(); sleep(0.5)
sudo apt install -y python3-gpiozero
python3 blink.py
方式 C:C + libgpiod(你最终要用的)
// blink.c — 编译: gcc -O2 -Wall -o blink blink.c -lgpiod
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
struct gpiod_chip *chip = gpiod_chip_open_by_name("gpiochip0");
if (!chip) { perror("open chip"); return 1; }
struct gpiod_line *line = gpiod_chip_get_line(chip, 17);
if (!line) { perror("get line"); gpiod_chip_close(chip); return 1; }
if (gpiod_line_request_output(line, "blink", 0) < 0) {
perror("request output"); gpiod_chip_close(chip); return 1;
}
for (int i = 0; i < 5; i++) {
gpiod_line_set_value(line, 1);
printf("LED ON\n");
fflush(stdout);
sleep(1);
gpiod_line_set_value(line, 0);
printf("LED OFF\n");
fflush(stdout);
sleep(1);
}
gpiod_line_release(line); /* 归还引脚 */
gpiod_chip_close(chip);
return 0;
}
sudo apt install -y libgpiod-dev
gcc -O2 -Wall -o blink blink.c -lgpiod && ./blink
三个 API 版本差异:
libgpiod1.x 用gpiod_chip_open_by_name/gpiod_line_request_output;2.x 改成了gpiod_chip_open+gpiod_line_request结构体风格。上面是 1.x(Raspberry Pi OS 当前仓库版本)。如果编译报implicit declaration,先pkg-config --modversion libgpiod看版本。
为什么必须走一遍 C:pinctrl 和 gpiozero 都是别人包装好的,你不知道底下发生了什么。用 C 写一次 open chip → get line → request output → set value → release,你就明白了:GPIO 在 Linux 里就是一个可以被"申请"的资源,和打开一个文件没本质区别。
这句话是整条嵌入式路线的地基。
五、SSH 远程点灯(这一步才算真的"控制")
把上面任何一个程序放到树莓派上,从你的笔记本执行:
ssh pi@raspberrypi.local 'pinctrl set 17 op dh' # 灯亮
ssh pi@raspberrypi.local 'pinctrl set 17 op dl' # 灯灭
这一刻的意义:你人在另一个房间,通过一条网络连接,让一个物理器件状态改变了。
这就是"物联网"的全部本质。 后面 S1 的网页开关灯、S3 的多节点协同,都是这一条命令的包装。
六、五个必踩的坑
| 症状 | 原因 | 怎么修 |
|---|---|---|
| 灯完全不亮 | LED 反接 / 电阻没插实 | 翻 LED;把元件按到底 |
| 灯很暗 | 蓝/白 LED + 220Ω,电流不够 | 换 100Ω,或换红色 LED |
pinctrl: command not found | 老系统(Bullseye 之前) | 用 raspi-gpio set 17 op dh,或升级系统 |
gpiod_chip_open: No such file | chip 名不对 | gpiodetect 看实际名字,Pi 5 早期镜像是 gpiochip4 |
| 程序退出后灯还亮着 | 没 gpiod_line_release | 这是 RAII 要解决的问题,S1 会讲 |
| 树莓派随机重启 | 供电不足 | 换官方电源,别用手机充电器 |
七、过门标准(四条,缺一条不算过)
- ✅ 独立烧录系统(不让别人帮你点鼠标)
- ✅ 点亮一个 LED
- ✅ SSH 登录,用命令行控制它亮灭
- ✅ 能回答这两个问题:
- 为什么 LED 要串 220Ω,不能直接接 3.3V?
- 换成蓝色 LED,电阻要变大还是变小?为什么?
第 4 项是重点。能算出来,说明你懂了;只会照抄接线图,等于没学。
八、下一步
S0 通过之后,S1 是「用 C 重写一个网关」,周期 4–6 周,最终产出网页点按钮 → 继电器"咔"一声。
到那时你会用到今天买的继电器模块(所以它列在清单里但可以先不买)。
同时补两块地基:
- 电学基础:先回看本篇第二节的欧姆定律,再找一本直流电路入门书放在手边——只查不读,遇到"这个电阻多大"才去翻
- C 语言:指针、结构体内存布局、
snprintf、函数指针。函数指针是 C 里唯一的"多态",MCU 的驱动框架全靠它
附:这次的最小行动清单
今天:下单 1–7 项
第 1 天:烧系统 → 能 SSH 登录
第 2 天:接 LED + 电阻 → pinctrl 点亮
第 3 天:算电阻 → 换三种颜色验证
第 4 天:gpiozero 跑 blink.py
第 5 天:用 C + libgpiod 重写 blink.c
第 6 天:SSH 从笔记本点灯
第 7 天:回答过门问题,拍照存档
七天之后,你就不是"没碰过硬件的人"了。
最后更新:2026-10-24 · 下一篇:S1 用 C 重写网关(预告)