Nuestros mejores desarrolladores han agotado sus provisiones de café, investigando todo el tiempo por la respuesta, hasta que Andrea halló la contestación en Beanstalk por lo tanto ahora la compartimos contigo.
Solución:
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;
Soy un poco novato yo mismo, butttt-
Utilicé el código que proporcionaste y lo probé yo mismo, y como dijiste, no funcionó bien, pero luego me di cuenta de que estaba pasando caracteres hexadecimales, así que simplemente cambié uint a char y al menos me verificó.
incluso calculé una muestra a mano para verificar dos veces.
De acuerdo con MODBUS sobre la guía de implementación y especificación de línea serie V1.02, el CRC se envía little-endian (primer byte bajo).
Sin embargo, no tengo idea de cómo llegaste a necesitar bytes hexadecimales para el CRC. MODBUS RTU es un protocolo binario y el CRC se envía como dos bytes, no como cuatro dígitos hexadecimales.
Así es como lo haría, usando la función CRC16 que proporcionó.
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;
Intenté usar el primer ejemplo de código que publicaste aquí (el que usa la tabla) y descubrí que hay un error al usar index. Para que el código funcione correctamente, debe acceder a la tabla en el área limitada por su tamaño.
wCRCWord ^= wCRCTable[(nTemp & 0xFF)];
Entonces, el código completo que devuelve el valor correcto de CRC16 para MODBUS se enumera a continuación. El número devuelto ya ha cambiado el byte Lo y Hi.
WORD CRC16 (const BYTE *nData, WORD wLength)
static const WORD wCRCTable[] =
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,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 ;
BYTE nTemp;
WORD wCRCWord = 0xFFFF;
while (wLength--)
nTemp = *nData++ ^ wCRCWord;
wCRCWord >>= 8;
wCRCWord ^= wCRCTable[(nTemp & 0xFF)];
return wCRCWord;
// End: CRC16