串口通信
让 Arduino 与电脑对话:打印调试信息、接收命令、用绘图器看波形,以及用软串口接入更多设备。
让 Arduino 与电脑对话:打印调试信息、接收命令、用绘图器看波形,以及用软串口接入更多设备。
while(!Serial); 等待串口就绪(仅部分板如 Leonardo 需要)。print() 把数据转成人类可读文本发出(数字 65 发成字符 "65");println() 同 print 但末尾加换行;write() 发原始字节(把 65 发成一个字节 0x41=字符 'A')。调试打印用 print/println,传二进制协议用 write。available() 返回接收缓冲区里还有多少字节没读(>0 说明有数据来了);read() 取出并移除一个字节,无数据时返回 -1。接收数据的标准套路:if (Serial.available()) { char c = Serial.read(); ... }。Serial.println(数值) 输出的数字实时绘成折线图,多个用逗号/空格分隔的值会画成多条线。观察传感器波形、调 PID、看噪声时极其直观。注意:绘图器只认纯数字,混入文字会出错。串口打印是 Arduino 世界的"printf 调试法"——没有屏幕时,靠它了解程序在干什么。
// 每秒打印一次计数和一句话 int count = 0; void setup() { Serial.begin(9600); // 启动串口,波特率 9600 Serial.println("Arduino 已启动"); } void loop() { count++; Serial.print("第 "); // print 不换行 Serial.print(count); Serial.println(" 次循环"); // println 换行 delay(1000); }
上传后,点 IDE 右上角放大镜图标(或菜单 工具→串口监视器)。关键:把监视器右下角的波特率下拉框也调成 9600,与代码里的 Serial.begin(9600) 一致,否则显示乱码。每次打开监视器 Uno 会自动复位、程序从头运行。
反过来,电脑也能给 Arduino 发指令。下例:在监视器输入 1 开灯、0 关灯。
// 串口收命令控制 LED:发 '1' 开、'0' 关 const int ledPin = 13; void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); Serial.println("发 1 开灯,发 0 关灯"); } void loop() { // 缓冲区里有数据才读 if (Serial.available() > 0) { char cmd = Serial.read(); // 读一个字符 if (cmd == '1') { digitalWrite(ledPin, HIGH); Serial.println("LED 已开"); } else if (cmd == '0') { digitalWrite(ledPin, LOW); Serial.println("LED 已关"); } } }
从串口读来的是 字符。用户敲的 "1" 是字符 '1'(ASCII 值 49),不是整数 1。所以判断要写 cmd == '1'。若要把输入的一串数字转成整数,用 Serial.parseInt();读整行文本用 Serial.readStringUntil('\n')。别忘了把监视器的行尾设置调成"换行符(NL)"配合 readStringUntil。
// 读一整行文本命令,例如输入 "led on" void setup() { Serial.begin(9600); } void loop() { if (Serial.available()) { // 读到换行符为止,得到一整行 String line = Serial.readStringUntil('\n'); line.trim(); // 去掉首尾空白和回车 if (line == "led on") { digitalWrite(13, HIGH); } else if (line == "led off") { digitalWrite(13, LOW); } else { Serial.print("未知命令: "); Serial.println(line); } } }
把电位器接 A0,打印读数,用绘图器观察旋钮变化的曲线:
// 供串口绘图器用:只 println 纯数字 void setup() { Serial.begin(9600); } void loop() { int v = analogRead(A0); Serial.println(v); // 绘图器会把它画成折线 delay(50); // 多条曲线:用逗号分隔多个值 // Serial.print(v1); Serial.print(","); Serial.println(v2); }
同一份 println 输出,串口监视器显示成文字数字流,绘图器(工具→串口绘图器)画成折线图。二者不能同时打开(都占用串口)。绘图器只接受数字;如果你的输出里混了 "raw=" 这类文字,绘图会报错或画不出——给绘图器的代码要输出纯数字。
Uno 的硬件串口被 USB 占着,想同时连蓝牙(如 HC-05)又想用监视器调试,就用软串口把 D10/D11 变成第二个串口。
#include <SoftwareSerial.h> // 软串口:RX=D10, TX=D11(接蓝牙模块时交叉连:模块 TX→D10, 模块 RX→D11) SoftwareSerial btSerial(10, 11); void setup() { Serial.begin(9600); // 硬串口:和电脑调试 btSerial.begin(9600); // 软串口:和蓝牙模块 Serial.println("软串口就绪"); } void loop() { // 蓝牙 → 转发到电脑监视器 if (btSerial.available()) { Serial.write(btSerial.read()); } // 电脑 → 转发到蓝牙 if (Serial.available()) { btSerial.write(Serial.read()); } }
串口接线口诀:我的 TX 接你的 RX(交叉)。发送脚连对方接收脚才能通。另外 5V 的 Uno 直连 3.3V 模块的 RX 可能损坏模块,需用电阻分压或电平转换。软串口在 57600 以上波特率容易丢数据,蓝牙模块建议设 9600。
串口(UART)是最基础的通信方式,只需 TX/RX/GND 三线,数据一位位串行传输。收发双方波特率必须一致(常用 9600、115200),否则乱码——这是新手第一大坑,记得把串口监视器右下角的波特率也调成和 Serial.begin() 相同。发送用 print(转文本)、println(加换行)、write(发原始字节);接收标准套路是 if(Serial.available()) { c = Serial.read(); },注意读到的是字符('1' 是 ASCII 49 而非整数 1),读整数用 parseInt()、读整行用 readStringUntil('\n')。串口绘图器能把纯数字输出实时画成折线,适合看波形,但不能混文字、不能与监视器同开。Uno 只有一个硬串口(被 USB 占用),要再接蓝牙/GPS 用 SoftwareSerial 把普通引脚模拟成串口(高波特率不稳)。接线口诀:TX 接对方 RX 交叉连,5V 与 3.3V 之间要做电平匹配。