两块Arduino开发板之间的串口通信,是嵌入式系统中最基础却最实用的硬件对话方式。我在五年前的智能温室项目中第一次用到这个方案——当时需要主控板收集传感器数据,再转发给负责显示的副板。这种看似简单的技术,实际上能解决物联网设备中的关键问题:低成本实现分布式控制。
串口通信(UART)之所以成为Arduino开发者的首选,核心在于其硬件门槛极低。只需要三根线(TX、RX、GND)就能建立双向通道,通信速率从300bps到115200bps可调,完全能满足大多数传感器数据和控制指令的传输需求。相比I2C或SPI等协议,串口的优势在于:
最稳妥的连接方式是交叉连接TX/RX线,同时共地:
code复制Arduino A Arduino B
TX ----------- RX
RX ----------- TX
GND ----------- GND
重要提示:务必先断开电源再接线!我曾在带电状态下误接TX线导致一块Uno的串口芯片烧毁。共地线(GND)是保证信号电平基准一致的关键,这个细节新手最容易忽略。
不同型号Arduino的工作电压可能不同:
当5V板与3.3V板直连时,建议在5V板的TX端串联1kΩ电阻作为简单限流保护。更好的方案是使用电平转换模块(如TXB0108),这在长期运行的工业项目中尤为重要。
当板间距超过1米时,需要考虑:
发送端核心代码:
cpp复制void setup() {
Serial.begin(9600); // 初始化硬件串口
}
void loop() {
int sensorValue = analogRead(A0);
Serial.print("VOLT:"); // 添加数据头标识
Serial.println(sensorValue);
delay(100); // 控制发送频率
}
接收端处理逻辑:
cpp复制String inputString = ""; // 接收缓冲区
bool stringComplete = false;
void setup() {
Serial.begin(9600);
Serial1.begin(9600); // Mega等板卡可用额外串口
}
void loop() {
if (stringComplete) {
if(inputString.startsWith("VOLT:")) {
int value = inputString.substring(5).toInt();
// 数据处理逻辑...
}
inputString = "";
stringComplete = false;
}
}
void serialEvent1() { // 串口中断处理
while (Serial1.available()) {
char inChar = (char)Serial1.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
经过多个项目迭代,我总结出高效协议的关键:
cpp复制// 发送端
String data = "TMP23.5";
byte checksum = 0;
for (int i=0; i<data.length(); i++){
checksum += data[i];
}
Serial.println(data + "*" + String(checksum));
// 接收端校验逻辑...
在环境干扰大的场合,可以这样实现自动波特率同步:
cpp复制void autoBaudRate() {
long bauds[] = {9600, 19200, 38400, 57600, 115200};
for(int i=0; i<5; i++){
Serial1.begin(bauds[i]);
Serial1.write('?');
if(Serial1.read() == '!') break; // 收到应答则锁定波特率
}
}
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 接收乱码 | 波特率不匹配 | 检查双方Serial.begin()参数 |
| 数据丢失 | 缓冲区溢出 | 增加Serial.available()检查 |
| 通信不稳定 | 电源干扰 | 并联100μF电容在电源两端 |
| 只能单向通信 | 接线错误 | 确认TX/RX交叉连接 |
| 长距离传输失败 | 信号衰减 | 改用RS485或降低波特率 |
cpp复制// 在关键节点添加LED指示
digitalWrite(LED_BUILTIN, Serial.available() ? HIGH : LOW);
通过软件串口库(SoftwareSerial)可实现一主多从通信:
cpp复制#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX,TX
void setup() {
Serial.begin(9600);
mySerial.begin(9600);
}
// 轮询方式与多个从机通信
保留串口协议,替换物理线路为:
通过Python脚本实现Arduino与电脑的数据中转:
python复制import serial
ser = serial.Serial('COM3', 9600)
while True:
if ser.in_waiting:
data = ser.readline().decode().strip()
# 数据处理逻辑...
在最近的一个农业物联网项目中,我采用双Arduino+Python方案实现了环境数据采集→边缘计算→云端上报的全链路,其中关键正是稳定可靠的串口通信基础。