串口通信的自我理解和用法
一、什么是串口通信?
串口通信(Serial Communication),简单理解就是数据通过串口数据线一位一位地按顺序发送和接收的通信方式。就像排队过独木桥,同一时间只能过一个人,但只要桥够长、速度够快,依然能高效传输信息。
与之相对的是并口通信——数据多位同时传输,像多车道马路,但线材成本高、距离远了容易互相干扰,所以现在除了特定场景,串口反而用得更广泛。
我的核心理解
- 串行 = 逐位传输,节省物理线路,适合远距离
- 全双工 / 半双工 / 单工:
- 全双工:双方可以同时说话(比如打电话)
- 半双工:同一时间只能一方说(比如对讲机)
- 单工:只能单向传(比如广播)
- 串口最常见的是全双工,发和收各走一条线,互不干扰
二、串口通信的关键参数
双方要想正常对话,必须约定好一套"规则",否则你说你的我说我的,谁也听不懂。这套规则就是串口参数。
1. 波特率(Baud Rate)
- 含义:每秒传输的码元个数,可以粗略理解为每秒传多少位数据
- 常见值:9600、115200、38400、19200、57600
- 最常用:9600 和 115200
- ⚠️ 收发双方波特率必须完全一致,否则数据全是乱码
2. 数据位(Data Bits)
- 含义:一个字节数据占几位
- 常见值:5、6、7、8
- 最常用:8位,刚好对应一个字节
3. 停止位(Stop Bits)
- 含义:表示一个数据包结束的标志位
- 常见值:1、1.5、2
- 最常用:1位
4. 校验位(Parity)
- 含义:简单的错误检测机制
- 常见值:
- None(无校验,最常用)
- Odd(奇校验)
- Even(偶校验)
- 作用:通过额外一位来检查数据传输过程中有没有出错
常用组合速记
最通用配置:波特率 9600,数据位 8,停止位 1,无校验
简写:9600-8-N-1
高速常用配置:115200-8-N-1
三、常见的串口物理接口
很多人容易把"串口"和"RS-232"划等号,其实不对。串口是一种通信方式,RS-232、TTL、RS-485 是不同的电气标准和物理接口。
1. TTL 电平串口
- 电平标准:0V 代表 0,3.3V 或 5V 代表 1
- 特点:芯片直接输出的电平,单片机上最常见
- 连线:TX(发) → RX(收),RX(收) → TX(发),GND 共地
2. RS-232 串口
- 电平标准:正负电平,+3~+15V 代表 0,-3~-15V 代表 1
- 特点:抗干扰比 TTL 强,传输距离更远(几十米)
- 接口:经典的 DB9 九针接口,老电脑上常见
- 注意:TTL 和 RS-232 电平不兼容,需要 MAX232 之类的转换芯片
3. RS-485 串口
- 电平标准:差分信号,用 A、B 两根线的电压差表示 0 和 1
- 特点:抗干扰极强,传输距离可达上千米,支持多设备组网
- 常用场景:工业现场、楼宇控制、长距离通信
4. USB 转串口
- 现在的电脑基本没有原生串口了,都是用 USB 转 TTL / USB 转 RS-232 模块
- 常见芯片:CH340、CP2102、PL2303
- 使用方法:装驱动 → 插上电脑 → 在设备管理器里看串口号
四、串口是怎么工作的?
1. 物理连线(以 TTL 为例)
设备A 设备B
TX ────────→ RX
RX ←──────── TX
GND ───────── GND

- 交叉连接:A 的发接 B 的收,A 的收接 B 的发
- 必须共地:GND 一定要连,否则电平参考点不一致,数据会乱
2. 数据传输过程
- 空闲状态:线路保持高电平
- 起始位:拉低 1 位,告诉对方"我要开始发数据了"
- 数据位:逐位发出 5~8 位数据(低位先发)
- 校验位(可选):发校验位用于检错
- 停止位:拉高 1~2 位,表示"这包发完了"
- 回到空闲,等待下一包
一个完整的数据帧结构:
[起始位] + [数据位] + [校验位(可选)] + [停止位]
五、常用调试工具
1. 电脑端串口助手
- Windows:串口调试助手、XCOM、SecureCRT、Putty
- Mac/Linux:minicom、screen、picocom
- 功能:打开串口、收发数据、十六进制显示、定时发送
2. 使用步骤
- 把 USB 转串口模块插到电脑
- 安装对应驱动(CH340 / CP2102)
- 打开串口助手,选择串口号
- 设置波特率、数据位、停止位、校验位
- 打开串口,就可以收发数据了
六、编程实战:Python 操作串口
Python 用 pyserial 库操作串口非常简单,适合快速做原型和工具。
1. 安装库
pip install pyserial
2. 最简示例:发送和接收
import serial
import time
# 打开串口
ser = serial.Serial(
port='COM3', # Windows 是 COMx,Linux/Mac 是 /dev/ttyUSB0 之类
baudrate=115200, # 波特率
bytesize=8, # 数据位
parity='N', # 校验位 N-无 O-奇 E-偶
stopbits=1, # 停止位
timeout=1 # 读超时,单位秒
)
# 检查是否成功打开
if ser.is_open:
print("串口打开成功!")
# 发送数据(字符串转字节)
ser.write(b"Hello Serial!\n")
# 读取数据
time.sleep(0.1) # 等一下数据过来
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting)
print("收到:", data.decode('utf-8'))
# 关闭串口
ser.close()
3. 持续监听示例
import serial
import threading
def read_loop(ser):
while True:
if ser.in_waiting:
data = ser.readline()
print("收到:", data.decode('utf-8', errors='ignore'))
ser = serial.Serial('COM3', 115200, timeout=1)
t = threading.Thread(target=read_loop, args=(ser,), daemon=True)
t.start()
while True:
msg = input("输入要发送的内容:")
ser.write((msg + '\n').encode('utf-8'))
七、编程实战:C 语言操作串口(Linux)
在嵌入式/Linux 开发中,串口本质上是一个设备文件,通过文件操作 + termios 配置来使用。
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
int main() {
int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
if (fd < 0) {
perror("打开串口失败");
return -1;
}
struct termios opt;
tcgetattr(fd, &opt);
// 设置波特率 115200
cfsetispeed(&opt, B115200);
cfsetospeed(&opt, B115200);
// 8位数据,无校验,1停止位
opt.c_cflag &= ~PARENB; // 无校验
opt.c_cflag &= ~CSTOPB; // 1停止位
opt.c_cflag &= ~CSIZE;
opt.c_cflag |= CS8; // 8数据位
tcsetattr(fd, TCSANOW, &opt);
// 发送数据
char buf[] = "Hello from C!\n";
write(fd, buf, strlen(buf));
// 读取数据
char recv[128];
int n = read(fd, recv, sizeof(recv)-1);
if (n > 0) {
recv[n] = '\0';
printf("收到: %s\n", recv);
}
close(fd);
return 0;
}
八、常见问题与排查思路
1. 收不到数据?
- 检查 TX/RX 是不是接反了
- 检查 GND 有没有共地
- 确认两边波特率、数据位等参数完全一致
- 确认串口选择正确,没有被其他程序占用
2. 收到的全是乱码?
- 99% 的情况是波特率不匹配
- 其次可能是数据位、校验位、停止位设置不一致
- 也可能是编码问题(发送和接收编码不同)
3. 数据偶尔出错?
- 距离太长,信号衰减
- 周围有强电磁干扰
- 波特率太高,硬件跟不上
- 没有共地或者地线接触不良
4. 提示找不到串口?
- 驱动没装好
- USB 线有问题(有些线只能充电不能传数据)
- 串口芯片坏了
九、实际应用场景
- 单片机调试:STM32、Arduino 等通过串口打印日志
- 传感器数据读取:GPS、蓝牙模块、WiFi 模块大多用串口通信
- 工业控制:PLC、变频器、仪表通过 RS-485 通信
- 固件烧录:很多芯片通过串口下载程序
- 设备间通信:两个板子之间简单的数据交互
十、学习建议
- 先上手再深入:买个 USB 转 TTL 模块,用串口助手自发自收(TX 接 RX),先感受一下数据是怎么跑的
- 理解帧结构:用逻辑分析仪抓一下波形,直观看到起始位、数据位、停止位
- 动手写代码:从 Python 开始,再过渡到 C 语言,自己实现收发逻辑
- 踩坑中成长:乱码、丢数据、接反线都是必经之路,遇到问题按排查思路一步步来
怕什么真理无穷,进一步有进一步的欢愉
本文来自博客园,作者:开源xiaotang,转载请注明原文链接:https://www.cnblogs.com/xiaotangBlog/p/22153510

浙公网安备 33010602011771号