AI 编程课
完整教案
自学课件
4 课 · 共 4/48

让板子开口说话 ——串口、波特率和你的第一个电脑软件

课时
待定
器材
ESP32-S3 触摸屏板 + USB 线
前置知识
配套代码
见项目 demo 目录

自学读本:跟着读、照着做,卡住就问 AI

你好,我是吴老师。

这份是给你自己读的——不用等我讲,你一段一段往下看,看到让你停下来的地方,就照着做一遍。看不懂的整段复制给 AI,加一句"请一次只解释一个概念,讲完问我一个小问题"。

读完之后,你应该能:说出 TX、RX 各管什么方向、为什么烧录前要关闭串口;解释波特率是什么,并说出本板"改了波特率却不乱码"的原因;让板子汇报按键、听懂你的命令;设计一套自己的命令表。

用时:基础实验 60–90 分钟;自制命令表与两个案例另留 30–40 分钟(可分两次做)。准备:板子、数据线、已经接入板卡 Skill 的 WorkBuddy、配套的"串口小助手"软件(双击就能运行的那个)。


一、前三课,板子一直很沉默

回头看看我们做过的东西:第 1 课灯会变色,第 2 课板子能感觉到按键,第 3 课整块屏幕能亮出一种颜色。

可是我有个问题:灯亮着的时候,你怎么知道板子认为它是亮的?程序跑到一半卡住了,你怎么知道它卡在哪一步?

以前我们只能靠"看结果"猜。今天给板子装一根"电话线",让它把心里想的说出来,也能听懂你说的话。这根线叫串口。今天做三件事:

  1. 弄明白串口是什么、波特率又是什么;
  2. 用你自己的小软件和板子对话;
  3. 让板子听懂你的命令:按按钮它汇报,你说"红色"它就亮红灯,你说"屏幕绿色"整屏变绿。

二、串口是什么:两条传送带,方向相反

先纠正一个容易搞错的地方:串口不是一条线,而是两条,各管一个方向。

  • TX(Transmit,发送):板子往外说。
  • RX(Receive,接收):别人往板子里说。

串口:两条方向相反的传送带

把它们想成两条并排的传送带:一条只往外运,一条只往里运——所以板子可以一边说一边听,不用像对讲机那样"说完请回答"。

但这个比喻少了真实串口的第三样东西:GND,共同的地线。两条传送带要"共地"才能对齐高度。没有共地,两边对"高"和"低"的理解不一样,说出来的话全是乱的。

还有一件重要的事:发送和接收要交叉连接——我这边的 TX 接你那边的 RX,我这边的 RX 接你那边的 TX。就像打电话,听筒要对着话筒;接反了,两边都在对着自己说。

我们这块板用的是 USB 串口:ESP32-S3 芯片自己有 USB 接口,插上数据线,电脑上就会出现一个"COM 口"。不用额外接线,串口已经在那儿了。

三、串口能帮我们做什么

三件事,这节课一件一件遇到:

用处例子
板子汇报自己启动时打印"我醒了",按键时打印"按钮已按下"——这些文字叫日志
你给板子下命令电脑上打"红色",板子收到就把灯点亮——这就是"遥控器"
出问题时找原因程序卡在哪一步?打印出来看一眼,比猜快得多

第三件以后你调试作品时会天天用到。

四、波特率:先说好一秒钟敲几下

现在认识今天最容易绕晕的词——波特率

串口线上只有"高"和"低"两种状态。要说话就得约定:**一个信号持续多久算一个?**两边必须一样快,否则我数成 3 下,你数成 5 下,听到的就不是同一句话。

波特率就是这个约定:**每秒钟传送多少个基本信号单元。**我们课上常用 115200,意思是一秒传 115200 个单元。

打个比方:两个人隔着墙敲管子,先约好"我一秒敲十下"。敲的人按这个节奏敲,听的人也按这个节奏数——听的人若按"一秒五下"数,听到的全是乱码。

比喻有个地方和真实硬件不一样:串口不是靠人敲,是靠两边各自的时钟;而且两边不需要分毫不差,一小段时间内差不多就行。

再算一笔账。传一个字节时,通常会额外带上"开始信号"和"结束信号",一个字节约占 10 个单元:

115200 ÷ 10 ≈ 11520 字节/秒

一秒约一万字——打印日志快得几乎感觉不到延迟;但以后要传图片,就得算时间了。

**关键点:板子程序和电脑软件必须设成同一个波特率。**板子上写 Serial.begin(115200),电脑上也选 115200。不过——我们这块板有个特别的地方,等下你会亲自发现。

五、认识你的新工具:串口小助手

这节课我们不一直借用 WorkBuddy 的串口看消息。我给你一个你自己的软件:它叫串口小助手,双击就能运行、不用安装。样子大概是:

┌──────────────────────────────────────────────┐
│  串口小助手                                   │
│  串口  [COM34      ▼]  [刷新]                │
│  波特率 [115200     ▼]                        │
│  [ 打开串口 ]                                 │
│  ┌────────────────────────────────────────┐  │
│  │ [12:30:01] 我醒了,我是第 4 课的板子   │  │
│  │ [12:30:03] 按钮已按下                  │  │
│  │              (接收区:板子说的话)     │  │
│  └────────────────────────────────────────┘  │
│  [ 清空 ]            [ ] 发送后加换行         │
│  [ 输入你要说的话 ______]  [ 发送 ]          │
│  常用命令:[红色] [绿色] [蓝色] [关闭]       │
└──────────────────────────────────────────────┘

五个区域要记住:

区域作用
串口下拉 + 刷新选板子现在在哪个 COM 口。烧录后端口会变,要按刷新
波特率下拉必须和板子一致,我们固定用 115200
打开/关闭串口连接和断开。烧录前一定要点"关闭串口"
接收区板子发来的文字,带时间,方便数秒
发送框 + 发送你发给板子的话。勾了"发送后加换行",板子才知道一句话说完了

为什么烧录前要关闭串口?

电脑上一个串口同时只能被一个程序占用。串口小助手连着时,WorkBuddy 就烧不进去;反过来也一样。

烧录时看到"端口被占用 / port is busy"?先回串口小助手点关闭串口,再让 AI 重新烧录。烧完后 COM 口号可能变了(比如 COM34 → COM17),按刷新重新选一次再打开。

这不是软件坏了,是规矩:一根电话线,一次只能一个人用。

第一次连接

先把串口跑起来:

请使用课程的 esp32s3-touchboard-hardware-dev Skill,
给触摸屏板写一个串口测试程序:
启动时用 115200 打开串口,打印一句"我醒了,我是第 4 课的板子",
然后每秒打印一次"我还活着,已经过了 N 秒",N 是实际秒数。
屏幕不用画复杂界面,保持清屏即可。
帮我新建程序并烧录,保留原来的示例。

烧录完(记得先关闭串口助手)按顺序做:打开串口小助手 → 点刷新 → 选检测到的 COM 口 → 波特率 115200 → 点"打开串口"。

看到了吗?接收区不停地冒出"我还活着"——板子在你不插手的情况下,一直主动说话。

如果看到一堆 ���� 或奇怪方块,多半是波特率不一致,或板子正在重启。把现象如实记下来,下面用得上。

六、动手实验

实验 1:波特率改错了,会怎么样?

**先猜再试。**把电脑上的波特率从 115200 改成 9600(板子程序不改),你猜会发生什么?

我改了什么我预测的现象我实际看到的现象
电脑改成 9600,板子仍是 115200自己填写实验后填写
电脑改回 115200自己填写实验后填写

操作顺序:关闭串口 → 波特率改 9600 → 打开串口 → 观察十秒 → 改回 115200。

结果可能是两种之一:

**情况一:变成乱码。**正好印证:两边数得不一样快,话就听不懂了。

**情况二:字还是好好的,一点没乱。**如果你看到的是这个——恭喜,你发现了一个更重要的问题。把这段话发给 AI:

我把电脑上的波特率改成了 9600,板子程序里还是 115200,
可是收到的字并没有乱码,仍然是正确的中文。
请结合我们这块板的资料解释:为什么波特率不一致却还能正常通信?
是不是这块板的串口和我想的不一样?
请用简单例子讲,讲完问我一个小问题,等我回答再继续。

答案大概是这样:这块 ESP32-S3 板用的是 USB CDC——"用 USB 假装出来的串口"。数据真正跑在 USB 线上,速度由 USB 协议自己决定;两边填的那个波特率数字,很多时候只是"记账用的标签",没有真的去控制时钟。

而如果你用另一块带独立 USB 转换芯片的板子,波特率就必须严格一致,乱设就乱码。

记住这个发现:**你从实验里看到的现象,比书本上的结论更可靠。**书上写"波特率必须一致",在我们的板上却不成立——不是书错了,是书上讲的是另一种串口。以后再遇到"照着做却和说的不一样",先别急着说自己做错了——记录现象,追问为什么。

实验 2:按下按钮,让板子自己汇报

请使用课程的 Skill,在刚才的程序上加一个功能:
板载 BOOT 按键(GPIO0)被按下时,
通过串口打印一行"按钮已按下",并把按下的次数也打印出来。
按键的处理要用消抖,一次按下只打印一次。
保留每秒一次的"我还活着",帮我修改并烧录。

记录:

我按了几次接收区出现几行"按钮已按下"两者一致吗
1 次自己填写自己填写
3 次自己填写自己填写
按住不放 3 秒自己填写自己填写

第三行是故意的。先猜,再试:按住不放,会打印一次还是很多次?

消抖做好了通常只算一次;如果程序写的是"只要按键是低电平就打印",三秒里会刷出几百上千行——板子一秒钟能检查几千次。真看到刷屏,你就亲眼看见了重复触发:把现象告诉 AI,请它解释"按下瞬间"和"按住期间"的区别。

顺便看数据方向:你按按钮 → ESP32-S3 检测 GPIO0 变低 → 程序决定汇报 → Serial.println() 把文字放进串口 → USB 线传到电脑 → 小助手接收区显示出来。这一整条路是板子 → 电脑

实验 3:你说"红色",灯就亮红

换方向:电脑 → 板子

请使用课程的 Skill,在刚才的程序上再加一个功能:
通过串口接收一行文字并识别:
收到"红色",让板载 RGB 灯亮红色;
收到"绿色",让灯亮绿色;
收到"蓝色",让灯亮蓝色;
收到"关闭",把灯熄灭。
亮度用较低值,各通道不超过 40。
收到不认识的内容,就打印"没听懂:xxx",xxx 是收到的原文。
帮我修改并烧录。

在发送框输入 红色,点发送(勾上"发送后加换行")。每填一行前先说出预测:

我发送的我预测灯会怎样灯实际怎样接收区回了什么
红色自己填写实验后填写实验后填写
绿色自己填写实验后填写实验后填写
蓝色自己填写实验后填写实验后填写
关闭自己填写实验后填写实验后填写
紫色自己填写实验后填写实验后填写
红色(不勾换行)自己填写实验后填写实验后填写

最后一行又是个坑。先猜:发送时没有换行,板子还认得"红色"吗?

很多程序的写法是"一直读到换行符才算一句话"。没换行,板子就一直等——所以你会发现:不勾换行灯没反应;等下一次发送别的内容时,前面那句才被一起处理掉。

把现象告诉 AI,请它解释"程序怎么知道一句话说完了"。这里认识本课新的两个代码名字(只认名字,不学语法):

  • Serial.available():问一句"有没有话进来?",回答来了几个字符;
  • Serial.readStringUntil('\n'):一直读,读到换行为止,把整句拿进来。

还有两个老朋友:Serial.begin(115200)(开局说好速度)、Serial.println("...")(发一行字,末尾带换行)。

你可能会问:那"红色"这两个汉字,怎么穿过串口?串口线上跑的其实都是数字——每个字按一套规则变成数字,这套规则叫编码,我们用 UTF-8。发送方和接收方用同一套规则,中文就对得上;规则不一致,就变成问号或乱码。

实验 4:你说"屏幕绿色",整块屏幕变绿

请使用课程的 Skill,再加一条命令:
收到"屏幕绿色",把整块屏幕填充成绿色;
收到"屏幕红色",填充成红色;
收到"屏幕蓝色",填充成蓝色;
收到"清屏",把屏幕刷成黑色。
同时在屏幕上方用中文显示当前收到的命令,方便我对照。
帮我修改并烧录。

停下来想一个问题:同样是"红色"两个字,为什么控制灯要说"红色",控制屏幕要说"屏幕红色"?

因为板子收到一句话后要判断它是给谁的——我们在话里加个前缀来区分。这就是最简单的命令格式。规则是你定的:用 灯:红色屏:绿色 也行,只要板子和你说好。

这引出本课最后、也最有用的东西——命令表

七、命令表:板子里的"如果……否则"

把板子里的逻辑写成中文步骤,它会越来越像一张"表格":

启动时:
    以 115200 打开串口                      对应动作:Serial.begin
    初始化板载 RGB 灯(GPIO42)
    初始化屏幕
    打印"我醒了"                            对应动作:Serial.println

不断重复(每一小圈做下面几件事):
    如果按键刚被按下,而且已经消抖:
        按下次数加 1
        打印"按钮已按下,第 N 次"

    如果串口有话进来:                      对应动作:Serial.available
        一直读到换行,取出一整句             对应动作:Serial.readStringUntil
        去掉句子首尾的空格和换行

        如果这句话是"红色":
            设置灯为红色并发送
        否则如果这句话是"绿色":
            设置灯为绿色并发送
        否则如果这句话是"屏幕绿色":
            整块屏幕填成绿色
        否则如果这句话是"关闭":
            熄灭灯
        否则:
            打印"没听懂:这句话"

    短暂停顿一下,然后回到"不断重复"

请做两件事:

第一,遮住"否则:打印没听懂"一整块。假如删掉它,你发送"紫色"会怎样?用上面的步骤解释,不要猜。

第二,找一找:哪几行是板子说给电脑听的?哪几行是电脑说给板子听的?

这一整块"如果……否则如果……否则",就是命令表。你以后做遥控器、做菜单、做语音控制,用的都是这个结构——只是收到的命令来源不同:今天是串口,以后可能是蓝牙、WiFi 或语音识别出来的文字。

八、轮到你设计一套自己的命令

先想清三件事,再填空:

  1. 你想控制?(灯、屏幕,还是两个一起?)
  2. 每个命令叫什么名字?(要短、好记、不容易打错)
  3. 收到不认识的命令时,板子该怎么办?
请帮我把串口命令改成我自己设计的一套,保留按键汇报功能:
命令 1:输入"____",让____做____
命令 2:输入"____",让____做____
命令 3:输入"____",让____做____
收到不认识的内容时,打印"可用的命令有:……",把全部命令列出来。
用较低亮度,帮我修改并烧录。

最后那句"把全部命令列出来"是我特意加的——为什么?因为过几天你会忘记自己定过什么命令。让板子自己告诉你,比写在纸上可靠。这叫帮助信息,所有好用的软件都有。

完成后只改一个条件再验证一次:比如把"红色"改名叫"红灯",其它不动。先预测,再运行。

九、进阶:两个小案例

案例一:把板子变成小计算机

请在串口命令里加一条"计算"功能:
我发送"calc 12+34",板子算出结果并打印"12+34 = 46";
我发送"calc 7*8",打印"7*8 = 56"。
先支持加、减、乘、除四种,除不尽时保留两位小数。
算不出来或者格式不对时,打印一句提示,告诉我正确的写法。
帮我修改并烧录。

试试 calc 10/3——结果的位数和你平时写的一样吗?再试试 calc 苹果+1。这个案例想让你看到:**串口收到的只是一串字符,是程序决定把它当命令还是当算式。**板子并不"理解"数学,它只是按我们写好的规则处理文字。

案例二:让板子记住状态

请给板子加一条"status"命令:
我发送"status",板子打印当前状态,包括:
开机到现在多少秒、按钮一共按了几次、
灯当前是什么颜色、屏幕当前是什么颜色。
要求这些数字来自程序里真实记录的变量,不能每次都写死同一个答案。
帮我修改并烧录。

验证方法:先按三次按钮再发 status,看它报的是不是 3;把灯设成蓝色再发一次,看颜色有没有跟着变。如果按了三次它却报 0——说明变量没在累加,这是一个真实的 bug,把现象告诉 AI 一起查。

关键词是状态:程序记住的东西。第 2 课按键改变状态,今天我们第一次把它"打印出来看"。以后做课程表、计分、倒计时,都是同一套思路。

十、板子没有回应?这样提问

遇到问题用这个模板,把空白换成真实记录:

我想让板子____,实际却是____。
我用的串口号是____,波特率是____,软件显示的连接状态是____。
我点发送的内容是:____。
接收区显示的是:____(完全空白就写"什么都没有")。
请帮我查原因,一次告诉我检查一件事,等我反馈再继续。

高频原因先自查:

现象先检查
接收区一片空白串口号选对了吗?烧录后端口会变,按刷新重选
收到一堆乱码方块波特率是否一致;板子是否正在重启
点发送没反应勾了"发送后加换行"吗?程序是不是在等换行符

**"灯没有亮"是观察,"程序没收到"是推测。**推测要用实验验证。

十一、自检小测

先自己想,再点开对答案。

1. TX 和 RX 各管什么方向?为什么需要 GND?

TX 是发送(板子往外说),RX 是接收(别人说给板子)。需要共地(GND),两边对"高/低"的理解才一致。

2. 波特率是什么?两边不一致通常会怎样?

波特率是每秒传送多少个基本信号单元。两边数得不一样快通常会产生乱码。但我们这块板是 USB CDC,波特率数字很多时候只是"记账标签",改成 9600 也不一定乱码——以实测为准。

3. 为什么烧录前要关闭串口小助手?

一个串口同时只能被一个程序占用。小助手开着,WorkBuddy 就烧不进去(报 port is busy)。烧录后 COM 口号可能变,要刷新重选。

4. Serial.println() 和 Serial.readStringUntil() 分别是干什么的?

println 是"说":往电脑发一行字(带换行)。readStringUntil 是"听":一直读到换行符,把一整句话取回来。

5. 命令表里"否则"那一块有什么用?删掉会怎样?

"否则"处理所有没列出来的内容——比如打印"没听懂"。删掉后,遇到不认识的命令,板子就什么都不做,你也搞不清它收到没有。

6. "红色"两个汉字在线上是以汉字形式跑的吗?

不是。线路上只有高低电平(数字),每个字按 UTF-8 编码变成一串数字传过去,接收方按同一套规则还原成汉字。

7. 关掉串口小助手,板子还在运行吗?打印的字去哪了?

板子照常运行,只是没人听。数据发出去没有接收方,就丢掉了——日志只有在你看着的时候才有意义。

十二、还想玩点什么

方向可以描述给 AI 的效果值得继续想
打字机电脑打一句话,屏幕显示出来中文太长一行放不下怎么办?
数据记录仪每秒把按键次数发到电脑,存成文件一小时后数据有多大?
摩斯电码练习器按键长短记成点和划,板子翻成字母多长算"长"?标准谁定?
简易聊天室两块板 TX/RX 交叉相连,互相收发不经过电脑,它们能直接说话吗?

想做"用语音控制灯"的同学,把想法记下来——语音识别出来是一串文字,把那串文字交给今天这套命令表,就是语音控制台了。

下一课回到屏幕:把整屏的"一片色"拆开,只点亮其中的一个点——坐标、画线、画方框、画圆,都要从那个小小的点开始。


本课的配套资源

本节配套的演示程序源码与可烧录固件,已整合到课程页面底部的「配套资源 · 在线烧录」区——插上你的 ESP32-S3 触摸屏板(Chrome / Edge 浏览器),点「在线烧录」即可直接写入,无需安装软件。

给 AI 的第一句话(每次新开对话都先说这句):

请使用课程的 esp32s3-touchboard-hardware-dev Skill,
我现在做第 4 课(串口),需要你帮我____。
改动前先说清依据的项目文件路径,烧录前先运行 arduino-cli board list 确认端口。

本节配套资源 · 在线烧录

查看全部固件 →

下列演示程序已编译为可烧录固件。把你的 ESP32-S3 触摸屏板 用 USB 接上电脑(需 Chrome / Edge 浏览器),点「在线烧录」即可直接写入,无需安装任何软件。

第 4 课 · 串口心跳
可烧录

启动打印「我醒了」,之后每秒打印「我还活着,已经过了 N 秒」。串口是板子和电脑说话的通道。

04 串口 入门
第 4 课 · 按键汇报
可烧录

按 BOOT 打印「按钮已按下,第 N 次」,按住不刷屏。GPIO0 边沿+消抖,串口回显。

04 串口 按键
第 4 课 · 命令控灯
可烧录

发「红色/绿色/蓝色/关闭」控制 RGB 灯,未知命令回显「没听懂:xxx」。命令解析走串口。

04 命令 LED
第 4 课 · 命令控屏
可烧录

发「屏幕红色/绿色/蓝色/清屏」填充整屏,屏幕上方显示收到的命令。fillScreen 配合串口。

04 命令 屏幕
第 4 课 · 计算器(案例一)
可烧录

发 calc 12+34 打印 12+34 = 46;除不尽保留两位小数。支持 + − * / 四则运算。

04 案例 计算
第 4 课 · 状态查询(案例二)
可烧录

发 status 打印开机秒数、按键次数、灯与屏幕当前颜色。数值必须来自真实变量。

04 案例 状态