Arduino 上 Serial.print 很方便,但在 loop 里阻塞读或用 delay 等完整行,会拖死同时要扫按键、刷屏、控电机的任务。更稳妥的做法是 非阻塞读 + 环形缓冲 + 简单状态机。
推荐结构
1. 中断或 `available()` 轮询 把字节推进 Ring Buffer(注意关中断或用 volatile 保护索引)。
2. 主循环状态机 解析命令:如 WaitHeader → WaitLength → WaitPayload → WaitChecksum。
3. 完整帧回调 里再 switch(cmd) 执行业务,避免在收中断里做重逻辑。
行协议示例思路
若设备以 \n 结尾文本命令:缓冲追加字节,遇到 \n 取出一行 trim 后处理;缓冲超上限则丢弃防溢出。二进制协议则用长度域或固定帧长,并做超时清状态,防止半包卡死。
与上位机联调
- 波特率、8N1 与助手一致。
- 上位机可用「逐行发送」或预设按钮测状态机分支。
- 打开 HEX 监视,确认没有多余的 \r。
- 性能不够时再上 DMA/双缓冲;多数 Uno 级项目状态机已够用。
把串口接收从「print 调试」升级到「非阻塞协议解析」,是 Arduino 项目从玩具走向可长期跑现场的关键一步。
String inputBuffer = "";
void setup() {
Serial.begin(115200);
}
void loop() {
while (Serial.available() > 0) {
char inChar = (char)Serial.read();
if (inChar == '\\n') {
// 捕获到帧尾,开始解析
processCommand(inputBuffer);
inputBuffer = ""; // 清空缓冲区
} else if (inChar != '\\r') {
inputBuffer += inChar; // 累加合法字节
}
}
// 执行其他无延迟传感器监测任务...
}
void processCommand(String cmd) {
if (cmd == "LED_ON") digitalWrite(13, HIGH);
else if (cmd == "LED_OFF") digitalWrite(13, LOW);
}