Arduino 上 `Serial.print` 很方便,但在 `loop` 里阻塞读或用 `delay` 等完整行,会拖死同时要扫按键、刷屏、控电机的任务。更稳妥的做法是 **非阻塞读 + 环形缓冲 + 简单状态机**。
### 推荐结构
- **中断或 `available()` 轮询** 把字节推进 Ring Buffer(注意关中断或用 volatile 保护索引)。
- **主循环状态机** 解析命令:如 WaitHeader → WaitLength → WaitPayload → WaitChecksum。
- **完整帧回调** 里再 `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);
}