Потребовалось вычислять контрольную сумму по алгоритму CRC для пакетов данных, передаваемых по протоколу ModBus. В интернете есть функция вычисления CRC16, но её пришлось немного переделать, чтобы результат получался с нужным порядком следования байтов (протокол ModBus требует BigEndian).
CRC16 с BigEndian для ModBus в Qt
#include <QtEndian>
...
QByteArray MainWindow::CRC16_ModBusRTU(QByteArray buf, quint16 len) {
//Вычисляет контрольную сумму CRC16 для ModBus и выдаёт её с нужным порядком байтов
quint8 tmp[len];
for(int a=0;a<len;a++) {
tmp[a]= buf[a];
}
unsigned int crc = 0xFFFF;
for (int pos = 0; pos < len; pos++) {
crc ^= (unsigned int)tmp[pos];
for (int i = 8; i != 0; i--) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return QByteArray::number(qToBigEndian<quint16>(crc), 16);
}
Пример использования
QByteArray MainWindow::formatCmd(QByteArray hex) {
//Принимает команду вида "00 02 00 01 00 18", отдаёт байтовый массив, пригодный для отправки
//в COM-порт, с уже добавленной к команде контрольной суммой
QByteArray data = QByteArray::fromHex(hex);
return data.append(QByteArray::fromHex(CRC16_ModBusRTU(data, data.length())));
}