# 串口通信 串口通信(Serial Communication)是一种设备间常用的数据传输方式,其特点是**一位一位地顺序传输数据**,适用于近距离、低速通信场景。 ### **1. 基本概念** #### **物理层** - **接口类型**:常见有 RS-232(DB9 接口)、RS-485、USB 转串口(TTL 电平)。 - 通信参数: - **波特率**(Baud Rate):每秒传输的比特数,如 9600、115200。 - **数据位**(Data Bits):通常为 8 位。 - **停止位**(Stop Bits):1 位或 2 位。 - **校验位**(Parity):无校验(None)、奇校验(Odd)、偶校验(Even)。 #### **协议层** - **异步通信**:无共享时钟,依赖起始位和停止位同步。 - **数据格式**:起始位(0) + 数据位 + 校验位(可选) + 停止位(1)。 ### **2. 硬件连接** #### **常见接口** - **RS-232**:适用于工业设备,需注意电平转换(计算机端通常为 DB9 接口)。 - **USB 转串口**:使用 TTL 电平(如 Arduino、ESP32),通过 CH340、CP2102 等芯片转接。 #### **接线规则** - **TX(发送端)** → **RX(接收端)** - **GND(地)** → **GND** - 若为 RS-485,需额外连接 A/B 差分线。 ### **3. 软件配置** #### **工具推荐** - 串口调试助手: - Windows:[SSCOM](https://www.chiark.greenend.org.uk/~sgtatham/putty/)、[Putty](https://www.chiark.greenend.org.uk/~sgtatham/putty/) - Linux/macOS:`minicom`、`screen` 命令。 - 编程语言库: - Python:`pyserial` - C/C++:`termios`(Linux)、`CreateFile`(Windows)。 ### **4. 常见问题** 1. **无法连接**: - 检查设备管理器(Windows)或`dmesg`(Linux)确认串口名称。 - 确保驱动已安装(如 CH340 需额外驱动)。 - 检查权限(Linux 需添加用户到`dialout`组)。 2. **数据乱码**: - 确认波特率、数据位、停止位、校验位一致。 - 检查是否有干扰(如长距离传输需用 RS-485)。 3. **收发异常**: - 短接 TX/RX 自测(发送数据应能被自己接收)。 - 使用示波器监测电平信号。 ### **5. 进阶应用** - **多设备通信**:使用 RS-485 实现一主多从。 - **协议开发**:自定义通信协议(如添加帧头、CRC 校验)。 - **实时监控**:结合 GUI 工具(如 PyQt、Tkinter)开发监控界面。 ### **6. 资源推荐** - 文档: - [pyserial 官方文档](https://pyserial.readthedocs.io/) - [RS-232 规范](https://www.ti.com/lit/an/slla054a/slla054a.pdf) - 实践项目: - 用 Arduino 和 Python 实现温湿度数据传输。 - 基于串口的智能家居控制系统。 # 校验位 在串口通信中,校验位(Parity Bit)是一种用于**检测数据传输错误**的机制。它通过在数据位后添加一个额外的位,来验证接收数据的完整性。以下是关于校验位的详细介绍: ### **1. 校验位的作用** - **检测错误**:在数据传输过程中,由于电磁干扰、信号衰减等原因,可能导致数据位发生翻转(0→1 或 1→0)。校验位可以帮助接收方发现这类错误。 - **不纠错**:校验位只能检测错误,不能纠正错误。若需纠错,需使用更复杂的编码(如 CRC 校验、海明码)。 ### **2. 常见校验方式** #### **无校验(None)** - **特点**:不添加校验位,数据帧仅包含起始位、数据位和停止位。 - **适用场景**:干扰较小的环境,或已通过其他方式保证数据可靠性(如光纤传输)。 - **优点**:传输效率高,相同波特率下数据吞吐量更大。 - **缺点**:无错误检测能力。 #### **奇校验(Odd Parity)** - 规则:校验位使得整个数据(包括校验位)中 "1" 的个数为奇数。 - 示例:若数据位为 `1010010`(共 3 个 "1"),校验位为`0`(3+0=3,奇数)。 - 若数据位为 `1011010`(共 4 个 "1"),校验位为`1`(4+1=5,奇数)。 #### **偶校验(Even Parity)** - 规则:校验位使得整个数据中 "1" 的个数为偶数。 - 示例:若数据位为 `1010010`(共 3 个 "1"),校验位为`1`(3+1=4,偶数)。 - 若数据位为 `1011010`(共 4 个 "1"),校验位为`0`(4+0=4,偶数)。 #### **标记校验(Mark Parity)** - **规则**:校验位始终为`1`。 - **适用场景**:极少使用,仅在特定协议中存在。 #### **空格校验(Space Parity)** - **规则**:校验位始终为`0`。 - **适用场景**:极少使用,仅在特定协议中存在。 ### **3. 校验位的工作流程** 1. **发送端**: - 根据数据位计算校验位。 - 将数据位和校验位一起发送。 2. **接收端**: - 接收数据位和校验位。 - 重新计算校验位,并与接收到的校验位比较。 - 若不一致,说明数据传输过程中可能发生错误。 ### **4. 校验位的局限性** - **只能检测奇数个错误**:若数据位中有偶数个错误(如两位同时翻转),校验位无法检测。 - **无法定位错误**:仅能判断数据是否可能出错,但不知道具体是哪一位出错。 - **增加开销**:每个数据帧增加 1 位传输开销,降低了有效数据传输率。 ### **5. 校验位的选择建议** | 场景 | 校验方式 | | :--------------------: | :---------: | | 实验室环境(低干扰) | 无校验 | | 工业环境(高干扰) | 奇 / 偶校验 | | 关键系统(如医疗设备) | CRC 校验 | | 自定义协议 | 按需选择 | ### **7. 与其他校验方式的对比** | 校验方式 | 检测能力 | 开销 | 适用场景 | | :------: | :--------------------: | :----------: | :---------------------: | | 校验位 | 奇数个错误 | 1 位 / 帧 | 低速、短距离通信 | | CRC 校验 | 多位错误、突发错误 | 8-32 位 / 帧 | 高速、长距离通信 | | 海明码 | 单比特纠错、双比特检错 | 额外 k 位 | 存储系统(如 RAM 校验) | ### **8. 实际应用注意事项** 1. **收发双方必须一致**:发送端和接收端的校验方式(如奇校验 / 偶校验)必须相同,否则无法正确解析数据。 2. **结合其他机制**:校验位通常与超时重传机制结合使用(如 Modbus 协议),当检测到错误时请求重新发送。 3. **波特率影响**:使用校验位会降低有效数据传输率,例如 9600 波特率下,无校验时每秒可传约 960 字节,而使用奇校验时仅能传约 873 字节。 通过合理选择校验方式,可在可靠性和效率之间取得平衡。在实际开发中,建议根据通信环境的稳定性和数据重要性来决定是否使用校验位及选择何种校验方式。 # C++ 串口开发常用库(全平台 + Windows/Linux 专属) C++ 串口开发没有官方标准库,但有**成熟、稳定、跨平台**的开源库,也有系统原生 API。我按**推荐优先级**给你整理,从最简单到最底层全覆盖,新手直接用前 2 个即可。 ## 一、【首选】跨平台 C++ 串口库(推荐所有项目使用) ### 1. **Boost.Asio**(最强大、工业级、C++ 标准级) **地位**:C++ 网络 / 串口开发的事实标准,稳定、高性能、跨平台。 **支持**:Windows / Linux / macOS **特点**: - 支持同步 / 异步串口通信 - 自带超时、流控制、校验位配置 - 可和网络、文件 IO 无缝结合 - 大型项目、工业设备、机器人首选 **适用场景**:正式项目、工业通信、需要高稳定性的代码。 **缺点**:库体积大,需要编译 Boost。 ------ ### 2. **serial**(极简轻量、纯头文件、新手首选) **地址**:https://github.com/wjwwood/serial **特点**: - 纯 C++、轻量、无依赖 - 一行代码打开串口、配置波特率 / 校验位 - 接口极简,比 Boost 简单 10 倍 - 跨平台(Windows/Linux/macOS) **这是新手入门最推荐的库!** **示例代码(极简)** ```cpp #include #include int main() { serial::Serial ser; try { // 打开串口:COM3(Windows)/ /dev/ttyUSB0(Linux) ser.setPort("/dev/ttyUSB0"); ser.setBaudrate(115200); serial::Timeout to = serial::Timeout::simpleTimeout(1000); ser.setTimeout(to); ser.open(); if (ser.isOpen()) { // 发送数据 ser.write("Hello Serial"); // 读取数据 std::string res = ser.read(ser.available()); std::cout << "收到:" << res << std::endl; } } catch (...) {} return 0; } ``` ------ ### 3. **libserialport**(专注串口、跨平台、专业级) **地址**:https://sigrok.org/wiki/Libserialport **特点**: - 专门为串口设计的 C 库,C++ 可直接调用 - 支持所有串口参数(校验位、流控、波特率等) - 体积小、编译简单 - 很多串口调试工具底层都用它 **适用**:嵌入式、调试工具、轻量级项目。 ------ ## 二、Windows 专属串口开发(系统 API) ### 1. **Win32 API 串口函数** Windows 原生串口操作,不需要任何第三方库,直接用系统 API: - `CreateFile` 打开串口 - `SetCommState` 设置波特率 / 校验位 - `ReadFile` / `WriteFile` 收发数据 **优点**:无依赖、系统原生 **缺点**:代码繁琐、不跨平台 **适用**:仅 Windows 项目、不想装第三方库。 ------ ## 三、Linux 专属串口开发 ### 1. **Linux 原生 termios 库** Linux 下串口是**文件操作** + **termios 配置**: - 用 `open("/dev/ttyUSB0")` 打开 - 用 `termios` 结构体配置波特率、校验位 - 用 `read()` / `write()` 收发数据 **优点**:Linux 原生、无依赖 **缺点**:配置代码多、参数复杂 ------ ## 四、库选择建议(直接照抄) ### ✅ 新手 / 快速开发 **选:wjwwood/serial** (纯头文件、简单、5 分钟上手) ### ✅ 工业项目 / 正式产品 **选:Boost.Asio** (稳定、异步、高性能) ### ✅ 跨平台轻量工具 **选:libserialport** ### ✅ 仅 Windows / 仅 Linux 直接用**系统原生 API**(Win32 / termios) ------ ## 五、最关键总结(必看) 1. **C++ 没有官方串口库**,必须用第三方或系统 API 2. **90% 的项目用 wjwwood/serial 或 Boost.Asio 就够了** 3. 串口参数(波特率、校验位、数据位、停止位)**收发必须完全一致** 4. 跨平台优先用开源库,不要手写原生 API