|
|
@@ -0,0 +1,98 @@ |
|
|
|
#include "../include/modbus_master.h" |
|
|
|
|
|
|
|
Modbus_Master::Modbus_Master(QObject *parent) |
|
|
|
: QObject(parent) |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Modbus_Master::~Modbus_Master() |
|
|
|
{ |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
QByteArray Modbus_Master::build_modbus_pkg(quint8 slave_addr, quint8 func_code, const QByteArray & work_data) |
|
|
|
{ |
|
|
|
QByteArray 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; |
|
|
|
} |
|
|
|
|
|
|
|
bool Modbus_Master::parse_modbus_pkg(const QByteArray& pkg, quint8& slave_addr, quint8& func_code, QByteArray& 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 |
|
|
|
QByteArray 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; |
|
|
|
} |
|
|
|
|
|
|
|
quint16 Modbus_Master::calc_crc(const QByteArray& 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; |
|
|
|
} |
|
|
|
|