Реализация CRC4 в C
Я изменил реализацию, найденную здесь, чтобы построить функцию генерации таблиц для CRC4 следующим образом:
#define bufferSize 16
crc crcTable[bufferSize];
#define POLYNOMIAL 0x13
void Init()
{
crc remainder;
for(int dividend = 0; dividend < bufferSize; ++dividend)
{
remainder = dividend;
for(uint8_t bit = 8; bit > 0; --bit)
{
if(remainder & 1)
remainder = (remainder >> 1) ^ POLYNOMIAL;
else
remainder = (remainder >> 1);
}
crcTable[dividend] = remainder;
printf("%hu\n", remainder);
}
}
А затем рассчитайте CRC следующим образом:
uint8_t calc_crc4(uint8_t start_crc, uint8_t byte)
{
byte ^= start_crc;
start_crc = crcTable[byte] ^ (start_crc >> 8);
return start_crc;
}
Сгенерированный crcTable из:
/*
* Table based on Polynomial 0x13
*/
uint8_t crcTable[tableSize] = {
0x00, 0x0E, 0x1C, 0x12,
0x1F, 0x11, 0x03, 0x0D,
0x19, 0x17, 0x05, 0x0B,
0x06, 0x08, 0x1A, 0x14
};
Проблема заключается в том, что когда я запускаю его для файла ERF, ни одно из моих сгенерированных значений CRC не совпадает с теми, которые прикреплены к концу кадра ERF. Когда я печатаю значения, это выглядит как вызов crcTable[byte]
в calc_crc4
Функция почти всегда возвращает значение 0x00, но я недостаточно хорошо понимаю концепцию, чтобы понять, является ли это правильным значением или нет. Единственное, о чем я могу думать, это то, что он ничего не находит в индексной позиции байта, поэтому он возвращает 0x00. Я предполагал, что в CRC4 может быть только 16 значений, поэтому в этом месте должно быть что-то.
1 ответ
У вас нет полного определения желаемого CRC, и ваша попытка экстраполировать реализацию на четыре бита имеет много ошибок.
Прежде всего, вам нужно знать больше, чем полином. Вы должны знать, отражается ли CRC, также отражается ли выход, каково начальное значение регистра, и является ли выход исключительным или имеет какое-либо значение или нет.
Во-вторых, если вы обрабатываете байт за раз, в таблице должно быть 256 записей, независимо от длины CRC. Кроме того, каждая запись должна быть длиной CRC, в этом случае четыре бита, где у вас есть записи с пятью. Также вам нужно поместить CRC в соответствующий конец байта для первоначального исключения - или перед поиском таблицы, или сдвинуть таблицу. Как уже отмечалось, восьмибитное значение, сдвинутое вниз на восемь битов, равно нулю, поэтому исключающее-или-с этим ничего не дает.
В зависимости от рефлексии реализация четырехбитного CRC на основе таблиц может быть чем-то вроде этого.
static unsigned char const table_byte[256] = {
0x90, 0xa0, 0xf0, 0xc0, 0x50, 0x60, 0x30, 0x00, 0x20, 0x10, 0x40, 0x70, 0xe0,
0xd0, 0x80, 0xb0, 0xc0, 0xf0, 0xa0, 0x90, 0x00, 0x30, 0x60, 0x50, 0x70, 0x40,
0x10, 0x20, 0xb0, 0x80, 0xd0, 0xe0, 0x30, 0x00, 0x50, 0x60, 0xf0, 0xc0, 0x90,
0xa0, 0x80, 0xb0, 0xe0, 0xd0, 0x40, 0x70, 0x20, 0x10, 0x60, 0x50, 0x00, 0x30,
0xa0, 0x90, 0xc0, 0xf0, 0xd0, 0xe0, 0xb0, 0x80, 0x10, 0x20, 0x70, 0x40, 0xe0,
0xd0, 0x80, 0xb0, 0x20, 0x10, 0x40, 0x70, 0x50, 0x60, 0x30, 0x00, 0x90, 0xa0,
0xf0, 0xc0, 0xb0, 0x80, 0xd0, 0xe0, 0x70, 0x40, 0x10, 0x20, 0x00, 0x30, 0x60,
0x50, 0xc0, 0xf0, 0xa0, 0x90, 0x40, 0x70, 0x20, 0x10, 0x80, 0xb0, 0xe0, 0xd0,
0xf0, 0xc0, 0x90, 0xa0, 0x30, 0x00, 0x50, 0x60, 0x10, 0x20, 0x70, 0x40, 0xd0,
0xe0, 0xb0, 0x80, 0xa0, 0x90, 0xc0, 0xf0, 0x60, 0x50, 0x00, 0x30, 0x70, 0x40,
0x10, 0x20, 0xb0, 0x80, 0xd0, 0xe0, 0xc0, 0xf0, 0xa0, 0x90, 0x00, 0x30, 0x60,
0x50, 0x20, 0x10, 0x40, 0x70, 0xe0, 0xd0, 0x80, 0xb0, 0x90, 0xa0, 0xf0, 0xc0,
0x50, 0x60, 0x30, 0x00, 0xd0, 0xe0, 0xb0, 0x80, 0x10, 0x20, 0x70, 0x40, 0x60,
0x50, 0x00, 0x30, 0xa0, 0x90, 0xc0, 0xf0, 0x80, 0xb0, 0xe0, 0xd0, 0x40, 0x70,
0x20, 0x10, 0x30, 0x00, 0x50, 0x60, 0xf0, 0xc0, 0x90, 0xa0, 0x00, 0x30, 0x60,
0x50, 0xc0, 0xf0, 0xa0, 0x90, 0xb0, 0x80, 0xd0, 0xe0, 0x70, 0x40, 0x10, 0x20,
0x50, 0x60, 0x30, 0x00, 0x90, 0xa0, 0xf0, 0xc0, 0xe0, 0xd0, 0x80, 0xb0, 0x20,
0x10, 0x40, 0x70, 0xa0, 0x90, 0xc0, 0xf0, 0x60, 0x50, 0x00, 0x30, 0x10, 0x20,
0x70, 0x40, 0xd0, 0xe0, 0xb0, 0x80, 0xf0, 0xc0, 0x90, 0xa0, 0x30, 0x00, 0x50,
0x60, 0x40, 0x70, 0x20, 0x10, 0x80, 0xb0, 0xe0, 0xd0};
unsigned crc4interlaken(unsigned crc, void const *data, size_t len) {
if (data == NULL)
return 0;
crc &= 0xf;
crc <<= 4;
while (len--)
crc = table_byte[crc ^ *(unsigned char const *)data++];
crc >>= 4;
return crc;
}
или же
static unsigned char const table_byte[256] = {
0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6,
0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb,
0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5,
0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2, 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8,
0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0,
0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd,
0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3,
0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe,
0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa,
0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7,
0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9,
0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4,
0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc,
0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1,
0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf,
0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2};
unsigned crc4itu(unsigned crc, void const *data, size_t len) {
if (data == NULL)
return 0;
crc &= 0xf;
while (len--)
crc = table_byte[crc ^ *(unsigned char const *)data++];
return crc;
}
Этот код и таблицы были сгенерированы моим кодом crcany. Эти два CRC определены в каталоге Грега Кука, где эти два 4-битных определения CRC:
width=4 poly=0x3 init=0xf refin=false refout=false xorout=0xf check=0xb name="CRC-4/INTERLAKEN"
width=4 poly=0x3 init=0x0 refin=true refout=true xorout=0x0 check=0x7 name="CRC-4/ITU"