C++ modbus串口通信
时间: 2025-07-09 09:20:45 浏览: 3
### 关于C++实现Modbus串口通信
在工业自动化领域,Modbus RTU是一种广泛使用的通信协议,尤其适用于串口通信场景。以下是基于C++实现Modbus RTU串口通信的一个完整示例及其关键技术点。
#### 1. 开发环境准备
为了实现Modbus RTU通信,可以使用Visual Studio 2022作为开发工具,并针对x86架构进行编译和运行[^1]。此外,还需要配置串口参数以匹配目标设备的要求,例如波特率、数据位、停止位以及校验方式等。
#### 2. Modbus RTU消息结构
Modbus RTU的消息遵循特定的帧格式,通常由以下几个部分组成:
- **从机地址**:指定目标设备的唯一标识。
- **功能码**:定义操作类型(如读取输入寄存器、写单个线圈等)。
- **数据区**:包含实际的操作数据。
- **CRC校验码**:用于检测传输错误。
以下是一个典型的Modbus RTU请求帧示例[^5]:
```plaintext
01 03 00 00 00 0A B8 CA
```
其中:
- `01` 表示从机地址;
- `03` 是功能码;
- `00 00` 和 `00 0A` 定义起始地址和寄存器数量;
- `B8 CA` 是计算得到的CRC校验值。
#### 3. CRC校验算法实现
在发送任何Modbus RTU消息之前,必须生成并附加CRC校验码。下面展示了一种常见的CRC-16校验函数实现:
```cpp
#include <stdint.h>
#include <vector>
uint16_t calculateCRC(const std::vector<uint8_t>& data) {
uint16_t crc = 0xFFFF;
for (size_t i = 0; i < data.size(); ++i) {
crc ^= static_cast<uint16_t>(data[i]);
for (int j = 0; j < 8; ++j) {
if (crc & 0x0001) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return ((crc << 8) | (crc >> 8)) & 0xFFFF;
}
```
此函数接受一个字节向量作为输入,并返回对应的CRC-16校验值[^3]。
#### 4. 发送与接收消息
通过Windows API中的`CreateFile`、`WriteFile`和`ReadFile`函数可完成串口的打开、写入及读取操作。以下是一段简单的代码片段演示如何执行这些基本任务:
```cpp
#include <windows.h>
#include <iostream>
#include <vector>
void sendAndReceiveData(HANDLE hComm, const std::vector<uint8_t>& sendData) {
DWORD bytesWritten, bytesRead;
std::vector<uint8_t> receiveBuffer(256);
// Write to serial port
WriteFile(hComm, sendData.data(), sendData.size(), &bytesWritten, NULL);
// Read from serial port
Sleep(10); // Wait briefly before reading
ReadFile(hComm, receiveBuffer.data(), receiveBuffer.size(), &bytesRead, NULL);
// Output received data
for (DWORD i = 0; i < bytesRead; ++i) {
printf("%02X ", receiveBuffer[i]);
}
printf("\n");
}
HANDLE openSerialPort(const char* portName) {
HANDLE hComm = CreateFile(portName,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hComm == INVALID_HANDLE_VALUE) {
std::cerr << "Error opening serial port." << std::endl;
exit(EXIT_FAILURE);
}
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
GetCommState(hComm, &dcbSerialParams);
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
SetCommState(hComm, &dcbSerialParams);
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
SetCommTimeouts(hComm, &timeouts);
PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR);
return hComm;
}
```
上述代码提供了创建串口句柄的功能,并封装了发送和接收数据的过程[^1]。
#### 5. Qt框架下的实现选项
如果倾向于跨平台解决方案,则可以选择利用Qt框架来简化GUI设计的同时支持Modbus通信。具体而言,可以通过集成第三方库如QModbus轻松达成目的[^4]。
---
###
阅读全文
相关推荐

















