开始之前

第 2 课:环境配置(Arduino CLI + AI 辅助路线)

用 AI 带着你自动装好 Arduino CLI 和 ESP32 开发环境,避开 C3 的串口坑,最后用 Blink 点亮板载 LED。

环境配置:Arduino CLI + AI 辅助路线

这节课有点长,但值得

我是吴老师。上一条路我们用积木把灯点亮了,这一条路,我们把灯点亮的同时,还要把"为什么"搞明白

先说清楚一件事:这节课比图形化那节长,中间可能会卡。我提前把话说在这儿——卡住是正常的,不是你笨,也不是你电脑有问题。装嵌入式环境这事儿,全世界的人都卡。区别只在于:有人卡住了就放弃了,有人卡住了知道该查哪一步。这节课我主要教你的,就是"该查哪一步"。

好消息是,你现在有 AI 帮忙。以前装环境是纯手工活,报错了只能去论坛翻帖子;现在 AI 能直接读你的报错、直接敲命令、直接帮你定位。 这就是为什么我不用 Arduino IDE,而是用 Arduino CLI——下面第一节就讲这个。

一、为什么用 Arduino CLI,不用 Arduino IDE

我知道你听过 Arduino IDE。图形界面,点两下就能烧程序,看着挺友好。那为什么不推荐?

因为IDE 是一扇关着的门,CLI 是一扇开着的门

Arduino IDE 是一扇关着的门,AI 看不见也点不了;CLI 是一扇开着的门,AI 能直接执行命令

Arduino IDE Arduino CLI
交互方式 鼠标点按钮 敲命令
AI 能不能帮你操作 不能。AI 看不见你的窗口,也点不了你的按钮 。AI 可以直接执行命令、读输出、判断结果
出错时的信息 弹窗、红字,你还得自己描述给 AI 听 全是文本,AI 能直接读懂并定位
能不能重复 每次都要手动点一遍 一条命令,写一次跑一百次
能不能写成脚本 基本不能 天生就是干这个的
装环境 手动在菜单里翻,一层套一层 三条命令装完

关键就在第一行对比。AI 没法帮你点鼠标,但 AI 能帮你敲命令。 你选 IDE,就等于把 AI 这个最强助手关在门外了;你选 CLI,AI 就能全程陪着你,从装环境一路陪到烧录排错。

另外三个理由,说给你听:

  1. 可脚本化。 你要给 30 个学生装同样的环境?CLI 写个脚本,一次搞定;IDE 就一个一个点吧。
  2. 可复现。 命令是白纸黑字写下来的,我发的命令你照着敲,结果一模一样。IDE 里"点哪个菜单"这种描述,换个版本就失效了。
  3. 输出是文本。 编译报错、烧录日志、串口输出,全是纯文本。文本 AI 读起来毫无障碍——这意味着你遇到问题不用费劲描述,直接把输出丢给 AI 就行。

一句话:IDE 是给人操作的,CLI 是给人和 AI 一起操作的。 我们这套课有 AI,所以选 CLI。

二、动手之前,先认你的板子和线

别急着敲命令。环境配置失败的原因,一半不在软件,在硬件。先花三分钟把这三件事确认了,能省你一个下午。

1. 那根线,是不是数据线

你套件里那根 Type-C 线,我在材料清单里特意标了**"需支持数据传输"**,不是凑字数的。

市面上大量的 Type-C 线是纯充电线——里面只有供电的两根芯(VBUS 和 GND),根本没有传数据的那两根(D+ 和 D-)

插上这种线会发生什么?板子上的电源灯亮得好好的,电脑却怎么都找不到串口。 你会以为是驱动问题、是板子坏了、是软件装错了,折腾一下午,其实就换根线的事。

这个坑太经典了,我专门教你怎么用万用表验它:

  1. 万用表打到通断档(就是那个会"嘀"的档位,图标像个声波)。
  2. 先短接两支表笔,确认表响了。这一步不能省——表笔断了或者档位打错了,测什么都是不通,你会得出错误结论。
  3. 一支表笔点线的一头,另一支点另一头对应的触点,测 GND 是否导通(应该响)。
  4. 再测 D+ 和 D- 是否导通。

第 4 步就是分水岭:GND 响、D+ 或 D- 不响 → 这就是一根纯充电线,换掉它。 别犹豫,也别可惜,它对你没有任何用处。

图省事的话还有个土办法:拿一根你平时给手机传文件用的线,那种线一定是数据线。

2. 板子上那两个小按键

拿到板子,翻到正面,你会看到一到两个小小的贴片按键。它们大概率是这两个:

  • BOOT 键:管"进入下载模式"的。烧录不进去的时候,就得靠它。
  • EN / RESET 键:管"复位重启"的。

有些小板子(尤其是那种很小的 C3)只有一个 BOOT 键,没有复位键。 没关系,后面的操作照样能做,我会写两种手法。

现在你只需要做一件事:用手摸一遍,记住它们在哪、哪个是哪个。 一会儿卡住了你会感谢现在的自己。

3. 板子上有没有那颗"转接芯片"

这一步是给后面那个最大的坑做铺垫。

把板子翻到背面,看看 Type-C 口旁边,有没有一颗小小的黑色方形芯片(比指甲盖还小)。有两种情况:

  • 有这颗芯片:说明板子用了一颗"USB 转串口"芯片(常见型号 CH340、CH343、CP2102)。这颗芯片负责把电脑的 USB 信号翻译成主控能懂的串口信号。
  • 没有这颗芯片:说明这块板子是 Type-C 直连主控的,靠 ESP32-C3 芯片自己内置的 USB 功能来跟电脑通信(这块 C3 内置了 USB Serial/JTAG)。

记住你是哪一种,第三节讲坑的时候要用。 判断不出来也没关系——插上电脑看设备管理器,后面会讲怎么分辨。

三、装 Arduino CLI

下面是正式操作。我按 Windows 11 给你写。

方式 A:winget(我推荐这个)

Windows 11 自带 winget。打开PowerShell或者终端,敲:

PowerShell
winget install --id ArduinoSA.CLI --exact

装完之后,把终端窗口关掉,重新开一个——这一步很多人漏掉,导致敲 arduino-cli 提示"找不到命令",然后以为装失败了。其实只是当前窗口还没读到新的 PATH。

重新开窗口后验证:

Shell
arduino-cli version

看到类似 arduino-cli Version: 1.x.x ... 就成功了。

方式 B:MSI 安装包

不想用 winget,就去下载官方 MSI:

纯文本
https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.msi

下载完双击装,一路下一步。装完同样重开终端,再验证。

方式 C:手动解压 ZIP(需要自己配 PATH)

下载这个 ZIP:

纯文本
https://downloads.arduino.cc/arduino-cli/arduino-cli_latest_Windows_64bit.zip

解压到哪儿?别乱放。 我给你两条硬规矩:

  • 路径必须是纯英文、不能有空格。 别放在"桌面"、别放在"我的文档"、别放在带中文的文件夹里。中文路径会让后面的编译和烧录出各种莫名其妙的错,而且报错信息完全看不出是路径的锅——这是最恶心的一类问题。
  • 建议路径C:\arduino-cli\(全局,所有用户可用),或者 C:\Users\你的用户名\arduino-cli\(只给当前用户,不需要管理员权限)。

解压完,C:\arduino-cli\arduino-cli.exe 应该存在。

配 PATH

用 PowerShell 永久添加(注意别用 setx,它会在 1024 字符处截断,还有可能把你的 PATH 整个覆盖掉,是个坑爹命令):

PowerShell
$old = [Environment]::GetEnvironmentVariable('Path', 'User')
[Environment]::SetEnvironmentVariable('Path', $old + ';C:\arduino-cli', 'User')

改完必须重开终端才生效。

如果只想在当前 Git Bash 窗口临时用一下,可以这样:

Shell
export PATH="$PATH:/c/arduino-cli"

Git Bash 和 PowerShell 的差异,我说清楚

你用的是 Git Bash,这里有几个地方跟 PowerShell 不一样,不知道的话会踩坑:

事情 Git Bash PowerShell
路径写法 /c/arduino-cli C:\arduino-cli
临时加 PATH export PATH="$PATH:/c/arduino-cli" $env:Path += ';C:\arduino-cli'
永久加 PATH ~/.bashrc [Environment]::SetEnvironmentVariable(...)
下载文件 curl -L -o x.zip URL curl.exe(PowerShell 里的 curlInvoke-WebRequest 的别名,参数完全不一样,直接写 curl 会报错)
搜索输出 arduino-cli board listall | grep -i c3 arduino-cli board listall | Select-String c3
串口名 COM3 直接写就行 COM3

关于串口名:在 Git Bash 里有时候需要用 /dev/ttyS3 这种写法来指代 COM3大多数情况下直接写 COM3 就行,如果报"端口不存在",换成 /dev/ttyS2 这种写法试一下(COM3 对应 ttyS2,也就是串口号减一)。这是 Git Bash 的历史遗留问题,不是你操作错了。

数据目录在哪

arduino-cli 下载的开发板支持包、编译工具链,默认都放在:

纯文本
C:\Users\你的用户名\AppData\Local\Arduino15\

这个目录会涨到 1~2 GB。 C 盘紧张的同学心里有个数,回头清理或者装之前先留出空间。

四、装 ESP32 支持包(两条路,选一条)

Arduino CLI 本身只是个空壳,它不知道 ESP32 是什么。我们要告诉它:去哪儿找 ESP32 的开发板支持。

这一步是整节课最容易卡住的地方,因为要下载几百 MB。我给你两条路:

方式一:在线装 方式二:离线包
适合 网速还行 装不动、反复失败、要离线教学
体积 下载约 400MB 下载约 1.8GB
时间 看网速,可能很久 下载慢,但装是一次性的
从哪拿 直接命令行装 百度网盘

先试方式一。 卡住了、反复失败,再上方式二。方式二虽然文件大,但一次到位,不用管网络


方式一:在线装(用国内镜像)

第 1 步:生成配置文件

Shell
arduino-cli config init

这会在 Arduino15 目录下生成 arduino-cli.yaml。看看它长什么样:

Shell
arduino-cli config dump

第 2 步:加开发板索引地址

这一步是关键,加错了后面会慢到你想砸电脑。

Shell
arduino-cli config add board_manager.additional_urls https://jihulab.com/esp-mirror/espressif/arduino-esp32/-/raw/gh-pages/package_esp32_index_cn.json

注意我加的是国内镜像,不是官方地址。 这里必须解释一下为什么,因为它直接决定你后面的体验:

官方索引 espressif.github.io 只是个"目录",它本身能访问。但它里面记的每一条下载地址都指向 github.com——而 GitHub 在国内是出了名的不稳定。

国内镜像索引 package_esp32_index_cn.json 不一样:它里面 1000 多条下载地址全部指向 dl.espressif.cn(乐鑫自己的国内 CDN)。同样的包,走国内 CDN 可能几分钟就下完,走 GitHub 可能一个下午都下不动。

我实测过这个镜像,本机这套环境就是用它装的。

两个地址二选一,千万别同时加。 它们指的是同一个 esp32:esp32 平台,同时加会让 arduino-cli 犯迷糊,出现"平台已安装但版本对不上"这类怪问题。

如果你之前手滑加过官方地址,先删掉:

Shell
arduino-cli config remove board_manager.additional_urls https://espressif.github.io/arduino-esp32/package_esp32_index.json

第 3 步:更新索引

Shell
arduino-cli core update-index

把"有哪些开发板、哪些版本"的清单拉下来。要联网,等一两分钟。

第 4 步:安装 ESP32 核心

Shell
arduino-cli core install esp32:esp32

这一步最慢,要下整套编译工具链(交叉编译器,几百 MB)。泡杯茶。

中途看着不动了别急着 Ctrl+C——它在下大文件,进度条经常卡着不动。Ctrl+C 打断会留下不完整的文件,下次装还得重来。

装完确认:

Shell
arduino-cli core list

列表里能看到 esp32:esp32 这一行就成了。


方式二:离线包(装不动就用这个)

这条路我不推荐你一开始就走,但它是最后的保障。

什么时候用

  • 方式一试了好几次,每次都下到一半失败
  • 你要在没有网的地方教学(机房、比赛现场)
  • 你不想每次都等下载

要下什么

一个约 1.8GB 的离线开发包,在百度网盘上:

纯文本
https://pan.baidu.com/share/init?surl=BlzEhW6F85fYG9sU3Cd0Xg
提取码:8888

为什么单独放网盘? 因为 1.8GB 太大了,没法塞在课程里直接给你。

另外:百度网盘不开会员下载会很慢,这是它的商业模式,不是文件有问题。如果你有别的网盘,也可以问问吴老师有没有备用地址。

里面是什么

这个包不是只有 ESP32 核心,而是一整个配置好的编译环境

内容 干什么的
ESP32 核心(3.3.10-cn 开发板支持包本体
全套工具链 RISC-V 编译器、C3 专用库、烧录工具
库索引 装第三方库时的目录,省得再联网拉

关键是"工具链"那几项。 没有它,你只能写代码不能编译——而它就是在线安装时最慢、最容易失败的那几百 MB。装上它,编译就完全不需要网了。

怎么装

一句话:把包里那个 Arduino15 文件夹,整个放到指定位置。

  1. 解压下载好的包,你会看到一个叫 Arduino15 的文件夹
  2. 找到你的目标位置(在资源管理器地址栏敲这个,回车):
    纯文本
    %LOCALAPPDATA%
    一般是 C:\Users\你的用户名\AppData\Local\
  3. Arduino15 整个放进去,和已有内容合并

如果那个位置已经有 Arduino15 了怎么办?

重命名Arduino15_备份(别直接删,万一要退回去)。然后再把新的放进去。

因为离线包里的版本是 3.3.10-cn,如果你之前装过别的版本,混在一起会出现"平台已安装但版本对不上"的问题。

  1. 验证
    Shell
    arduino-cli core list
    看到 esp32:esp32 3.3.10-cn 就成了。

本机现在用的就是这个版本。 所以课里后面所有命令,跟我这里的结果能对上。


五、找到 ESP32-C3 的"身份证"

不管走哪条路装好的,到这一步都一样。

在 arduino-cli 里,每块板子都有一个编号,叫 FQBN(Fully Qualified Board Name)。后面编译烧录都要用它。

Shell
arduino-cli board listall | grep -i esp32c3

PowerShell 里用 Select-String

PowerShell
arduino-cli board listall | Select-String esp32c3

我们要的是这个:

纯文本
esp32:esp32:esp32c3

把它抄下来,贴在你笔记里。 记不住没关系,但别记错——写成 esp32:esp32:esp32(那是通用 ESP32,不是 C3)就等着看板子装死吧。

六、装几个常用库

库就是别人写好的功能包。我们要用的:

Shell
arduino-cli lib install "Adafruit GFX Library"
arduino-cli lib install "Adafruit SSD1306"
arduino-cli lib install "DHT sensor library"
arduino-cli lib install "Adafruit Unified Sensor"

说明一下这几个是干嘛的:

干什么用
Adafruit GFX Library 图形显示的地基,画点、画线、画字
Adafruit SSD1306 OLED 屏的驱动,配合上面那个用
DHT sensor library 读温湿度传感器的
Adafruit Unified Sensor 上面那个 DHT 库的依赖,不装会编译报错

为什么现在就把这些装上? 因为这些库的下载和安装,也是要联网、也可能出错的。与其等到上 OLED 那一节课手忙脚乱,不如现在一次性把地基打平。

装完检查:

Shell
arduino-cli lib list

再说个小技巧:不确定库的准确名字时,先搜:

Shell
arduino-cli lib search SSD1306

搜出来的名字要原样用引号包着装进去,名字差一个字母都装不上。

七、ESP32-C3 的坑(这一节最重要)

好,环境装完了。但装完不等于能用。ESP32-C3 有几处特别的坑,不知道的话你会以为环境装错了,然后从头再装一遍——白折腾。

我把这些年被这些坑坑过的经验,一条一条交给你。

坑 1:串口一片空白——USB CDC On Boot

这是 C3 上最常见、最气人的一个问题。 症状是:程序烧录显示成功,板子也在跑,但你打开串口监视器,一片空白,一个字都没有

我先讲讲为什么会这样。

ESP32-C3 芯片上有两套能往外"说话"的通道:

  1. UART0:一根传统的串口,走 GPIO20(RX)和 GPIO21(TX)。
  2. USB Serial/JTAG:芯片内置的 USB 功能,直接走 GPIO18(D-)和 GPIO19(D+),也就是你那个 Type-C 口。

现在问题来了:你写的代码里 Serial 这个词,到底走哪条通道?

这是编译时决定的,由一个叫 CDCOnBoot 的选项控制:

  • CDCOnBoot=default(默认,关闭)→ SerialUART0GPIO20/GPIO21)。
  • CDCOnBoot=cdc(打开)→ SerialUSBGPIO18/GPIO19,即 Type-C 口)。

于是两种板子会出现两种完全相反的症状:

情况 A:你的板子是 Type-C 直连主控(没有转接芯片)。 Type-C 口连的是芯片的 USB 引脚。如果你保持默认(CDCOnBoot=default),Serial 就往 UART0 发数据——而 UART0 那两根脚根本没接到 Type-C 口上,悬空着呢。数据发到空气里去了。所以你看到的就是:烧录成功,串口空白。

→ 解法:给 FQBN 加上 :CDCOnBoot=cdc

情况 B:你的板子上有转接芯片(CH340 / CP2102)。 电脑看到的那个串口,是通过转接芯片连到 UART0 的。这时候你如果设了 CDCOnBoot=cdcSerial 就改往 USB 发了,而 USB 那两根脚可能压根没接到 Type-C 口。于是又是空白。

→ 解法:保持默认,别加 CDCOnBoot=cdc

看出来了吧?这个选项没有"对"和"错",只有"跟你的板子配不配"。 判断方法就是我们在第二节让你看的那颗芯片:

板子上有没有转接芯片 CDCOnBoot 该怎么设 串口走哪
没有(Type-C 直连) 加上 :CDCOnBoot=cdc USB(GPIO18/GPIO19
有(CH340 / CP2102 等) 保持默认,不加 UART0(GPIO20/GPIO21

加上之后的完整命令长这样:

Shell
arduino-cli compile --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc D:/dev/esp32-projects/blink

两个必须记住的点:

  1. CDCOnBoot 是编译期选项,不是运行期。 改完必须重新编译再重新烧录,光烧一遍旧的编译产物没用。
  2. 编译和烧录的 FQBN 要写成一样的。 别编译时带了 :CDCOnBoot=cdc,烧录时忘了带。养成习惯:同一个 FQBN 字符串,复制粘贴两遍。

还有个小提醒:在 CDCOnBoot=cdc 模式下,板子复位的时候 USB 会重新枚举一次,串口可能会短暂消失再出现。如果你看到串口在列表里一闪一闪的,那是正常的,不是坏了。

坑 2:驱动没装,电脑认不出板子

如果板子上有转接芯片,那就要装对应的驱动。Windows 11 不一定会自动给你装。

芯片型号 装什么驱动
CH340 / CH343 WCH 官方的 CH341SER 驱动
CP2102 / CP2104 Silicon Labs 的 CP210x VCP 驱动
无转接芯片(原生 USB) 一般免驱,Windows 自带的 USB CDC 驱动就够

怎么查? 打开设备管理器(按 Win + R,输入 devmgmt.msc,回车),重点看两个地方:

  • "端口 (COM 和 LPT)" 这一项下面,有没有出现一个 COM 开头的设备。
  • 有没有带黄色感叹号的未知设备。

一个百试百灵的判断手法

  1. 拔掉板子的 USB 线,看设备管理器,记住现在有什么。
  2. 插上板子,看多出来了什么

多出来的那个,就是你的板子。它出现在"端口"下面 → 驱动正常;它出现在"其他设备"下面还带个黄色感叹号 → 驱动没装,去装上面表格里对应的驱动。

装驱动这事儿,让 AI 帮你找官方下载页,别去那些乱七八糟的下载站,捆绑软件能给你装一箩筐。

坑 3:一直卡在 Connecting...,烧不进去

症状是这样——命令敲下去,屏幕上开始打点:

纯文本
Connecting........_____....._____....._____

然后一直卡着,最后超时报错。这不是环境坏了,是板子没进入"下载模式"。

正常情况下,arduino-cli 会自动通过串口的控制信号让板子复位进下载模式。但有些板子的自动复位电路没做全,或者被占用了,就得你手动来。

手动进下载模式的两种手法,按你的板子选:

手法一:板子上有 BOOT 键 + EN/RESET 键(两个键)

  1. 按住 BOOT 键不放。
  2. 点一下 EN/RESET 键(按一下松开)。
  3. 再松开 BOOT 键。

顺序别错。核心是:BOOT 要在复位的那一刻是按住的状态。

手法二:板子上只有一个 BOOT 键(很多小 C3 板是这样)

  1. 按住 BOOT 键不放。
  2. 保持按住,把 USB 线拔下来再插回去(或者如果有个电源开关就开关一次)。
  3. 再松开 BOOT 键。

进对了是什么表现? 通常会看到串口消失一下又回来(Windows 会"叮咚"一声),或者你盯着的那个"Connecting"突然就开始往下跑了。

最后强调:这个操作只在烧录失败的时候才需要。平时烧录,直接敲命令就行,不用每次都按。按 BOOT 是排错手段,不是标准流程——我见过学生每次烧录都按一遍,还以为是必须的,白白多了一道手续。

坑 4:GPIO 编号和板子丝印对不上

这个坑最隐蔽,因为它不报错。程序烧进去了,编译也没问题,就是不干活——因为你接错引脚了

先说清楚概念

  • GPIO 编号:芯片自己认的编号,是唯一的、权威的。代码里写的就是它。
  • 丝印:板子上、拓展板上印的字。是厂商自己起的名字,跟芯片没关系。

拓展板上经常看到 A0A1D2D3 这种丝印。这个 D2 极有可能不是 GPIO2,可能是 GPIO10、可能是 GPIO4,各家做得不一样。

唯一的准则是:以 GPIO 编号为准。 拿到任何一块板子,第一件事是找到它的引脚图(Pinout),把丝印和 GPIO 号的对应关系搞明白,写下来。别猜。猜错了不报错,只让你干瞪眼。

下面是 ESP32-C3 的引脚真相表。这张表你贴在桌上都不为过:

引脚 能不能接东西 说明
GPIO0 ~ GPIO4 可以,优先用 走 ADC1,做模拟输入的首选
GPIO5 慎用 是 ADC2 的唯一一路,和 WiFi 冲突,开 WiFi 时读数会失败
GPIO6 / GPIO7 可以,推荐 没特殊用途,推荐拿来做 I2C 的 SDA/SCL
GPIO8 谨慎 接了板载 RGB 灯,而且是启动模式相关引脚
GPIO9 别接东西 是 BOOT 按键,也是启动模式相关引脚
GPIO2 谨慎 启动模式相关引脚,别接按键或下拉电阻
GPIO10 可以 但跟 JTAG 调试口的选择有关,教学中建议避开
GPIO11 ~ GPIO17 别用 连着板载 flash,动了它就起不来了
GPIO18 / GPIO19 别用 是 USB 的 D- / D+,占用了 USB 口就废了
GPIO20 / GPIO21 慎用 是 UART0 的 RX / TX,串口通信用着

几条重点展开讲讲:

关于 GPIO5 和 WiFi 冲突: ESP32-C3 只有两路 ADC,ADC1 占了 GPIO0GPIO4 五路,ADC2 只有一路,就是 GPIO5。而 ADC2 是跟 WiFi 模块共用的——一旦你开了 WiFi,GPIO5 上的模拟读数就会失败或者给你乱数。所以做光敏、热敏、电位器、麦克风这些模拟实验时,一律用 GPIO0GPIO4。反正五路也够你用了。

关于 GPIO8GPIO9 这两个都是"启动模式"相关的引脚,芯片上电那一瞬间会去读它们的电平,决定是正常运行还是进下载模式。这里有个硬约束:GPIO8GPIO9 同时为低电平是非法状态,芯片会做出你预料不到的事。所以:

  • 别在 GPIO8 上接按键(按下就是接地)。
  • GPIO9 上已经焊了 BOOT 按键了,你就别往上接别的了。

关于 I2C 接 OLED 的坑(这个特别实用): ESP32-C3 的默认 I2C 引脚是 SDA = GPIO8、SCL = GPIO9。看出来问题没有?GPIO9 上焊着 BOOT 键,GPIO8 又是启动脚——俩都不是省油的灯。

所以接 OLED 的时候,别用默认引脚,在代码里手动指定。我推荐 GPIO6GPIO7

C++
Wire.begin(6, 7);   // SDA = GPIO6, SCL = GPIO7

这一行在你上 OLED 那节课的时候会救你的命。现在先记下这个结论:默认 I2C 引脚不能用,改用 GPIO6 / GPIO7

关于 GPIO18 / GPIO19 这两个是 USB 的口子。你把它们当普通 IO 用了,轻则 USB 口失效(得手动按 BOOT 才能再烧录),重则电脑再也认不出板子。总之——别碰。

坑 5:能供电,但电脑就是找不到串口

这个我在第二节提过,这里正式收尾。

板子上的电源灯亮,只说明一件事:USB 的供电通了(VBUS 和 GND 通了)。它完全不说明数据线通了。

这两件事是分开的

  • 电源灯亮 = VBUS、GND 这两根芯是通的 → 板子能上电。
  • 找得到串口 = D+、D- 这两根芯也是通的 → 电脑能和板子说话。

纯充电线只有前两根,没有后两根。 所以症状就是本文开头描述的:灯亮着,口找不到。

排查顺序,我按性价比排好:

  1. 换一根线——优先换你确定能传数据的(手机传文件那根)。这一条能解决八成的情况,而且只要十秒钟。
  2. 换一个 USB 口——特别是台式机,插机箱后面的口,别插前面板。
  3. 别用 USB 扩展坞 / Hub,直连。有些 Hub 供电不足或者芯片兼容性有问题。
  4. 万用表验 D+ / D-(做法见第二节)。到这一步还没解决,就是线的问题实锤了。
  5. 看设备管理器(见坑 2)。多出来个带感叹号的设备,那就是驱动问题,不是线的问题。

为什么要用万用表? 因为你光看外表分不出充电线和数据线,它们长得一模一样。万用表是唯一能一眼看穿的家伙。 这也是为什么材料清单里给你配了它——它不只是量电压用的,"通断"这个功能在排查这种问题时比什么都好使。

八、Blink:亲手验证环境通了

环境装好了,坑也讲完了。现在来真的——跑通 Blink,让板载 LED 闪起来。 这是我们这节课的成功标志。

第 1 步:建工程目录

先说一件重要的事:路径必须纯英文。

虽然我们这个课程项目本身的目录里带中文,但你自己写代码的工程目录,一定要用纯英文、无空格的路径。中文路径会让编译工具链出各种诡异的错,而且报错信息完全指向不到真正的原因。

所以我建议你在 D 盘建一个专门的目录:

纯文本
D:\dev\esp32-projects\

再强调一遍 Arduino 的一个死规矩:文件夹名必须和 .ino 文件名一模一样。 这条规矩无数人栽过,编译报错 main file missing from sketch 就是这个原因。

所以我们要建的是:

纯文本
D:\dev\esp32-projects\blink\blink.ino

文件夹叫 blink,文件也必须叫 blink.ino 一个字母都不能差。

在 Git Bash 里建:

Shell
mkdir -p /d/dev/esp32-projects/blink

在 PowerShell 里建:

PowerShell
New-Item -ItemType Directory -Force D:\dev\esp32-projects\blink

第 2 步:先接上 LED 模块

在写代码之前,先把灯接上。

我们套件里的 LED 是个独立的模块,不是焊在板子上的。所以你得先把它连起来:

LED 模块 接到
VCC 3.3V
GND GND
Signal GPIO3

接之前先断电(把板子从电脑上拔下来)。接好了再插回去。

为什么要用 GPIO3?因为它是这块板子上最安全的通用引脚之一——不是启动脚、不是 USB 脚、不是 flash 脚。后面几节课我们都尽量用它。

第 3 步:写代码

新建 blink.ino,就写这么点:

C++
void setup() {
  pinMode(3, OUTPUT);   // 把 GPIO3 设为"输出"
}

void loop() {
  digitalWrite(3, HIGH);   // 点亮
  delay(500);              // 等 500 毫秒
  digitalWrite(3, LOW);    // 熄灭
  delay(500);              // 等 500 毫秒
}

先别急着问为什么,先烧进去看现象。 原理我们后面几节课讲——这是这门课的规矩:先看到,再理解。

为什么这里写 3 而不是别的?

因为你的 Signal 线就接在 GPIO3 上。代码里的引脚号,必须跟你实际接线的那根脚对上。 接的是哪根、代码里就写哪根——这两件事不一致,灯就不会亮,而且从外观上完全看不出来。

这也是后面你排查故障时要留意的:第一件事就是核对"代码里写的脚"和"线插的脚"是不是同一个。

第 3 步:编译

Shell
arduino-cli compile --fqbn esp32:esp32:esp32c3 /d/dev/esp32-projects/blink

如果你的板子是 Type-C 直连的(第二节让你看过的那颗芯片,没有),加上 CDC 选项:

Shell
arduino-cli compile --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc /d/dev/esp32-projects/blink

编译成功的话,你会看到类似这样的输出:

纯文本
Sketch uses 288341 bytes (22%) of program storage space. Maximum is 1310720 bytes.
Global variables use 21876 bytes (6%) of dynamic memory, leaving 305804 bytes for local variables. Maximum is 327680 bytes.

看到这两行,就说明编译过了。 中间那些 #pragma message 之类的警告,忽略它们,不影响运行。新手最容易在这儿自己吓自己。

第 4 步:烧录

先确认板子插着,看看电脑认到哪个口了:

Shell
arduino-cli board list

你会看到类似这样的一行:

纯文本
Port  Protocol  Type              Board Name  FQBN  Core
COM3  serial    Serial Port (USB) Unknown

Board Name 显示 Unknown 是完全正常的,不用管它——那只是 arduino-cli 没法自动认出具体型号而已。我们关心的是 COM3 这个端口号。

注意:你要用你自己电脑上显示的那个端口号,别照抄我的 COM3 每台电脑都不一样。

然后烧录:

Shell
arduino-cli upload -p COM3 --fqbn esp32:esp32:esp32c3 /d/dev/esp32-projects/blink

带 CDC 的版本:

Shell
arduino-cli upload -p COM3 --fqbn esp32:esp32:esp32c3:CDCOnBoot=cdc /d/dev/esp32-projects/blink

FQBN 跟编译时保持一致,这是我前面强调过的。

烧录过程中会打出芯片信息:

纯文本
Chip type:          ESP32-C3 (QFN32) (revision v0.4)
Features:           Wi-Fi, BT, Single Core, 160MHz
Crystal frequency:  40MHz

看到 ESP32-C3 这行字,说明电脑确确实实跟芯片握上手了。 这一步的成功率是最高的,如果卡在 Connecting,回坑 3 按 BOOT。

如果卡住了,按一下 BOOT 键,或者按坑 3 的手法进下载模式,然后重新执行 upload 命令

第 5 步:看现象

烧录完成,眼睛离开屏幕,看你接的那个 LED 模块。

它开始一闪一闪,间隔半秒——恭喜,环境通了。 这节课最硬的一块骨头,你啃下来了。

没闪的话,按这个顺序倒查(顺序别乱):

  1. 接线VCC 真的是 3.3V 吗?GND 真的接地了吗?Signal 真的在 GPIO3 上吗?
  2. 代码里的引脚号:你接的是 GPIO3,代码里写的也是 3 吗?这两件事必须对上。
  3. 板子上的电源灯亮不亮?(不亮 → 坑 5,线的问题)
  4. 烧录命令真的成功了吗,还是中途报错了?(回去看输出)
  5. 前面那个"让板子说话"的程序还在跑吗?重新烧一次。

注意第 1、2 条排在最前面。九成的"灯不亮"都是接线或者引脚号的问题,而不是代码写错了。这就是下一课要学的"排查顺序"——先查硬件,最后才怀疑代码。

第 6 步:让它开口说话

灯闪了,再往前一步,让板子通过串口跟你说句话。把 blink.ino 改成这样:

C++
void setup() {
  Serial.begin(115200);             // 打开串口,速度设为 115200
  pinMode(3, OUTPUT);
  Serial.println("吴老师,我上线了!");
}

void loop() {
  Serial.println("灯亮");
  digitalWrite(3, HIGH);
  delay(500);

  Serial.println("灯灭");
  digitalWrite(3, LOW);
  delay(500);
}

波特率 115200 必须和后面读串口时用的一致,不一致就是一堆乱码。这是仅次于接错线的第二大新手坑。

重新编译、烧录(记得带上你那个 CDC 选项),然后读串口:

Shell
arduino-cli monitor -p COM3 --config baudrate=115200

Ctrl+C 退出。

给 AI 的一个实操建议:如果你是 AI 在代跑,别用 arduino-cli monitor——它是交互式终端,会一直占着不返回,不适合自动执行。改用 Python + pyserial 读固定行数:

Shell
pip install pyserial
Shell
python -c "
import serial, time
ser = serial.Serial('COM3', 115200, timeout=1)
time.sleep(2)                 # 等板子启动,这两秒不能省
for i in range(10):
    line = ser.readline()
    if line:
        print(line.decode('utf-8', errors='replace').strip())
ser.close()
"

time.sleep(2) 那行很关键——板子复位后要一两秒才启动完,起太早读到的全是空的,然后你会误判成"串口没输出"。

看到串口里滚动着"灯亮""灯灭",这节课就彻底通关了。 你现在有了一个完整可用的 ESP32-C3 开发环境。

九、AI 该按什么顺序帮你排查

这一节是写给 AI 看的,学习者也应该照着这个顺序自查。核心原则只有一条:从最底层往上一层层查,一步不通,绝不往下跳。

跳过前面的步骤直接查后面,是所有排查里最浪费时间的行为。 比如串口读不到,你上来就去改代码,而真正的原因可能是 arduino-cli 压根没装成功。

顺序 命令 要确认什么 这一步失败说明
1 arduino-cli version 能不能打印出版本号 没装成功,或者 PATH 没配好/没重开终端
2 arduino-cli config dump 输出里有没有 board_manager.additional_urls 索引地址没加上,或者配置写在别的地方了
3 arduino-cli core list 列表里有没有 esp32:esp32 核心没装成功,或者上一步索引没更新
4 arduino-cli board list 能不能列出 COM 端口 硬件层问题:线、驱动、USB 口。这一步不过,下面全是白费
5 arduino-cli board listall esp32c3 确认 FQBN 是 esp32:esp32:esp32c3 核心装好了但板型找不到,索引有问题
6 arduino-cli compile --fqbn ... 编译有没有通过 代码问题、库没装、路径问题
7 arduino-cli upload -p ... --fqbn ... 有没有打出 Chip type: ESP32-C3 板子没进下载模式(按 BOOT)、端口被占用
8 读串口(Python 或 monitor) 有没有正常文字输出 波特率不对、或 CDC 选项跟板子不匹配(回坑 1)

第 4 步是整个流程的分水岭。 端口列不出来,就不要再去动代码、动库、重装核心——那些跟这个问题一点关系都没有。老老实实回到坑 2 和坑 5:查驱动、换线、换 USB 口。

再给 AI 两条操作纪律:

  • 一次只改一个变量。 别一边换线一边重装核心一边改代码。改多了,成了你不知道为什么成,败了你也不知道是哪儿的错。
  • 每一步都把原始输出亮给学习者看。 别只说"好了"或者"失败了"。学习者看的就是这个排查过程,这才是这节课真正的教学内容。

十、故障速查表

症状 最可能的原因 怎么办
arduino-cli: command not found 装完没重开终端 / PATH 没配 关掉终端重新开一个;还不行就查 PATH
电源灯亮,但 board list 里没端口 纯充电线,D+ / D- 不通 换数据线(十秒钟解决八成情况);万用表验线;换 USB 口
设备管理器里有带感叹号的设备 驱动没装 按芯片型号装 CH340 或 CP210x 驱动
core install 卡住不动 / 超时 网络问题,在下几百 MB 工具链 耐心等;或换国内镜像索引重来
编译报 main file missing from sketch 文件夹名和 .ino 文件名不一致 改成同名,比如 blink/blink.ino
编译报找不到某个库 库没装,或库名打错了 arduino-cli lib search 关键词 搜准确名字,加引号重装
编译报中文路径相关的怪错 工程路径里有中文或空格 把工程挪到纯英文路径
烧录卡在 Connecting........_____ 板子没进下载模式 按住 BOOT → 点一下 EN → 松开 BOOT;只有一个键就按住 BOOT 插拔 USB
烧录成功,但串口一个字都没有 CDCOnBoot 跟板子不匹配(坑 1) 有转接芯片 → 用默认;Type-C 直连 → 加 :CDCOnBoot=cdc。改完重新编译再烧
串口全是乱码 波特率不匹配 Serial.begin() 和读串口时的 baudrate 都必须是 115200
串口读出来是空的 板子还没启动完 读之前先 time.sleep(2) 等它启动
程序烧进去了但不干活 引脚接错了(坑 4) 查板子的引脚图,以 GPIO 编号为准,别信丝印
烧录后 USB 口认不出来了 程序占用了 GPIO18 / GPIO19 按住 BOOT 进下载模式重新烧一个不占用 USB 的程序
灯不亮,但烧录成功 接线错了,或代码里的引脚号跟实际接的不一致 核对 Signal 接的是哪根、代码里写的是几

十一、自测

单选题装 ESP32 支持包时,为什么建议加"国内镜像索引"而不是官方索引?
单选题用离线包装完环境之后,编译还需要联网吗?
单选题arduino-cli 提示"找不到命令",但你确定刚才装成功了。最可能是什么原因?
问答题你的板子插上电脑,电源灯亮着,但 arduino-cli board list 里一个端口都没有。列出你的排查顺序,并说明每一步在排除什么可能。
拓展为什么"官方索引能打开,但装包很慢"?这两件事为什么不是一回事?

这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。

提示:搜"索引文件 与 实际下载地址 的关系"。想一想:一张菜单能看,不代表上面写的每一家店都好找。

拓展编译工具链(交叉编译器)是什么?为什么嵌入式开发需要它?

这个问题课上不讲,留给你自己找答案——**问 AI 是最好的办法**。

提示:搜"交叉编译 为什么需要"、"RISC-V 工具链"。想一想:你的电脑是 x86 的,而 ESP32-C3 是 RISC-V 的,编译出来的程序能直接在电脑上跑吗?

十二、本节你要动手做的事

别看完就关掉,动手做完这七件事,这节课才算真的过。

  1. 确认你的线。 用万用表通断档测那根 Type-C 线的 GND、D+、D-。测出来是充电线就换掉。 顺手记下结论:我用的线,是/不是数据线。
  2. 确认你的板子类型。 看背面有没有转接芯片,插上电脑看设备管理器的变化,结论记下来:我的板子是"Type-C 直连"还是"带转接芯片"。这个结论决定了你要不要加 CDCOnBoot=cdc
  3. 装好 arduino-cli 并验证。arduino-cli version 能看到版本号;arduino-cli config dump 里能看到你加的那个索引地址;arduino-cli core list 里能看到 esp32:esp32
    • 如果在线装反复失败,别硬耗,直接用第四节的离线包(百度网盘,1.8GB)。这条路慢在下载,但装是一次性的,装完再也不用管网络。
  4. 记下两个关键信息:你的 ESP32-C3 的 FQBN(应该是 esp32:esp32:esp32c3),和你的板子出现在哪个 COM 口。
  5. 跑通 Blink。D:\dev\esp32-projects\blink\blink.ino 写那四行,编译、烧录,亲眼看到 LED 模块闪起来
  6. 让板子说话。Serial 那版代码烧进去,读串口,看到"灯亮""灯灭"一路滚出来。
  7. 把 AI 的排查顺序走一遍。 就算一切顺利,也照着第八节那张表,从第 1 步到第 8 步把命令敲一遍,看看每步的输出长什么样。因为等你哪天真的卡住了,你需要的是"知道正常长什么样"——只有见过正常的,才能一眼认出不正常的。

说句掏心窝子的话

这节课你熬下来了,我得跟你说几句。

装环境是这门课里最没意思的一节——没有灯闪,没有舵机转,全程对着黑乎乎的命令行。它枯燥、容易报错、而且一点都不好玩。

但恰恰是它,劝退了大部分人。我教过的学生里,倒在"装环境"这一步的,比倒在后面所有技术难题上的加起来还多。不是因为它难,是因为它没有即时反馈——你在前面熬两个小时,什么都看不见,很容易就想"算了吧"。

你熬过来了。

顺便说件事:这一节里我讲的那几个坑(串口不显示、驱动、BOOT 键、CDC 模式),不是你这次躲过去了就永远没事了。你以后换板子、换电脑、帮同学装,还会再撞上它们。但那时候你已经见过正常的输出了——这就是今天第七件事的价值。

下一节开始,我们就有东西看了。真的。