← 返回博客列表

一、什么是串口通信

串口通信(Serial Communication)是指数据一位一位地按顺序传输的通信方式。与之相对的是并行通信,多位数据同时通过多根线传输。

串口是嵌入式开发中最基础、最常用的通信接口。从 Arduino 的 Serial.print(),到工业 PLC 的 Modbus,再到你电脑曾经的 COM 口,底层都是串口通信。

串口通信:数据一位一位排队传输 发送方 接收方 一根数据线 b0 b1 b2 b3 b4 b5 b6 b7 t1 t2 t3 t4 t5 t6 t7 t8 一个字节 0xB5 = 10110101 被拆成 8 个时间片依次发送 只需 1 根数据线 + 1 根地线 = 2 线即可通信
串口通信原理:数据按位顺序传输
串口通信的三层结构
① 协议层:UART(帧格式、波特率约定)
② 电气层:TTL / RS-232 / RS-485 / RS-422(电平标准)
③ 应用层:Modbus / AT 指令 / 自定义协议
同一个 UART 协议,搭不同电气层 = 不同串口标准。这是理解串口的关键。

二、串行 vs 并行:为什么串口赢了

早期计算机用并行口(LPT 打印口、IDE 硬盘)因为看起来"8 根线同时传 8 位 = 8 倍速度"。但并行最终被串行取代,原因有三:

并行 vs 串行 并行传输 发 收 8 根线同时传 8 位 ✗ 线间串扰(8根线互相干扰) ✗ 难以提升频率(信号偏移) ✗ 线多成本高、接口大 ✗ 同步困难(8 根线到达时间不一) ✗ 距离短(线间电容衰减快) → 已淘汰:LPT/IDE/SCSI 并口 串行传输 发 收 1 根线逐位传 ✓ 无串扰(差分线自抗扰) ✓ 频率可极高(USB 3.0 = 5Gbps) ✓ 线少成本低、接口小 ✓ 距离远(RS-485 = 1.2km) ✓ 无信号偏移问题 → 主流:USB/SATA/以太网/串口
串行通信为什么取代了并行
串口赢的三个核心原因
① 线少 → 串扰小:1~2 根线没有线间干扰
② 差分 → 抗扰强:RS-485/USB 用差分信号,不怕共模噪声
③ 频率可拉满:不用等 8 根线同步到达,单线可跑极高频率

三、通信三要素:方向、时钟、电平

3.1 方向:单工 / 半双工 / 全双工

通信方向:单工 / 半双工 / 全双工 单工 Simplex A B 单向,如广播、红外遥控 一根线,A 只发,B 只收 半双工 Half-Duplex A B 双向但不能同时,如 RS-485 一根线分时复用,轮流收发 全双工 Full-Duplex A B 双向且同时,如 RS-232 两根线,TX 发 + RX 收
三种通信方向模式

3.2 时钟:同步 vs 异步

同步 vs 异步通信 异步通信(UART) 约定波特率,各自计时 起始位同步 + 内部时钟采样 无需时钟线,只需 TX+RX+GND 优点:线少;缺点:波特率必须一致 代表:UART/RS-232/RS-485 同步通信(SPI/I2C) 共用时钟线,沿时钟沿采样 SCK 时钟线 + 数据线 无波特率约定问题,跟随时钟 优点:速度快;缺点:需额外时钟线 代表:SPI/I2C/USB
同步与异步通信的本质区别

3.3 电平:TTL / RS-232 / RS-485 / RS-422

这是串口种类最多的维度。同一个 UART 协议,配上不同电平标准,就变成了不同"串口":

电平标准逻辑 1逻辑 0传输方式典型电压
TTL高电平低电平单端0V / 3.3V 或 5V
RS-232负电压正电压单端-12V / +12V
RS-485A<BA>B差分±2V 差分
RS-422A<BA>B差分(双对)±2V 差分
关键认知
UART ≠ RS-232 ≠ RS-485。UART 是协议(帧格式),RS-232/485 是电平标准。一个 MCU 的 UART 引脚输出的是 TTL 电平,需要 MAX232 芯片转成 RS-232 电平,或用 MAX485 芯片转成 RS-485 差分信号。

四、UART:串口的大脑

UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)是串口通信的协议核心。它不是一种电平,而是规定了数据如何打包成帧、如何收发。

UART 在串口中的位置 应用层:Modbus / AT 指令 / 自定义协议 协议层:UART(帧格式 + 波特率) TTL 电平 RS-232 RS-485 RS-422 同一个 UART 协议,配不同电气层 = 不同串口标准
UART 是串口的协议核心,电气层决定具体类型

4.1 UART 硬件结构

UART 内部结构 CPU / MCU 写数据到发送寄存器 读接收寄存器 UART 控制器 TX 移位 RX 移位 波特率发生器 写 读 TX → ← RX 电平转换 MAX232/MAX485 → RS-232/485/422 UART 控制器负责"并↔串"转换 + 帧封装/解析,电平转换芯片负责"0/1 → 电气信号"
UART 硬件内部结构与数据流

五、串口帧格式:数据是怎么排队的

UART 的核心是帧格式。一个 UART 帧由 4 部分组成:

UART 帧格式 起始位1 bit 数据位(5~8 bit,LSB 先发)实际数据 校验位可选 停止位1~2 bit 下一帧起始位 空闲态为高电平 下降沿 触发采样 低位先发 LSB First 奇/偶/无 Parity 高电平 恢复空闲 一帧 = 起始位(1) + 数据位(5~8) + 校验位(0~1) + 停止位(1~2)
UART 帧格式详解

5.1 各字段详解

字段长度说明
起始位1 bit固定为 0(下降沿),标志帧开始。空闲时总线为高电平
数据位5~8 bit实际数据,低位(LSB)先发。常用 8 位(1 字节)
校验位0~1 bit奇校验/偶校验/无校验。用于简单错误检测
停止位1~2 bit固定为 1(高电平),标志帧结束。常用 1 位
起始位的"下降沿"是关键
总线空闲时一直是高电平。当接收方检测到下降沿(高→低跳变),就知道"有数据来了",然后按约定波特率在每个位的中点采样。这就是异步通信无需时钟线的秘密。

5.2 常见配置

串口配置通常写成 波特率-数据位-校验-停止位 格式:

六、波特率:通信的"语速"

波特率(Baud Rate)是每秒传输的码元数。在 UART 中,1 个码元 = 1 bit,所以波特率 = 比特率。常见值:9600、115200、921600 等。

波特率 = 每秒传输的位数 0 1 0s 1s 1 1 0 9600 波特率 = 每秒 9600 个位 ≈ 960 字节/秒 扣除起始位+停止位开销,有效数据约 80% 115200 波特率 ≈ 11.5 KB/s,满足大多数嵌入式场景
波特率示意图
波特率容差
收发双方波特率必须一致。如果差超过 3%,采样会"错位"导致乱码。这就是为什么不能用 RC 振荡器(误差 5%+),必须用晶振(误差 < 0.1%)。

6.1 常见波特率与场景

波特率字节/秒典型场景
2400240老式 GPS 模块、低速传感器
9600960工业仪表、Modbus 从站默认
192001920蓝牙模块 AT 配置
384003840部分 RFID 读卡器
11520011520调试输出、高精度 GPS
92160092160固件烧录、高速数据采集

七、TTL 串口:MCU 的母语

TTL 串口是 MCU(单片机)直接输出的串口电平。0V 表示逻辑 0,3.3V 或 5V 表示逻辑 1。

TTL 串口电平 0V 3.3V 逻辑1 逻辑0 1 0 1 1 TTL: 0V = 逻辑0, 3.3V/5V = 逻辑1(正逻辑) 直接从 MCU 引脚输出,无需电平转换芯片 传输距离短(< 1m),无抗干扰能力 用于 MCU 与模块近距离通信(如蓝牙模块、GPS 模块)
TTL 串口电平波形

7.1 TTL 串口的三种电压

MCU 电压逻辑 0逻辑 1典型芯片
5V TTL0V5VArduino UNO / 传统 51
3.3V TTL0V3.3VSTM32 / ESP32 / ESP8266
1.8V TTL0V1.8V部分低功耗 MCU
5V TTL 与 3.3V TTL 不能直连!
5V MCU 的 TX 输出 5V 高电平,直接接到 3.3V MCU 的 RX 会烧毁后者。需要电平转换(如 TXS0108E)或串联电阻限流。

八、RS-232:经典的 DB9 串口

RS-232是 1960 年代的标准,用 负逻辑:-3V~-15V 表示逻辑 1,+3V~+15V 表示逻辑 0。采用 DB9 接口(9 针 D 型连接器)。

RS-232 vs TTL 电平对比 TTL 电平(正逻辑) 3.3V 0V 逻辑1 (高) 逻辑0 (低) RS-232 电平(负逻辑) +12V -12V 逻辑0 (+12V) 逻辑1 (-12V) TTL: 高=1, 低=0(正逻辑) RS-232: 正电压=0, 负电压=1(负逻辑) MAX232 芯片负责两者转换:TTL ↔ RS-232 RS-232 电平高 → 抗干扰强 → 可传 15 米
TTL 与 RS-232 电平对比

8.1 DB9 接口引脚

DB9 串口引脚定义 1 2 3 4 5 6 7 8 9 DB9 引脚说明(公头) 1 DCD 数据载波检测 2 RXD 接收数据 ← 3 TXD 发送数据 → 4 DTR 数据终端就绪 5 GND 信号地 6 DSR 数据设备就绪 7 RTS 请求发送 8 CTS 清除发送 9 RI 振铃指示 最小三线:TXD(3) + RXD(2) + GND(5)
DB9 串口引脚定义
Null Modem 交叉接法
两台电脑用 RS-232 通信,TXD 对 RXD 交叉连接:
A 的 TXD(3) → B 的 RXD(2)
A 的 RXD(2) ← B 的 TXD(3)
A 的 GND(5) ↔ B 的 GND(5)
这就是"串口交叉线"的由来。

九、RS-485:工业总线的王者

RS-485采用差分信号传输,用两根线 A 和 B,信号靠电压差判断。最多 32~256 节点,传输距离 1200 米。

RS-485 差分信号原理 A B A-B A 高 B 低 A 低 B 高 A-B > +200mV → 逻辑0 A-B < -200mV → 逻辑1 A 和 B 同时被干扰 → 差值不变 → 抗干扰 双绞线保证干扰等量耦合到两根线 → 相减抵消 这就是 RS-485 能传 1200 米的秘密
RS-485 差分信号抗干扰原理
RS-485 vs RS-232 一句话总结
RS-232 = 单端(参考地)+ 全双工 + 点对点 + 15 米
RS-485 = 差分(A-B)+ 半双工 + 总线多节点 + 1200 米
软件层完全一样(都是 UART),只是电气层不同。

十、RS-422:全双工差分方案

RS-422是 RS-485 的"全双工版本"。用两对差分线(4 根),一对发(TX+/TX-),一对收(RX+/RX-),同时收发。

RS-485 vs RS-422 线制对比 RS-485(2 线半双工) 主站 从站 A B 从2 1 对线,分时收发 RS-422(4 线全双工) 主站 从站 TX+ TX- RX+ RX- 2 对线,同时收发
RS-485(半双工)与 RS-422(全双工)对比
维度RS-485RS-422
线数2 线(A/B)4 线(TX+/TX-/RX+/RX-)
双工半双工全双工
拓扑总线,多节点点对点/一点对多点
节点数32~25610(标准)
距离1200m1200m
成本低中(多一对线)
典型工业总线全双工仪表

十一、全家族对比与选型

串口家族全对比 TTL 电平: 0/3.3V 方式: 单端 双工: 全双工 距离: < 1m 节点: 点对点 抗扰: 无 用于: 模块间 芯片: 直连 如: MCU-GPS 成本: 最低 RS-232 电平: ±12V 方式: 单端 双工: 全双工 距离: 15m 节点: 点对点 抗扰: 中 用于: 调试接口 芯片: MAX232 如: PC-COM口 成本: 低 RS-485 电平: 差分 方式: 差分 双工: 半双工 距离: 1200m 节点: 32~256 抗扰: 强 用于: 工业总线 芯片: MAX485 如: Modbus 成本: 低 RS-422 电平: 差分 方式: 双差分 双工: 全双工 距离: 1200m 节点: 10 抗扰: 强 用于: 全双工仪表 芯片: MAX488 如: PLC通信 成本: 中
串口家族四种标准全对比

11.1 选型决策树

需求推荐理由
MCU 与模块近距离通信TTL无需电平芯片,直连即可
PC 调试输出RS-232 / USB转TTLPC 有 USB,转 TTL 最方便
工业多节点总线RS-485差分抗扰 + 多节点 + 远距离
全双工远距离RS-422同时收发 + 差分
高实时 + 多主 + 安全CAN仲裁 + 硬件 CRC + 自动降级

十二、串口硬件:接口与线缆

12.1 常见物理接口

串口常见物理接口 DB9 9针 D型 RS-232 经典 螺丝固定 USB-TTL USB CH340/CP2102 USB → TTL 最常用调试 插 USB 即用 接线端子 工业仪表 RS-485 常用 螺丝压线 M12 航空 工业防水 圆形快速 IP67 防护
串口四种常见物理接口

12.2 电平转换芯片

芯片转换供电特点
MAX232TTL ↔ RS-2325V经典 RS-232 转换,内置电荷泵
MAX3232TTL ↔ RS-2323.3V3.3V 版本,低功耗
MAX485TTL ↔ RS-4855V半双工,最常用 485 芯片
MAX488TTL ↔ RS-4225V全双工,4 线制
SP3485TTL ↔ RS-4853.3V3.3V 低功耗 485
ADM2483TTL ↔ RS-4855V隔离型,5000V 隔离
CH340USB ↔ TTL5VUSB 转串口,便宜好用
CP2102USB ↔ TTL3.3VSilicon Labs,更稳定
电平转换电路示意 MCU TX/RX TTL 3.3V MAX232 TTL→232 RS-232 DB9 接口 ±12V MAX485 TTL→485 RS-485 A/B 差分 → 15m 点对点 PC 调试 / 老设备 → 1200m 总线 工业多节点 MCU 输出 TTL → 经电平转换芯片 → 变成 RS-232/485/422 电气标准
电平转换芯片在电路中的位置

十三、Qt/C++ 实战代码

13.1 Qt 串口通信基础

// SerialPort.h —— Qt 串口封装
#ifndef SERIALPORT_H
#define SERIALPORT_H

#include <QObject>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QByteArray>

class SerialPort : public QObject {
    Q_OBJECT
public:
    explicit SerialPort(QObject *parent = nullptr);
    ~SerialPort();

    // 列举可用串口
    static QStringList listPorts();

    // 打开串口
    bool open(const QString &portName,
              qint32 baudRate = 115200,
              QSerialPort::DataBits dataBits = QSerialPort::Data8,
              QSerialPort::Parity parity = QSerialPort::NoParity,
              QSerialPort::StopBits stopBits = QSerialPort::OneStop);

    void close();
    bool isOpen() const;
    qint64 write(const QByteArray &data);

signals:
    void dataReceived(const QByteArray &data);
    void errorOccurred(const QString &error);

private slots:
    void onReadyRead();
    void onErrorOccurred(QSerialPort::SerialPortError error);

private:
    QSerialPort *m_serial;
    QByteArray m_buffer;  // 接收缓冲区
};

#endif
// SerialPort.cpp —— 实现
#include "SerialPort.h"
#include <QDebug>

QStringList SerialPort::listPorts() {
    QStringList ports;
    for (const QSerialPortInfo &info : QSerialPortInfo::availablePorts()) {
        ports << QString("%1 (%2 - %3)")
                   .arg(info.portName())
                   .arg(info.description())
                   .arg(info.manufacturer());
    }
    return ports;
}

SerialPort::SerialPort(QObject *parent) : QObject(parent), m_serial(new QSerialPort(this)) {
    connect(m_serial, &QSerialPort::readyRead, this, &SerialPort::onReadyRead);
    connect(m_serial, &QSerialPort::errorOccurred, this, &SerialPort::onErrorOccurred);
}

SerialPort::~SerialPort() { if (m_serial->isOpen()) m_serial->close(); }

bool SerialPort::open(const QString &portName, qint32 baudRate,
                  QSerialPort::DataBits dataBits,
                  QSerialPort::Parity parity,
                  QSerialPort::StopBits stopBits) {
    m_serial->setPortName(portName);
    m_serial->setBaudRate(baudRate);
    m_serial->setDataBits(dataBits);
    m_serial->setParity(parity);
    m_serial->setStopBits(stopBits);
    m_serial->setFlowControl(QSerialPort::NoFlowControl);

    if (!m_serial->open(QIODevice::ReadWrite)) {
        emit errorOccurred(m_serial->errorString());
        return false;
    }
    return true;
}

void SerialPort::close() { m_serial->close(); }
bool SerialPort::isOpen() const { return m_serial->isOpen(); }

qint64 SerialPort::write(const QByteArray &data) {
    return m_serial->write(data);
}

void SerialPort::onReadyRead() {
    QByteArray data = m_serial->readAll();
    m_buffer.append(data);

    // 按换行符分包(常见协议以 \n 或 \r\n 分隔)
    int idx;
    while ((idx = m_buffer.indexOf('\n')) >= 0) {
        QByteArray line = m_buffer.left(idx + 1);
        m_buffer.remove(0, idx + 1);
        emit dataReceived(line.trimmed());
    }
}

void SerialPort::onErrorOccurred(QSerialPort::SerialPortError error) {
    if (error != QSerialPort::NoError) {
        emit errorOccurred(m_serial->errorString());
    }
}

13.2 实战:NMEA GPS 数据解析

// main.cpp —— 读取 GPS 模块 NMEA 数据
#include <QCoreApplication>
#include "SerialPort.h"
#include <QDebug>
#include <QRegularExpression>

int main(int argc, char *argv[]) {
    QCoreApplication app(argc, argv);

    SerialPort serial;

    // GPS 模块通常 9600 波特率
    if (!serial.open("COM3", 9600)) {
        qDebug() << "打开串口失败";
        return -1;
    }

    QObject::connect(&serial, &SerialPort::dataReceived, [](const QByteArray &line) {
        QString msg = QString::fromUtf8(line);

        // 解析 NMEA GPRMC 语句:$GPRMC,时间,状态,纬度,N,经度,E,速度,航向,日期
        if (msg.startsWith("$GPRMC")) {
            QStringList parts = msg.split(',');
            if (parts.size() >= 10) {
                QString status = parts[2]; // A=有效, V=无效
                QString lat = parts[3];  // 纬度 ddmm.mmmm
                QString lon = parts[5];  // 经度 dddmm.mmmm
                QString speed = parts[7]; // 速度(节)

                if (status == "A") {
                    qDebug() << "GPS有效:" << "Lat=" << lat << "Lon=" << lon
                             << "Speed=" << speed << "knots";
                }
            }
        }
    });

    QObject::connect(&serial, &SerialPort::errorOccurred, [](const QString &err) {
        qDebug() << "串口错误:" << err;
    });

    qDebug() << "GPS 监听已启动...";
    return app.exec();
}

13.3 RS-485 方向控制

// RS-485 半双工需要控制收发方向
// DE/RE 引脚:高=发送,低=接收

void sendRs485(QSerialPort *serial, const QByteArray &data) {
    // 1. 拉高 RTS(DE=1),进入发送模式
    serial->setRequestToSend(true);

    // 2. 发送数据
    serial->write(data);
    serial->flush();

    // 3. 等待最后一个字节发送完毕
    while (serial->bytesToWrite() > 0) {
        serial->waitForBytesWritten(100);
    }

    // 4. 关键延时:等待最后一个位真正离开移位寄存器
    QThread::msleep(2);

    // 5. 拉低 RTS(DE=0),切回接收模式
    serial->setRequestToSend(false);
}

// 完整的 Modbus RTU 主站轮询示例
class ModbusMaster : public QObject {
    Q_OBJECT
public:
    explicit ModbusMaster(QSerialPort *s, QObject *p = nullptr)
        : QObject(p), m_serial(s) {
        connect(m_serial, &QSerialPort::readyRead, this, &ModbusMaster::onRead);
    }

    void readHoldingRegisters(quint8 slave, quint16 addr, quint16 count) {
        QByteArray req;
        req.append(char(slave));     // 从站地址
        req.append(char(0x03));      // 功能码:读保持寄存器
        req.append(char((addr >> 8) & 0xFF));
        req.append(char(addr & 0xFF));
        req.append(char((count >> 8) & 0xFF));
        req.append(char(count & 0xFF));
        quint16 crc = crc16Modbus(req);
        req.append(char(crc & 0xFF));
        req.append(char((crc >> 8) & 0xFF));

        sendRs485(m_serial, req);  // 485 方向控制发送
    }

private slots:
    void onRead() {
        QByteArray resp = m_serial->readAll();
        if (resp.size() >= 5) {
            quint8 slave = resp[0];
            quint8 func = resp[1];
            quint8 byteCount = resp[2];
            qDebug() << "从站" << slave << "功能码" << QString::number(func, 16);
        }
    }

private:
    QSerialPort *m_serial;

    // Modbus CRC16 计算
    quint16 crc16Modbus(const QByteArray &data) {
        quint16 crc = 0xFFFF;
        for (int i = 0; i < data.size(); i++) {
            crc ^= (quint8)data[i];
            for (int j = 0; j < 8; j++) {
                if (crc & 1) crc = (crc >> 1) ^ 0xA001;
                else crc >>= 1;
            }
        }
        return crc;
    }
};
串口编程三大要点
① 异步接收 + 缓冲区:串口数据可能分多次到达,必须缓冲累积后按帧分隔
② 485 方向延时:发送后等 2ms 再切接收,防止最后一个字节被截断
③ 超时处理:Modbus 等请求-响应协议必须有超时机制,不能死等

十四、应用场景全景

串口应用场景全景 调试输出 • MCU printf 调试 • USB-TTL 接 PC • 串口终端显示 • 波特率: 115200 工业控制 • Modbus RTU 仪表 • PLC 通信 • 变频器控制 • RS-485 总线 传感器 • GPS 模块 NMEA • 温湿度变送器 • 气体检测仪 • 压力传感器 模块通信 • 蓝牙模块 AT • WiFi/4G 模块 • RFID 读卡器 • 条码扫描器 医疗设备 • 血压计 • 心电监护 • 输液泵 • 隔离 RS-485 消费电子 • 智能家居 • 无人机飞控 • 3D 打印机 • Arduino 项目 固件烧录 • MCU ISP 模式 • Bootloader • STM32 串口下载 • ESP-Flasher AT 命令 • AT+BAUD=115200 • AT+NAME=BT01 • HC-05 蓝牙配置 • SIM800C 模块
串口在各领域的应用场景

十五、调试技巧与常见问题

15.1 调试三板斧

  1. 先确认物理层:万用表测 TX/RX 引脚有无电压跳变,排除接线问题
  2. 用串口助手回环测试:TX 短接 RX,发什么收什么 → 证明本机串口正常
  3. 抓包对比:用逻辑分析仪或串口监控工具,看实际波形和数据

15.2 常见问题速查

现象原因解决
收到乱码波特率不匹配双方波特率必须一致
收到部分数据缓冲区未分包按帧分隔符拆包
485 收不到A/B 接反对调 A/B 线
485 尾字节丢失方向切换过早发送后延时 2ms 再切接收
TTL 直连烧 MCU5V 接 3.3V加电平转换
偶发误码线路干扰/波特率容差用双绞线/晶振
跨平台端口名变USB 转串口每次枚举不同用序列号固定端口
串口调试三大坑
① 波特率容差:收发差超过 3% 就乱码,别用内部 RC 振荡器
② 共地:TTL/RS-232/RS-485 都要共地,不共地通信不稳定
③ 485 终端电阻:总线两端各 120Ω,不是每个节点都接

15.3 常用调试工具

工具平台用途
串口调试助手Win/Linux手动收发测试
putty / minicom跨平台终端式串口交互
逻辑分析仪硬件看实际波形,排查时序
Modbus Poll/SlaveWinModbus 主站/从站模拟
Virtual Serial PortWin虚拟串口对,无硬件测试

十六、总结

本文知识全景

  1. 串口本质:数据一位一位顺序传输,1 根线即可通信
  2. 三层结构:协议层(UART) + 电气层(TTL/232/485/422) + 应用层(Modbus/AT)
  3. 串行 vs 并行:线少→无串扰→频率高→串行赢了
  4. 通信三要素:方向(单工/半双工/全双工) + 时钟(同步/异步) + 电平
  5. UART 帧格式:起始位(1) + 数据位(5~8) + 校验位(0~1) + 停止位(1~2)
  6. 波特率:每秒传输位数,双方必须一致(容差 < 3%)
  7. TTL:0V/3.3V 正逻辑,MCU 母语,< 1m,无抗扰
  8. RS-232:±12V 负逻辑,单端全双工,15m,DB9 接口
  9. RS-485:差分半双工,1200m,32~256 节点,工业总线王者
  10. RS-422:差分全双工,4 线制,1200m,全双工仪表
  11. 电平转换:MAX232(TTL→232) / MAX485(TTL→485) / CH340(USB→TTL)
  12. Qt 编程:QSerialPort + readyRead 异步 + 缓冲区拆帧 + 485 方向控制
  13. 调试要点:共地 + 波特率一致 + 485 终端电阻 + 方向延时
串口一图速记 TTL 0/3.3V 正逻辑 全双工 点对点 < 1m 无抗扰 MCU 母语 RS-232 ±12V 负逻辑 全双工 点对点 15m DB9 接口 PC 调试口 RS-485 差分 半双工 1200m 32~256节点 抗扰强 工业总线 RS-422 差分 全双工 1200m 4线 10 节点 全双工仪表 UART 协议 + 不同电气层 = 不同串口标准 软件层几乎无差别,差别在硬件电平与拓扑
串口四种标准一图速记
最后的话
串口通信是嵌入式工程师的"ABC":看起来简单(两根线),但背后藏着异步同步、单端差分、帧格式、波特率、电平转换等一整套知识体系。

理解串口后,再看 CAN、USB、I2C、SPI 都会有"似曾相识"的感觉——它们都在解决同一类问题:如何在两个或多个设备之间可靠地传输比特。差别只在于"怎么打包、怎么传输、怎么纠错"。

动手建议:买一个 USB-TTL 模块(CH340 或 CP2102,十元一个),用 Qt 串口示例在自己电脑上收发数据,比读百遍文章更有效。