Calculating Modbus RTU CRC 16
unsigned int CRC16_2(unsigned char *buf, int len)
{
unsigned int crc = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
crc ^= (unsigned int)buf[pos]; // XOR byte into least sig. byte of crc
for (int i = 8; i != 0; i--) { // Loop over each bit
if ((crc & 0x0001) != 0) { // If the LSB is set
crc >>= 1; // Shift right and XOR 0xA001
crc ^= 0xA001;
}
else // Else LSB is not set
crc >>= 1; // Just shift right
}
}
return crc;
}
im kind of a noob myself, butttt-
i used the code u provided and tested it myself, and as u said it didnt work right, but then i realized it was passing hex chars, so i just changed uint to char and it checks out for me at least.
i even calculated a sample by hand to double check.
According to MODBUS over serial line specification and implementation guide V1.02, the CRC is sent little-endian (low byte first).
I have no idea, though, how you came up with needing any hexadecimal bytes for the CRC. MODBUS RTU is a binary protocol, and the CRC is sent as two bytes, not as four hexadecimal digits!
Here's how you'd do it, using the CRC16 function you provided.
QByteArray makeRTUFrame(int slave, int function, const QByteArray & data) {
Q_ASSERT(data.size() <= 252);
QByteArray frame;
QDataStream ds(&frame, QIODevice::WriteOnly);
ds.setByteOrder(QDataStream::LittleEndian);
ds << quint8(slave) << quint8(function);
ds.writeRawData(data.constData(), data.size());
int const crc = CRC16((BYTE*)frame.constData(), frame.size());
ds << quint16(crc);
return frame;
}