|
|
@@ -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; |
|
|
|
} |