当前位置: 首页 > news >正文

RS232 串行通信:C++ 实现指南

image.png

文章目录

    • 一、RS232 简介
      • 1. 电气特性
      • 2. 传输速率
      • 3. 传输距离
    • 二、在 C++ 中实现 RS232 通信
      • 1. Windows 平台
        • (1)打开串行端口
        • (2)配置串行通信参数
        • (3)发送数据
        • (4)接收数据
        • (5)主函数示例
      • 2. Linux 平台
        • (1)打开串行端口
        • (2)配置串行通信参数
        • (3)发送数据
        • (4)接收数据
        • (5)主函数示例
    • 三、注意事项
    • 四、总结

在现代嵌入式系统和工业控制领域,RS232 串行通信仍然是一种不可或缺的技术。尽管 USB 和以太网等高速通信技术已经广泛应用,但在一些需要低速、简单通信的场景中,RS232 仍然是首选。本文将详细介绍如何在 C++ 中实现与 RS232 的通信,包括 Windows 和 Linux 平台的实现方法。

一、RS232 简介

RS232 是一种串行通信协议,用于实现设备之间的近距离数据传输。它通过一对发送和接收引脚(TxD 和 RxD)进行数据通信,并支持控制信号(如 RTS 和 CTS)以实现流控制。RS232 的传输速率通常在几百比特每秒(bps)到几十千比特每秒(kbps)之间,适用于低速数据传输场景。

1. 电气特性

RS232 使用负逻辑,逻辑“1”对应的电平范围是 -3V 到 -15V,逻辑“0”对应的电平范围是 +3V 到 +15V。这种设计使得信号在传输过程中具有一定的抗干扰能力。

2. 传输速率

RS232 的传输速率通常在几百 bps 到几十 kbps 之间。例如,常见的波特率有 9600 bps、19200 bps 和 115200 bps。波特率越高,数据传输速度越快,但传输距离和可靠性可能会受到影响。

3. 传输距离

RS232 的传输距离通常在 15 米以内。如果需要更长的传输距离,可以使用 RS485 等其他串行通信协议。

二、在 C++ 中实现 RS232 通信

在 C++ 中实现 RS232 通信,需要使用操作系统提供的串行通信 API。以下是基于 Windows 和 Linux 平台的实现方法。

1. Windows 平台

在 Windows 系统中,可以使用 Windows API 中的串行通信函数来实现与 RS232 的通信。以下是一个简单的示例代码,展示如何打开串行端口、设置通信参数、发送和接收数据。

(1)打开串行端口
#include <windows.h>
#include <iostream>// 打开串行端口
HANDLE OpenSerialPort(const char* portName)
{HANDLE hSerial;hSerial = CreateFile(portName, // 端口名称,如 "COM1"GENERIC_READ | GENERIC_WRITE, // 读写权限0, // 不共享0, // 无安全属性OPEN_EXISTING, // 打开已存在的设备0, // 非异步0 // 无模板);if (hSerial == INVALID_HANDLE_VALUE){std::cerr << "Error opening serial port" << std::endl;return INVALID_HANDLE_VALUE;}return hSerial;
}
(2)配置串行通信参数
// 配置串行通信参数
bool ConfigureSerialPort(HANDLE hSerial)
{DCB dcbSerialParams = { 0 };dcbSerialParams.DCBlength = sizeof(dcbSerialParams);if (!GetCommState(hSerial, &dcbSerialParams)){std::cerr << "Error getting state" << std::endl;return false;}dcbSerialParams.BaudRate = CBR_9600; // 波特率 9600dcbSerialParams.ByteSize = 8; // 数据位 8dcbSerialParams.StopBits = ONESTOPBIT; // 停止位 1dcbSerialParams.Parity = NOPARITY; // 无校验位if (!SetCommState(hSerial, &dcbSerialParams)){std::cerr << "Error setting state" << std::endl;return false;}return true;
}
(3)发送数据
// 发送数据
bool WriteSerialPort(HANDLE hSerial, const char* data, DWORD size)
{DWORD bytesWritten;if (!WriteFile(hSerial, data, size, &bytesWritten, 0)){std::cerr << "Error writing to port" << std::endl;return false;}return true;
}
(4)接收数据
// 接收数据
bool ReadSerialPort(HANDLE hSerial, char* buffer, DWORD size)
{DWORD bytesRead;if (!ReadFile(hSerial, buffer, size, &bytesRead, 0)){std::cerr << "Error reading from port" << std::endl;return false;}return true;
}
(5)主函数示例
int main()
{const char* portName = "COM1";HANDLE hSerial = OpenSerialPort(portName);if (hSerial == INVALID_HANDLE_VALUE){return 1;}if (!ConfigureSerialPort(hSerial)){CloseHandle(hSerial);return 1;}const char* dataToSend = "Hello, Serial Port!";if (!WriteSerialPort(hSerial, dataToSend, strlen(dataToSend))){CloseHandle(hSerial);return 1;}char readBuffer[128];if (ReadSerialPort(hSerial, readBuffer, sizeof(readBuffer))){std::cout << "Received: " << readBuffer << std::endl;}CloseHandle(hSerial);return 0;
}

2. Linux 平台

在 Linux 系统中,可以使用 POSIX 串行通信 API 来实现与 RS232 的通信。以下是一个简单的示例代码。

(1)打开串行端口
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <cstring>// 打开串行端口
int OpenSerialPort(const char* portName)
{int fd = open(portName, O_RDWR | O_NOCTTY | O_SYNC);if (fd < 0){std::cerr << "Error opening serial port" << std::endl;return -1;}return fd;
}
(2)配置串行通信参数
// 配置串行通信参数
bool ConfigureSerialPort(int fd)
{struct termios tty;if (tcgetattr(fd, &tty) != 0){std::cerr << "Error getting attributes" << std::endl;return false;}cfsetospeed(&tty, B9600); // 波特率 9600cfsetispeed(&tty, B9600);tty.c_cflag &= ~PARENB; // 无校验位tty.c_cflag &= ~CSTOPB; // 1 停止位tty.c_cflag &= ~CSIZE; // 清除数据位掩码tty.c_cflag |= CS8; // 8 数据位tty.c_cflag &= ~CRTSCTS; // 关闭硬件流控制tty.c_cflag |= CREAD | CLOCAL; // 启用接收器,忽略调制解调器控制线tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控制tty.c_iflag &= ~(ICRNL | INLCR); // 禁用回车和换行的特殊处理tty.c_lflag &= ~ICANON;tty.c_lflag &= ~ECHO; // 关闭回显tty.c_lflag &= ~ISIG; // 关闭信号字符tty.c_oflag &= ~OPOST; // 防止特殊解释输出数据tty.c_oflag &= ~ONLCR; // 防止将换行符转换为回车换行符if (tcsetattr(fd, TCSANOW, &tty) != 0){std::cerr << "Error setting attributes" << std::endl;return false;}return true;
}
(3)发送数据
// 发送数据
bool WriteSerialPort(int fd, const char* data, size_t size)
{ssize_t bytesWritten = write(fd, data, size);if (bytesWritten < 0){std::cerr << "Error writing to port" << std::endl;return false;}return true;
}
(4)接收数据
// 接收数据
bool ReadSerialPort(int fd, char* buffer, size_t size)
{ssize_t bytesRead = read(fd, buffer, size);if (bytesRead < 0){std::cerr << "Error reading from port" << std::endl;return false;}return true;
}
(5)主函数示例
int main()
{const char* portName = "/dev/ttyS0";int fd = OpenSerialPort(portName);if (fd < 0){return 1;}if (!ConfigureSerialPort(fd)){close(fd);return 1;}const char* dataToSend = "Hello, Serial Port!";if (!WriteSerialPort(fd, dataToSend, strlen(dataToSend))){close(fd);return 1;}char readBuffer[128];if (ReadSerialPort(fd, readBuffer, sizeof(readBuffer))){std::cout << "Received: " << readBuffer << std::endl;}close(fd);return 0;
}

三、注意事项

  1. 波特率匹配:发送端和接收端的波特率必须一致,否则会导致数据传输错误。
  2. 串行端口名称:在 Windows 上,串行端口名称通常为 “COM1”、“COM2” 等;在 Linux 上,通常为 “/dev/ttyS0”、“/dev/ttyUSB0” 等。
  3. 错误处理:在实际应用中,需要对串行通信中的错误进行详细处理,例如超时错误、硬件故障等。
  4. 多线程支持:在需要同时进行发送和接收操作时,可以使用多线程来实现。

四、总结

RS232 串行通信在工业控制和嵌入式系统中仍然具有重要地位。通过使用 Windows API 和 POSIX API,我们可以在 C++ 中实现与 RS232 的通信。本文提供了详细的代码示例,帮助开发者快速上手。在实际应用中,还需要根据具体需求进行适当的扩展和优化。

相关文章:

  • SAP系统生产跟踪报表入库数异常
  • C语言中的双链表和单链表详细解释与实现
  • 极狐GitLab Git LFS 速率限制如何设置?
  • [Python] 入门核心笔记
  • 使用C#和FFmpeg开发RTSP视频播放器的完整指南
  • Azkaban集群搭建
  • 递归的模板 (以反转链表为例)
  • AI时代,是该切换到Cursor编辑器了
  • 探究CF1009(div3)C题——XOR and Triangle
  • 【第16届蓝桥杯C++C组】--- 2025
  • Docker Compose 使用实例
  • 接口测试流程和步骤
  • vue3 + element-plus中el-dialog对话框滚动条回到顶部
  • vue使用语音识别
  • 包管理工具有哪些?主流软件分享
  • Windows部署FunASR实时语音听写便捷部署教程
  • 详解LibTorch中train()函数
  • [渗透测试]渗透测试靶场docker搭建 — —全集
  • FreeRTos学习记录--2.内存管理
  • 自注意力机制、多头自注意力机制、填充掩码 Python实现
  • 又一名被拐孩子找到!29年后,在警方帮助下云南男子寻子成功
  • 普京签署有关批准俄罗斯与伊朗全面战略伙伴关系条约的联邦法令
  • “6+2”小复式追加票!松江购彩者擒大乐透1672万头奖
  • “解压方程式”主题沙龙:用艺术、精油与自然的力量,寻找自我疗愈的方式
  • A股低开高走,震荡收涨:两市成交10414亿元,4360股收涨
  • 印度空军计划增购40架法制“阵风”战机,此前已购买36架