From 7dda9467ea2011e3387f79aab4eecd0af1e96612 Mon Sep 17 00:00:00 2001 From: "ZTZHANG\\ztzhang" Date: Fri, 25 Jul 2025 14:43:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BA=86Modbus=20RTU?= =?UTF-8?q?=E4=B8=BB=E7=AB=99=E7=9A=84=E5=9F=BA=E6=9C=AC=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Modbus/Modbus.vcxproj | 10 +++ Modbus/Modbus.vcxproj.filters | 32 +++++++ Modbus/include/modbus_err.h | 13 +++ Modbus/include/modbus_log.h | 17 ++++ Modbus/include/modbus_rtu_pkg.h | 43 +++++++++ Modbus/include/modbus_rtu_receiver.h | 13 +++ Modbus/include/modbus_rtu_sender.h | 20 +++++ Modbus/src/modbus_err.cpp | 13 +++ Modbus/src/modbus_log.cpp | 13 +++ Modbus/src/modbus_rtu_pkg.cpp | 129 +++++++++++++++++++++++++++ Modbus/src/modbus_rtu_receiver.cpp | 13 +++ Modbus/src/modbus_rtu_sender.cpp | 13 +++ 12 files changed, 329 insertions(+) create mode 100644 Modbus/include/modbus_err.h create mode 100644 Modbus/include/modbus_log.h create mode 100644 Modbus/include/modbus_rtu_pkg.h create mode 100644 Modbus/include/modbus_rtu_receiver.h create mode 100644 Modbus/include/modbus_rtu_sender.h create mode 100644 Modbus/src/modbus_err.cpp create mode 100644 Modbus/src/modbus_log.cpp create mode 100644 Modbus/src/modbus_rtu_pkg.cpp create mode 100644 Modbus/src/modbus_rtu_receiver.cpp create mode 100644 Modbus/src/modbus_rtu_sender.cpp diff --git a/Modbus/Modbus.vcxproj b/Modbus/Modbus.vcxproj index 22dd846..5cd1f61 100644 --- a/Modbus/Modbus.vcxproj +++ b/Modbus/Modbus.vcxproj @@ -95,12 +95,22 @@ + + + + + + + + + + diff --git a/Modbus/Modbus.vcxproj.filters b/Modbus/Modbus.vcxproj.filters index dd1f0cd..bc1fd80 100644 --- a/Modbus/Modbus.vcxproj.filters +++ b/Modbus/Modbus.vcxproj.filters @@ -46,10 +46,42 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + Header Files + + Header Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/Modbus/include/modbus_err.h b/Modbus/include/modbus_err.h new file mode 100644 index 0000000..4c659b1 --- /dev/null +++ b/Modbus/include/modbus_err.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +class Modbus_Err : public QObject +{ + Q_OBJECT + +public: + Modbus_Err(QObject *parent); + ~Modbus_Err(); +}; + diff --git a/Modbus/include/modbus_log.h b/Modbus/include/modbus_log.h new file mode 100644 index 0000000..581bf76 --- /dev/null +++ b/Modbus/include/modbus_log.h @@ -0,0 +1,17 @@ +#pragma once + +#include + + +/** + * . + */ +class Modbus_Log : public QObject +{ + Q_OBJECT + +public: + Modbus_Log(QObject *parent); + ~Modbus_Log(); +}; + diff --git a/Modbus/include/modbus_rtu_pkg.h b/Modbus/include/modbus_rtu_pkg.h new file mode 100644 index 0000000..6d62478 --- /dev/null +++ b/Modbus/include/modbus_rtu_pkg.h @@ -0,0 +1,43 @@ +#pragma once +#include +#include +#include +#include +#include + + +/** + * Modbus RTU数据包格式合成和解析 + * 创建传输或发送数据包的统一格式 + * 计算以及解析CRC16校验码 + */ +class Modbus_RTU_Pkg : public QObject +{ + Q_OBJECT + +public: + explicit Modbus_RTU_Pkg(QObject *parent = nullptr); + ~Modbus_RTU_Pkg(); + + // 构建Modbus RTU数据包 + QVector build_modbus_pkg( + quint8 slave_addr, + quint8 func_code, + const QVector& work_data + ); + + // 解析Modbus RTU数据包 + bool parse_modbus_pkg( + const QVector &pkg, + quint8 &slave_addr, + quint8 &func_code, + QVector &work_data + ); + + + +private: + // 计算Modbus CRC16 + quint16 calc_crc(const QVector& pkg_data) const; +}; + diff --git a/Modbus/include/modbus_rtu_receiver.h b/Modbus/include/modbus_rtu_receiver.h new file mode 100644 index 0000000..3e0774f --- /dev/null +++ b/Modbus/include/modbus_rtu_receiver.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +class Modbus_RTU_Receiver : public QObject +{ + Q_OBJECT + +public: + Modbus_RTU_Receiver(QObject *parent); + ~Modbus_RTU_Receiver(); +}; + diff --git a/Modbus/include/modbus_rtu_sender.h b/Modbus/include/modbus_rtu_sender.h new file mode 100644 index 0000000..c9eba3d --- /dev/null +++ b/Modbus/include/modbus_rtu_sender.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include +#include + +/** + * Modbus RTU发送数据类 + * 主要实现了功能码 + */ +class Modbus_RTU_Sender : public QObject +{ +public: + explicit Modbus_RTU_Sender(QObject *parent); + ~Modbus_RTU_Sender(); + + + +}; + diff --git a/Modbus/src/modbus_err.cpp b/Modbus/src/modbus_err.cpp new file mode 100644 index 0000000..3ef5a83 --- /dev/null +++ b/Modbus/src/modbus_err.cpp @@ -0,0 +1,13 @@ +#include "../include/modbus_err.h" + +Modbus_Err::Modbus_Err(QObject *parent) + : QObject(parent) +{ + +} + +Modbus_Err::~Modbus_Err() +{ + +} + diff --git a/Modbus/src/modbus_log.cpp b/Modbus/src/modbus_log.cpp new file mode 100644 index 0000000..3df7a97 --- /dev/null +++ b/Modbus/src/modbus_log.cpp @@ -0,0 +1,13 @@ +#include "../include/modbus_log.h" + +Modbus_Log::Modbus_Log(QObject *parent) + : QObject(parent) +{ + +} + +Modbus_Log::~Modbus_Log() +{ + +} + diff --git a/Modbus/src/modbus_rtu_pkg.cpp b/Modbus/src/modbus_rtu_pkg.cpp new file mode 100644 index 0000000..1f24bb3 --- /dev/null +++ b/Modbus/src/modbus_rtu_pkg.cpp @@ -0,0 +1,129 @@ +#include "../include/modbus_rtu_pkg.h" + +Modbus_RTU_Pkg::Modbus_RTU_Pkg(QObject *parent) + : QObject(parent) +{ + +} + +Modbus_RTU_Pkg::~Modbus_RTU_Pkg() +{ + +} + +/** + * 构建Modbus RTU数据包 + * + * \param slave_addr + * \param func_code + * \param work_data + * \return + */ +QVector Modbus_RTU_Pkg::build_modbus_pkg( + quint8 slave_addr, + quint8 func_code, + const QVector& work_data +) +{ + QVector pkg; + + try { + // 添加设备地址 + pkg.append(slave_addr); + // 添加功能码 + pkg.append(func_code); + // 添加工作数据 + pkg.append(work_data); + + // 计算CRC + quint16 crc = calc_crc(pkg); + + // 添加CRC,小端序 + // 低字节 + pkg.append(static_cast(crc & 0xFF)); + // 高字节 + pkg.append(static_cast((crc >> 8) & 0xFF)); + } + catch (const std::exception& ex) { + // TODO:抛出异常 + + + } + + return pkg; +} + +/** + * 解析Modbus RTU数据包 + * + * \param pkg + * \param slave_addr + * \param func_code + * \param work_data + * \return + */ +bool Modbus_RTU_Pkg::parse_modbus_pkg( + const QVector& pkg, + quint8& slave_addr, + quint8& func_code, + QVector& work_data +) +{ + // 检查数据包长度 + if (pkg.size() < 4) + { + // TODO:抛出异常 + + return false; + } + + // 提取设备地址 + slave_addr = pkg[0]; + // 提取功能码 + func_code = pkg[1]; + // 提取工作数据 + work_data.clear(); + if (pkg.size() > 4) + { + work_data = pkg.mid(2, pkg.size() - 4); + } + // 提取数据包自带的CRC + quint16 crc_bring = static_cast(pkg[pkg.size() - 2]) | + (static_cast(pkg[pkg.size() - 1]) << 8); + // 计算接收数据CRC + QVector pkg_data = pkg.mid(0, pkg.size() - 2); + quint16 crc_after_calc = calc_crc(pkg_data); + // CRC校验 + if (crc_after_calc != crc_bring) + { + // TODO:抛出异常 + + return false; + } + + return true; +} + +/** + * 使用查表法计算CRC + * + * \param pkg_data + * \return + */ +quint16 Modbus_RTU_Pkg::calc_crc(const QVector& pkg_data) const +{ + static const quint16 crcTable[] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841 + }; + + quint16 crc = 0xFFFF; + for (int i = 0; i < pkg_data.size(); ++i) { + crc ^= static_cast(pkg_data[i]); + crc = (crc >> 8) ^ crcTable[crc & 0x0F]; + crc = (crc >> 8) ^ crcTable[crc & 0x0F]; + } + return crc; +} diff --git a/Modbus/src/modbus_rtu_receiver.cpp b/Modbus/src/modbus_rtu_receiver.cpp new file mode 100644 index 0000000..d52f898 --- /dev/null +++ b/Modbus/src/modbus_rtu_receiver.cpp @@ -0,0 +1,13 @@ +#include "../include/modbus_rtu_receiver.h" + +Modbus_RTU_Receiver::Modbus_RTU_Receiver(QObject *parent) + : QObject(parent) +{ + +} + +Modbus_RTU_Receiver::~Modbus_RTU_Receiver() +{ + +} + diff --git a/Modbus/src/modbus_rtu_sender.cpp b/Modbus/src/modbus_rtu_sender.cpp new file mode 100644 index 0000000..fe9e089 --- /dev/null +++ b/Modbus/src/modbus_rtu_sender.cpp @@ -0,0 +1,13 @@ +#include "../include/modbus_rtu_sender.h" + + +Modbus_RTU_Sender::Modbus_RTU_Sender(QObject* parent) + : QObject(parent) +{ +} + +Modbus_RTU_Sender::~Modbus_RTU_Sender() +{ + +} +