Cómo calcular el CRC en el protocolo RFID
Pregunta
Al leer datos de un dispositivo RFID se encuentra un CRC-CCITT sobre la carga útil. "El CRC se inicializa con 0x3791 en lugar del valor habitual 0xFFFF." ¿Cómo puedo definir la función, que comprueba que el CRC está bien.
muestra
data: { 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0xA0 }
CRC: {0x60, 0xE7}
otra muestra
data: { 0x02, 0x41, 0x00, 0x00, 0x00, 0x00, 0xA4 }
CRC: {0x6F, 0xA5}
Solución
La única manera de que pudiera conseguir esto para trabajo era mediante la aplicación del algoritmo de bit por bit (TMS37157 ficha técnica de la Figura 52).
UINT16 rfid_get_crc(const UINT8 * data, INT8 size)
{
static BOOL lsb;
static BOOL rxdt;
static UINT16 crc;
static UINT8 bits;
static UINT8 byte;
static UINT8 i;
const UINT16 RFID_CRC_INIT = 0x3791;
crc = RFID_CRC_INIT;
for (i=0; i<size; i++)
{
bits = 8;
byte = data[i]; // Next byte
while (bits --> 0)
{
lsb = crc & 1; // Store LSB
crc >>= 1; // Shift right 1 bit
rxdt = byte & 1;
if (rxdt)
crc |= 0x8000; // Shift in next bit
if (lsb) // Check stored LSB
crc ^= 0x8000; // Invert MSB
if (0x8000 == (crc & 0x8000)) // Check MSB
crc ^= 0x0408; // Invert bits 3 and 10
byte >>= 1; // Next bit
}
}
return crc;
}
Otros consejos
Una implementación más compacto (en código de pseudo) es:
// Least significant bit first (little-endian)
// x^16+x^12+x^5+1 = 1000 0100 0000 1000 (1) = 0x8408
function crc(byte array string[1..len], int len) {
//Other RFID tags I have seen use initialization of 0x0000:
//rem := 0x3791;
rem := 0x3791;
for i from 1 to len {
rem := rem xor string[i]
for j from 1 to 8 { // Assuming 8 bits per byte
if rem and 0x0001 { // if rightmost (most significant) bit is set
rem := (rem rightShift 1) xor 0x8408
} else {
rem := rem rightShift 1
}
}
}
// A popular variant complements rem here
return rem
Esto se puede encontrar en el Código Fragmento de 5:
http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks