
折腾过 Arduino 的朋友应该都有同感原版 IDE 虽然“能跑”但离“好用”差得实在有点远代码补全基本等于没有工程结构一复杂就乱成一团编译上传还经常莫名其妙卡住。所以这两年我陆陆续续把整套 Arduino 工作流迁到了 VS Code arduino-cli 上从 EV3 小车到 ESP32 网络服务器都没再用过传统 IDE。今天就把这套轻量化配置完整拆开讲一遍包括怎么装、怎么配、怎么用最后再把我踩了很久的串口中文乱码问题一次性解决掉。无论你是刚接触 Arduino 的新手还是已经在用 VS Code 写 C 语言、做 ESP32 开发的老手这篇都可以直接对照着操作。1. 为什么选择 VS Code arduino-cli1.1 传统 Arduino IDE 到底哪里不够用Arduino IDE 给人的最大感觉就是“单薄”。它的界面逻辑基本是模仿记事本打开一个 .ino 文件直接写写完了点上传仅此而已。早期版本连“打开多个文件”这个操作都要折腾半天更别说跳转函数定义、批量重命名、查看变量引用了这些基础功能它统统没有。真正让我忍无可忍的是两个点第一写稍大一点的工程时IDE 把所有 .ino 文件拼接成一个临时源文件来编译文件一多就分不清谁是谁报错信息也没有文件路径全靠猜第二IDE 对 Git 这种现代开发流程几乎是绝缘的代码写完想提交到仓库还得重新在 VS Code 里打开工程等于维护两套环境。还有个很现实的问题——版本更新太慢。Arduino 2.x 虽然比 1.8.6 好看不少但核心依然是那个“单文件 一键上传”的模型。而且它自带的库管理器经常下载速度感人安装一个库要等半天中间还容易失败。对于习惯用命令行装依赖、用任务系统构建项目的开发者来说这套 IDE 确实不太顺手。1.2 arduino-cli VS Code 的组合优势arduino-cli 是 Arduino 官方推出的命令行工具它把编译、烧录、库管理、板卡管理全部封装成了命令底层用的还是官方那套编译工具链所以兼容性不用担心。这套组合的优势很直接VS Code 管编辑arduino-cli 管编译烧录两者各司其职互不干扰。VS Code 本身不参与编译只负责提供编辑器、终端、任务系统和调试界面所以即使工程很大也不会卡。配置可复用、可提交到 Git。整个环境只需要一个 arduino-cli 配置文件和 VS Code 的 tasks.json换电脑后十分钟就能恢复完整开发环境再也不用花一晚上装 IDE。支持多板卡一键切换。通过不同的 fqbn 参数可以随心所欲地在 UNO、ESP32、STM32 之间切换不用像 IDE 那样每次在“开发板管理器”里翻半天。插件生态全部开放。VS Code 里的 AI 插件、Git 插件、代码格式化插件都能直接用配合 codex 这类工具做自动补全时体验比 IDE 好了不止一个量级。我自己的感受是这套组合最接近“用现代工具链做嵌入式开发”的正确姿势而且不需要为此多装任何重型软件整个 arduino-cli 程序才几十 MB。2. 环境准备安装 arduino-cli 并完成基础配置2.1 下载安装 arduino-cli 的两种方式安装 arduino-cli 总的来说有两种方式建议 Windows 用户优先试第一种。方式一用包管理器安装最简单Windows 10/11 自带 winget打开 PowerShell 直接跑winget install Arduino.arduino-climacOS 用户可以用 Homebrewbrew install arduino-cliLinux 用户也可以直接用 apt 或从官方 Releases 页面下二进制不过发行版仓库里的版本可能不是最新建议拉官方最新 release。方式二手动下载 zip 包打开 arduino-cli 的 GitHub Releases 页面下载对应系统架构的 zip 包。Windows 一般选Windows_64bit.zip解压后把arduino-cli.exe放到一个不含中文、不带空格的目录里比如D:\tools\arduino-cli\然后把目录加入 PATH。装完之后验证一下arduino-cli version如果能打印版本号说明安装成功。这里说一句安装目录尽量别放中文路径不然之后找生成文件或者配置路径时容易出现奇奇怪怪的编码问题。2.2 初始化配置与安装核心安装完成后需要先初始化配置文件arduino-cli config init默认情况下会生成arduino-cli.yaml配置文件放在用户目录下。如果你的开发板比较多第二行建议顺手把版型库索引更新一下arduino-cli core update-index然后装自己需要的板卡核心。比如用 Arduino UNO、Nano、Mega 这些 AVR 系列开发板就装arduino-cli core install arduino:avr如果用的是 ESP32就要先配置额外的板卡管理器地址然后再安装arduino-cli config add board_manager.additional_urls https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json arduino-cli core update-index arduino-cli core install esp32:esp32装完之后可以用arduino-cli core list检查当前已经安装的核心。整个过程都是命令化的比 IDE 里一页一页点菜单要快很多也方便在文档里记录。2.3 串口权限与板型检测Windows 上这一步相对简单重点是安装好 USB 转串口驱动。很多“找不到串口”的报错不是 arduino-cli 的问题而是驱动没装。UNO 板载的通常是 ATmega16U2识别为标准 USB 串口但很多国产开发板用的是 CH340 或 CP2102需要到芯片厂商官网下载驱动。Linux 下有一个权限问题很坑。默认串口设备归属于 dialout 组普通用户直接访问会报 Permission denied。解决办法是把当前用户加进 dialout 组sudo usermod -a -G dialout $USER操作完记得重新登录然后插入 USB 线用arduino-cli board list看看有没有识别到板子。正常输出会有一个列表显示端口号例如/dev/ttyUSB0Linux或COM3Windows同时会给出当前识别到的板卡 FQBN比如arduino:avr:uno。这个 FQBN 是编译上传时最重要的参数之一之后配置 tasks.json 全靠它。3. 打通 VS Codetasks.json 配置编译上传流程3.1 工程目录结构规划用 arduino-cli 管理工程时目录结构可以保持 Arduino 的标准形式也就是一个工程对应一个文件夹内部包含一个同名.ino文件。D:\projects\smart_car\ ├── smart_car.ino ├── .vscode\ │ └── tasks.json ├── lib\ │ └── (可选放第三方库) └── build\ └── (arduino-cli 编译输出目录)build 目录是 arduino-cli 生成的用于存放编译产物一般不需要手动创建。如果不设置--build-path参数arduino-cli 会在系统临时目录下生成构建文件我个人的习惯是把 build 目录固定到工程目录下方便 debug 时查找生成的 hex 文件。3.2 tasks.json 编写与参数逐行解释VS Code 的任务系统是整个工作流的核心。它允许我们预定义好“编译”“上传”等指令然后在编辑器里按快捷键直接执行不需要每次手动敲命令行。我的工程里.vscode/tasks.json长这样{ version: 2.0.0, tasks: [ { label: arduino-compile, type: shell, command: arduino-cli compile, args: [ --fqbn, arduino:avr:uno, --build-path, build, . ], group: build, problemMatcher: [] }, { label: arduino-upload, type: shell, command: arduino-cli upload, args: [ --fqbn, arduino:avr:uno, --port, COM3, . ], group: build, dependsOn: [ arduino-compile ] } ] }这里逐项解释一下label是在任务列表中显示的任务名可以随便取。command是实际执行的命令这里指定arduino-cli compile或arduino-cli upload。args是命令参数。--fqbn指定完整板卡标识符--build-path指定编译输出目录最后的.表示编译当前目录下的工程。group设为build后可以直接用CtrlShiftB触发编译任务体验和 IDE 里的“一键编译”类似。dependsOn让上传任务先自动执行编译任务避免忘记编译直接上传旧固件。这里有个容易踩的坑上传参数里的--port不是固定的。Windows 下串口号可能因为插入的 USB 口不同而改变比如今天插前面板是 COM3明天插后面板变成 COM5。如果上传时报错找不到串口先跑arduino-cli board list确认当前端口再改 tasks.json 里的参数。3.3 编译、上传的实际执行与结果判读配置好 tasks.json 后在 VS Code 里打开工程按CtrlShiftB触发编译任务这时候底部会弹出终端并开始执行命令。我第一次跑的时候不太懂编译日志怎么看后来发现重点看几行就可以了。编译链接完之后会打印 hex 文件路径和烧录的 Flash 大小比如Sketch uses 4568 bytes (13%) of program storage space. Maximum is 32256 bytes.看到这行说明编译成功刷进去的固件有多大、空间还剩多少一目了然。上传的时候会看到类似Writing at 0x...的输出因为 Arduino 是通过串口把固件一个扇区一个扇区写进 Flash所以会有多条写记录。最后出现Hash of data verified或Upload complete之类的提示就说明烧录完成板子上的程序已经更新了。实际操作中还有个小技巧可以在 tasks.json 里顺便定义一个“打开串口监视器”的任务用 VS Code 的串口终端扩展实现这样编译、上传、看串口输出全在一个环境里闭环。4. 串口乱码问题根因与解决方案4.1 先分清“乱码”的类型Arduino 的串口输出乱码是我见过最多的问题但在动手修之前建议先判断到底是哪种乱码波特率不匹配代码里是Serial.begin(115200)终端打开时选成了 9600输出就是一堆不可读的符号。换行符不一致终端设置了No line ending但代码输出的是\n显示时所有内容挤在一起看起来像乱码。终端编码不对这是中文乱码的最常见原因。考虑到 Arduino 串口输出的字节流本身只有 8 位它在硬件上不区分什么“编码格式”真正乱码是发生在终端解析字节流时用错了码表。搞清楚类型再处理不然很容易白忙一场。比如我早期遇到中文乱码第一反应是改波特率改来改去发现没用最后才发现是编码问题。4.2 Windows 下中文乱码的处理路径先说结论在 Windows 上Arduino IDE 自带的串口监视器默认按 GBK 解码串口数据而 VS Code 或 arduino-cli 环境下很多串口终端默认按 UTF-8 解码。Arduino 代码里的中文字符串在编译时通常以 UTF-8 字节序列存放比如Serial.println(你好)最终在串口上输出的是E4 BD A0 E5 A5 BD这一串 UTF-8 字节。Windows 终端如果按 GBK 解码E4 BD A0解析出来的就是“浣犲ソ”这种完全看不懂的符号。找到根因之后解决方案很清晰方案一换一个支持 UTF-8 解码的串口终端。比如 VS Code 里安装Serial Monitor扩展它会按 UTF-8 解码串口数据这样代码里直接Serial.println(你好)就能正常显示。PuTTY 也可以只要会话配置里把 Transmission 的编码设为 UTF-8。方案二如果必须在传统 Windows 串口终端比如 IDE 自带监视器、SecureCRT 等里查看那就改代码。最简单的做法是不输出中文用英文或拼音替代。仔细想想其实工程类日志用英文才是主流习惯避免编码问题带来的麻烦。方案三写一个 UTF-8 转 GBK 的小函数在代码里预先转换。这个方案适合那些必须输出中文、又必须在 Windows 老终端里看的场景。我测试过一段可用代码void utf8ToGbk(String s) { // 这个函数需要配合串口输出内部将UTF-8字节流转为GBK输出 // 更稳妥的方式是直接使用一个开源的U8g2或相关转码库 // 简单场景下也可以先取到UTF-8字符串并逐字节判定。 }这个函数实现有点绕而且不同的 Arduino 核心自带内存和 ROM 有限直接转码会吃不少资源。所以我的建议是能用英文尽量不要碰中文实在要中文优先考虑前端工具转码比如先让板子输出 UTF-8 字节然后再用 Python 脚本读取串口数据并解码这样最灵活且不占用单片机资源。4.3 嵌入式日志的通用建议关于串口日志有一个非常实用的通用建议统一波特率统一编码统一换行符。我现在的做法是所有工程代码里Serial.begin(115200)所有终端监视器统一设 115200换行符设为 LF。这样一来不管换到什么终端软件输出格式都是稳定的排查问题的时候不会因为环境差异而浪费时间。另外如果你做的是 ESP32 这类内存比较大的开发板可以直接用带颜色高亮的串口终端插件日志加个时间戳调试体验又会好不少。日志内容里尽量只保留有效数据不要刷屏式地打印无意义字符这在嵌入式开发里算是最容易被忽视但又最影响效率的一条。5. 常见问题与排查技巧实录5.1 上传错误“找不到串口”怎么办上传时报No such file or directory或者Failed to open the port是最常见的。排查顺序我建议这样走先确认板子和电脑的连接状态换一根数据线。注意有些便宜的线只能供电不能传数据这种线连上去灯是亮的但系统识别不到串口。用arduino-cli board list看端口号。如果这里能看到说明驱动没问题问题是烧录时端口号填错了。如果板子是 CH340 芯片去官网重装驱动。Windows 系统重装驱动后要重新拔插 USB 线。确认串口号范围。Windows 下如果串口号大于 COM9部分程序会兼容不佳可以在设备管理器里把端口改成 COM3 这种短端口号。还有个特别容易忽略的问题同时打开了 Arduino IDE 或别的串口监视器把串口占用了。关闭所有其他串口调试工具再试一次基本就能解决。5.2 编译报错“找不到头文件/库”用 arduino-cli 开发时很多人第一次添加第三方库会犯迷糊因为 IDE 里是图形化安装但在命令行下需要手动执行arduino-cli lib search DHT sensor library arduino-cli lib install DHT sensor library安装之后用arduino-cli lib list查看当前库列表确认库路径是否在 arduino-cli 管理的目录下。如果项目里用到的是自己写的头文件放在工程目录的lib子目录下编译时用--libraries参数指定路径或者直接把头文件放到 .ino 同目录下。VS Code 有时候会因为找不到头文件标红这是 IntelliSense 的包含路径没配置好在.vscode/c_cpp_properties.json里把 arduino-cli 的库目录加进去标红就会消失但实际编译不受影响。5.3 多板卡切换与开发提速技巧如果你手里同时有 UNO 和 ESP32每次切换板卡都要改 tasks.json 里的 fqbn 参数很麻烦。我的做法是把每个板卡单独建一个任务比如arduino-compile-uno、arduino-upload-uno、arduino-compile-esp32、arduino-upload-esp32复用同一套命令模板只改参数。另外配合 Git 做工程版本管理的时候建议把 build 目录加入.gitignore避免提交大量编译中间文件。再配合 VS Code 的 Git 插件和 AI 插件日常改代码的效率比在 IDE 里高很多。多板卡项目里我经常用arduino-cli board listall查看所有支持的板卡型号命令会列出每个板卡对应的 FQBN比如 ESP32 Dev Module 的 FQBN 是esp32:esp32:esp32。把这串字符记下来以后写配置就是复制粘贴的事。最后分享点实际体会我用这套方案做 Arduino 开发大概有大半年了踩过的坑几乎都集中在串口环节。一个比较深的体会是不要盲目追求在终端里显示中文尤其在嵌入式日志这个场景下用英文或拼音作为日志语言是最省力的。如果你真要在 Windows 下显示中文优先选支持 UTF-8 的终端工具然后统一波特率和换行符这样配合起来才能做到一劳永逸。另一个小技巧是把 tasks.json 配置好后一定记得提交到 Git 仓库一次这样换个电脑或者重装系统只需要装好 arduino-cli、拉一下仓库整个开发环境就回来了省掉的重复配置时间远超最开始的搭建成本。