@@ -95,12 +95,22 @@ | |||||
<QtRcc Include="resources\modbus.qrc" /> | <QtRcc Include="resources\modbus.qrc" /> | ||||
<QtUic Include="ui\modbus.ui" /> | <QtUic Include="ui\modbus.ui" /> | ||||
<QtMoc Include="include\modbus.h" /> | <QtMoc Include="include\modbus.h" /> | ||||
<ClCompile Include="src\modbus_err.cpp" /> | |||||
<ClCompile Include="src\modbus_rtu_receiver.cpp" /> | |||||
<ClCompile Include="src\modbus_log.cpp" /> | |||||
<ClCompile Include="src\modbus_rtu_pkg.cpp" /> | |||||
<ClCompile Include="src\modbus_rtu_sender.cpp" /> | |||||
<ClCompile Include="src\modbus.cpp" /> | <ClCompile Include="src\modbus.cpp" /> | ||||
<ClCompile Include="src\main.cpp" /> | <ClCompile Include="src\main.cpp" /> | ||||
<None Include="resources\Modbus.ico" /> | <None Include="resources\Modbus.ico" /> | ||||
<ResourceCompile Include="resources\Modbus.rc" /> | <ResourceCompile Include="resources\Modbus.rc" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<QtMoc Include="include\modbus_log.h" /> | |||||
<QtMoc Include="include\modbus_rtu_receiver.h" /> | |||||
<QtMoc Include="include\modbus_err.h" /> | |||||
<ClInclude Include="include\modbus_rtu_sender.h" /> | |||||
<QtMoc Include="include\modbus_rtu_pkg.h" /> | |||||
<ClInclude Include="x64\Debug\qt\uic\ui_modbus.h" /> | <ClInclude Include="x64\Debug\qt\uic\ui_modbus.h" /> | ||||
</ItemGroup> | </ItemGroup> | ||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
@@ -46,10 +46,42 @@ | |||||
<ClCompile Include="src\main.cpp"> | <ClCompile Include="src\main.cpp"> | ||||
<Filter>Source Files</Filter> | <Filter>Source Files</Filter> | ||||
</ClCompile> | </ClCompile> | ||||
<ClCompile Include="src\modbus_rtu_sender.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="src\modbus_rtu_pkg.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="src\modbus_log.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="src\modbus_rtu_receiver.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
<ClCompile Include="src\modbus_err.cpp"> | |||||
<Filter>Source Files</Filter> | |||||
</ClCompile> | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ClInclude Include="x64\Debug\qt\uic\ui_modbus.h"> | <ClInclude Include="x64\Debug\qt\uic\ui_modbus.h"> | ||||
<Filter>Header Files</Filter> | <Filter>Header Files</Filter> | ||||
</ClInclude> | </ClInclude> | ||||
<ClInclude Include="include\modbus_rtu_sender.h"> | |||||
<Filter>Header Files</Filter> | |||||
</ClInclude> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<QtMoc Include="include\modbus_rtu_pkg.h"> | |||||
<Filter>Header Files</Filter> | |||||
</QtMoc> | |||||
<QtMoc Include="include\modbus_log.h"> | |||||
<Filter>Header Files</Filter> | |||||
</QtMoc> | |||||
<QtMoc Include="include\modbus_rtu_receiver.h"> | |||||
<Filter>Header Files</Filter> | |||||
</QtMoc> | |||||
<QtMoc Include="include\modbus_err.h"> | |||||
<Filter>Header Files</Filter> | |||||
</QtMoc> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
@@ -0,0 +1,13 @@ | |||||
#pragma once | |||||
#include <QObject> | |||||
class Modbus_Err : public QObject | |||||
{ | |||||
Q_OBJECT | |||||
public: | |||||
Modbus_Err(QObject *parent); | |||||
~Modbus_Err(); | |||||
}; | |||||
@@ -0,0 +1,17 @@ | |||||
#pragma once | |||||
#include <QObject> | |||||
/** | |||||
* . | |||||
*/ | |||||
class Modbus_Log : public QObject | |||||
{ | |||||
Q_OBJECT | |||||
public: | |||||
Modbus_Log(QObject *parent); | |||||
~Modbus_Log(); | |||||
}; | |||||
@@ -0,0 +1,43 @@ | |||||
#pragma once | |||||
#include <QObject> | |||||
#include <QVector> | |||||
#include <QByteArray> | |||||
#include <QtEndian> | |||||
#include <QDebug> | |||||
/** | |||||
* 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<quint8> build_modbus_pkg( | |||||
quint8 slave_addr, | |||||
quint8 func_code, | |||||
const QVector<quint8>& work_data | |||||
); | |||||
// 解析Modbus RTU数据包 | |||||
bool parse_modbus_pkg( | |||||
const QVector<quint8> &pkg, | |||||
quint8 &slave_addr, | |||||
quint8 &func_code, | |||||
QVector<quint8> &work_data | |||||
); | |||||
private: | |||||
// 计算Modbus CRC16 | |||||
quint16 calc_crc(const QVector<quint8>& pkg_data) const; | |||||
}; | |||||
@@ -0,0 +1,13 @@ | |||||
#pragma once | |||||
#include <QObject> | |||||
class Modbus_RTU_Receiver : public QObject | |||||
{ | |||||
Q_OBJECT | |||||
public: | |||||
Modbus_RTU_Receiver(QObject *parent); | |||||
~Modbus_RTU_Receiver(); | |||||
}; | |||||
@@ -0,0 +1,20 @@ | |||||
#pragma once | |||||
#include <QObject> | |||||
#include <QVector> | |||||
#include <QByteArray> | |||||
/** | |||||
* Modbus RTU发送数据类 | |||||
* 主要实现了功能码 | |||||
*/ | |||||
class Modbus_RTU_Sender : public QObject | |||||
{ | |||||
public: | |||||
explicit Modbus_RTU_Sender(QObject *parent); | |||||
~Modbus_RTU_Sender(); | |||||
}; | |||||
@@ -0,0 +1,13 @@ | |||||
#include "../include/modbus_err.h" | |||||
Modbus_Err::Modbus_Err(QObject *parent) | |||||
: QObject(parent) | |||||
{ | |||||
} | |||||
Modbus_Err::~Modbus_Err() | |||||
{ | |||||
} | |||||
@@ -0,0 +1,13 @@ | |||||
#include "../include/modbus_log.h" | |||||
Modbus_Log::Modbus_Log(QObject *parent) | |||||
: QObject(parent) | |||||
{ | |||||
} | |||||
Modbus_Log::~Modbus_Log() | |||||
{ | |||||
} | |||||
@@ -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<quint8> Modbus_RTU_Pkg::build_modbus_pkg( | |||||
quint8 slave_addr, | |||||
quint8 func_code, | |||||
const QVector<quint8>& work_data | |||||
) | |||||
{ | |||||
QVector<quint8> 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<quint8>(crc & 0xFF)); | |||||
// 高字节 | |||||
pkg.append(static_cast<quint8>((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<quint8>& pkg, | |||||
quint8& slave_addr, | |||||
quint8& func_code, | |||||
QVector<quint8>& 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<quint16>(pkg[pkg.size() - 2]) | | |||||
(static_cast<quint16>(pkg[pkg.size() - 1]) << 8); | |||||
// 计算接收数据CRC | |||||
QVector<quint8> 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<quint8>& 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<quint16>(pkg_data[i]); | |||||
crc = (crc >> 8) ^ crcTable[crc & 0x0F]; | |||||
crc = (crc >> 8) ^ crcTable[crc & 0x0F]; | |||||
} | |||||
return crc; | |||||
} |
@@ -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() | |||||
{ | |||||
} | |||||
@@ -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() | |||||
{ | |||||
} | |||||