4. 串口参数配置实战:波特率、数据位、停止位、校验位、超时时间的配置与测试

串口通信的参数配置,说白了就是让两个设备约定好「怎么说话」。我刚开始做嵌入式那会儿,总觉得这些参数随便填就行,结果经常收到一堆乱码。后来才明白——收发双方的参数必须完全一致,差一点都不行。

这一节,咱们把五个核心参数掰开揉碎讲清楚。你跟着我走一遍,以后配置串口再也不会翻车。

4.1 波特率:通信的「节拍器」

波特率(Baud Rate)定义的是每秒传输多少个符号。在串口里,一个符号就是一个比特,所以波特率就等于比特率。

波特率(bps) 典型应用场景 优缺点
9600 工业仪表、GPS模块、老旧设备 稳定可靠,抗干扰强,但速度慢
115200 调试输出、传感器数据、WiFi模块 速度适中,兼容性好,最常用
921600 高速数据传输、固件升级 速度快,但线长超过1米容易丢包
3000000+ 芯片内部调试、短距离高速通信 极快,对硬件和线缆要求极高
我的习惯:调试阶段一律用115200。这个速率在大多数USB转串口芯片上表现最稳定,而且Python的serial库对这个速率支持最好。等产品定型了再根据实际需求调整。

配置波特率在Python里就一行代码:

import serial

ser = serial.Serial(
    port='COM3',
    baudrate=115200,   # 波特率
    timeout=1
)

嗯,这里要注意——波特率不是越高越好。我曾经在一个项目里为了追求速度,把波特率设到了2Mbps,结果线缆稍微长一点就开始丢数据。后来老老实实降到460800,问题全解决了。

4.2 数据位:一帧里装多少数据

数据位(Data Bits)决定每个字节实际传输多少位。常见的有7位和8位。

  • 8位数据位:最常用,能表示0-255的完整字节。ASCII字符、二进制数据都用这个。
  • 7位数据位:老式设备或特殊协议用,只能表示0-127。比如某些工业PLC还在用7位。
  • 5位、6位:基本绝迹了,只有极古老的设备才用。
避坑指南:我曾经接手过一个项目,设备一直发乱码。查了两天,最后发现设备用的是7位数据位,而我默认配了8位。你想想看,高位对不上,数据肯定全错。所以拿到新设备,第一件事就是确认数据位。

配置代码:

ser = serial.Serial(
    port='COM3',
    baudrate=115200,
    bytesize=serial.EIGHTBITS,  # 8位数据位
    timeout=1
)

4.3 停止位:帧与帧之间的「休止符」

停止位(Stop Bits)告诉接收方「这一帧结束了」。常见的有1位、1.5位和2位。

停止位 说明 使用场景
1位 标准配置,开销最小 绝大多数现代设备
1.5位 特殊定时要求 某些老式电机控制器
2位 额外冗余,更稳定 长距离通信、噪声环境

我个人习惯:能用1位就不用2位。多一位停止位虽然更稳,但传输效率会下降约10%。除非你的通信环境特别恶劣,否则1位完全够用。

ser = serial.Serial(
    port='COM3',
    baudrate=115200,
    bytesize=serial.EIGHTBITS,
    stopbits=serial.STOPBITS_ONE,  # 1位停止位
    timeout=1
)

4.4 校验位:数据完整性的「安检员」

校验位(Parity Bit)用来检测传输过程中有没有发生错误。说白了就是加一个额外的比特,让整个帧里1的个数是奇数还是偶数。

  • 无校验(N):不加校验位,效率最高。短距离、低噪声环境首选。
  • 奇校验(O):让1的总数为奇数。能检测出奇数个位翻转。
  • 偶校验(E):让1的总数为偶数。效果和奇校验一样,只是规则相反。
  • 标记校验(M):校验位固定为1。很少用。
  • 空格校验(S):校验位固定为0。也很少用。
实战建议:大多数场景用「无校验」就够了。如果通信环境有干扰,优先用偶校验——因为很多工业协议默认就是偶校验,兼容性更好。

配置代码:

ser = serial.Serial(
    port='COM3',
    baudrate=115200,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_NONE,   # 无校验
    stopbits=serial.STOPBITS_ONE,
    timeout=1
)

4.5 超时时间:别让程序死等

超时(Timeout)是串口编程里最容易忽略、也最容易出问题的参数。它决定了read()函数最多等多久。

超时设置 行为 适用场景
timeout=None 一直等,直到收到指定字节数 数据量确定、不会丢包的场景
timeout=0 非阻塞模式,立即返回 轮询读取、实时性要求高
timeout=N 最多等N秒,超时返回已收到的数据 最常用,兼顾实时性和可靠性
我曾经踩过的坑:有次写一个自动测试脚本,没设超时。结果设备突然掉线,程序卡在read()那里一动不动,整个测试流程全停了。从那以后,我所有串口程序都强制设超时,哪怕设个0.1秒也比不设强。

我的推荐配置:

ser = serial.Serial(
    port='COM3',
    baudrate=115200,
    bytesize=serial.EIGHTBITS,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    timeout=1  # 1秒超时,够用又不会卡死
)

4.6 完整配置与测试流程

下面我把所有参数串起来,写一个完整的配置和测试脚本。你直接复制就能用。

import serial
import time

def configure_serial(port, baudrate=115200):
    """配置串口参数并返回串口对象"""
    try:
        ser = serial.Serial(
            port=port,
            baudrate=baudrate,
            bytesize=serial.EIGHTBITS,
            parity=serial.PARITY_NONE,
            stopbits=serial.STOPBITS_ONE,
            timeout=1
        )
        print(f"[OK] 串口 {port} 已打开,参数:{baudrate} 8N1")
        return ser
    except serial.SerialException as e:
        print(f"[ERROR] 打开串口失败:{e}")
        return None

def test_communication(ser):
    """发送测试数据并检查回显"""
    if ser is None:
        return
    
    test_data = b"Hello UART!\n"
    ser.write(test_data)
    print(f"[TX] 发送:{test_data}")
    
    time.sleep(0.1)  # 等设备处理
    response = ser.read(ser.in_waiting)
    print(f"[RX] 收到:{response}")
    
    if response == test_data:
        print("[PASS] 回显测试通过")
    else:
        print("[FAIL] 回显测试失败,请检查参数")

if __name__ == "__main__":
    ser = configure_serial("COM3", 115200)
    test_communication(ser)
    if ser:
        ser.close()

4.7 参数配置知识图谱

下面这张图帮你理清五个参数之间的关系。你一看就明白:

串口参数配置知识图谱 串口通信参数 波特率 数据位 停止位 校验位 超时时间 关键原则: 1. 收发双方五个参数必须完全一致,否则通信失败 2. 超时时间只影响接收,不影响发送 3. 调试阶段建议用 115200 8N1 + 1秒超时,兼容性最好

4.8 常见问题排查清单

配置完串口发现通信不正常?别慌,按这个清单一步步查:

  1. 检查波特率:两边是不是一样?差1bps都不行。
  2. 检查数据位:都是8位吗?7位和8位混用必出乱码。
  3. 检查停止位:1位还是2位?对不上会丢帧。
  4. 检查校验位:无校验、奇校验还是偶校验?这个最容易忽略。
  5. 检查超时:是不是设了None导致程序卡死?
  6. 检查硬件连接:TX接RX了吗?地线接了吗?
我的调试三板斧:第一,用示波器看波形,波特率对不对一眼就知道。第二,用串口助手先手动发数据,排除代码问题。第三,把超时设成0.5秒,避免程序卡死。这三招帮我解决了90%的串口问题。