从现有的 crc 函数生成 crc16 查找 table
Generate crc16 lookup table from existing crc function
我在一个项目中工作,其中有一个计算 CRC16 校验和的函数。
uint16_t x_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal = (unsigned char) (CrcVal >> 8) | (CrcVal << 8);
CrcVal ^= DataIn;
CrcVal ^= (unsigned char) (CrcVal & 0xff) >> 4;
CrcVal ^= (CrcVal << 8) << 4;
CrcVal ^= ((CrcVal & 0xff) << 4) << 1;
return CrcVal &0xFFFF;
}
并且是这样使用的:
uint8_t x[]={1,2,3,4,5,6,7,8,9,0};
uint16_t CrcResult=0;
for (size_t i = 0; i<10; i++) {
CrcResult = x_crc(CrcResult, *(x + i));
}
printf("\n\n\nCRC1 = 0x%04X\n",CrcResult);
由于性能问题,我需要转换为查找 table。我该怎么做,使用上面的函数生成条目?
谢谢。
由于移位实现,不清楚这是一个多项式为0x11021的左移CRC。示例代码包括一个由 16 位 table 驱动的 256。我认为编译器优化将内联 z_crc,也就是 table。如果不是,则将函数更改为采用 3 个参数,crcvalue、缓冲区指针、字节数。
#include <stdio.h>
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
uint16_t crctbl[256];
uint16_t x_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal = (unsigned char)(CrcVal>>8)|(CrcVal<<8); /* rotate left 8 bits */
/* crc ^= (byte*0x10000)>>16 */
CrcVal ^= DataIn; /* crc ^= (byte*0x0001) */
CrcVal ^= (unsigned char)(CrcVal&0xff)>>4; /* crc ^= ((crc&0xf0)*0x1000)>>16 */
CrcVal ^= (CrcVal<<8)<<4; /* crc ^= ((crc&0x0f)*0x1000) */
CrcVal ^= ((CrcVal&0xff)<<4)<<1; /* crc ^= ((crc&0xff)*0x0020) */
return CrcVal; /* 0x1021 */
}
uint16_t y_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal ^= ((uint16_t)DataIn) << 8;
for (uint16_t i = 0; i < 8; i++)
CrcVal = (CrcVal&0x8000)?(CrcVal<<1)^0x1021:(CrcVal << 1);
return CrcVal;
}
void inittbl()
{
for (uint16_t j = 0; j < 256; j++)
crctbl[j] = x_crc(0, (uint8_t)j);
}
uint16_t z_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal = crctbl[(CrcVal>>8)^DataIn]^(CrcVal<<8);
return CrcVal;
}
int main()
{
uint16_t crcx = 0;
uint16_t crcy = 0;
uint16_t crcz = 0;
uint8_t x[]={1,2,3,4,5,6,7,8,9,0};
inittbl();
for(size_t i = 0; i<10; i++)
crcx = x_crc(crcx, *(x + i));
for(size_t i = 0; i<10; i++)
crcy = y_crc(crcy, *(x + i));
for(size_t i = 0; i<10; i++)
crcz = z_crc(crcz, *(x + i));
if (crcx == crcy && crcx == crcz)
printf("match\n");
return 0;
}
我在一个项目中工作,其中有一个计算 CRC16 校验和的函数。
uint16_t x_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal = (unsigned char) (CrcVal >> 8) | (CrcVal << 8);
CrcVal ^= DataIn;
CrcVal ^= (unsigned char) (CrcVal & 0xff) >> 4;
CrcVal ^= (CrcVal << 8) << 4;
CrcVal ^= ((CrcVal & 0xff) << 4) << 1;
return CrcVal &0xFFFF;
}
并且是这样使用的:
uint8_t x[]={1,2,3,4,5,6,7,8,9,0};
uint16_t CrcResult=0;
for (size_t i = 0; i<10; i++) {
CrcResult = x_crc(CrcResult, *(x + i));
}
printf("\n\n\nCRC1 = 0x%04X\n",CrcResult);
由于性能问题,我需要转换为查找 table。我该怎么做,使用上面的函数生成条目?
谢谢。
由于移位实现,不清楚这是一个多项式为0x11021的左移CRC。示例代码包括一个由 16 位 table 驱动的 256。我认为编译器优化将内联 z_crc,也就是 table。如果不是,则将函数更改为采用 3 个参数,crcvalue、缓冲区指针、字节数。
#include <stdio.h>
typedef unsigned short uint16_t;
typedef unsigned char uint8_t;
uint16_t crctbl[256];
uint16_t x_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal = (unsigned char)(CrcVal>>8)|(CrcVal<<8); /* rotate left 8 bits */
/* crc ^= (byte*0x10000)>>16 */
CrcVal ^= DataIn; /* crc ^= (byte*0x0001) */
CrcVal ^= (unsigned char)(CrcVal&0xff)>>4; /* crc ^= ((crc&0xf0)*0x1000)>>16 */
CrcVal ^= (CrcVal<<8)<<4; /* crc ^= ((crc&0x0f)*0x1000) */
CrcVal ^= ((CrcVal&0xff)<<4)<<1; /* crc ^= ((crc&0xff)*0x0020) */
return CrcVal; /* 0x1021 */
}
uint16_t y_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal ^= ((uint16_t)DataIn) << 8;
for (uint16_t i = 0; i < 8; i++)
CrcVal = (CrcVal&0x8000)?(CrcVal<<1)^0x1021:(CrcVal << 1);
return CrcVal;
}
void inittbl()
{
for (uint16_t j = 0; j < 256; j++)
crctbl[j] = x_crc(0, (uint8_t)j);
}
uint16_t z_crc(uint16_t CrcVal, uint8_t DataIn) {
CrcVal = crctbl[(CrcVal>>8)^DataIn]^(CrcVal<<8);
return CrcVal;
}
int main()
{
uint16_t crcx = 0;
uint16_t crcy = 0;
uint16_t crcz = 0;
uint8_t x[]={1,2,3,4,5,6,7,8,9,0};
inittbl();
for(size_t i = 0; i<10; i++)
crcx = x_crc(crcx, *(x + i));
for(size_t i = 0; i<10; i++)
crcy = y_crc(crcy, *(x + i));
for(size_t i = 0; i<10; i++)
crcz = z_crc(crcz, *(x + i));
if (crcx == crcy && crcx == crcz)
printf("match\n");
return 0;
}