我有一些我需要测试的CRC方法。这些方法不是我自己写的。我能看到的最好方法是使用不同的技术实现CRC算法,然后比较结果。
目前,所有CRC例程都是以表驱动格式编写的。我似乎无法找到任何教程解释如何将代码转换为按位实现。我确信这是我对CRC的工作方式缺乏了解。
如果某人可以提供相同CRC例程的示例,则可以采用两种不同的方式。我在互联网上搜索过,但在我的问题上找不到太多帮助我的东西。
以下是我需要测试的一种CRC算法的示例代码:
// This table implements the EPO CRC16 algorithm with a polynomial of 0x17531
static const uint16 s_EPOCRC16Table[] =
{
0x0000U, 0x7531U, 0xEA62U, 0x9F53U, 0xA1F5U, 0xD4C4U, 0x4B97U, 0x3EA6U,
0x36DBU, 0x43EAU, 0xDCB9U, 0xA988U, 0x972EU, 0xE21FU, 0x7D4CU, 0x087DU,
0x6DB6U, 0x1887U, 0x87D4U, 0xF2E5U, 0xCC43U, 0xB972U, 0x2621U, 0x5310U,
0x5B6DU, 0x2E5CU, 0xB10FU, 0xC43EU, 0xFA98U, 0x8FA9U, 0x10FAU, 0x65CBU,
0xDB6CU, 0xAE5DU, 0x310EU, 0x443FU, 0x7A99U, 0x0FA8U, 0x90FBU, 0xE5CAU,
0xEDB7U, 0x9886U, 0x07D5U, 0x72E4U, 0x4C42U, 0x3973U, 0xA620U, 0xD311U,
0xB6DAU, 0xC3EBU, 0x5CB8U, 0x2989U, 0x172FU, 0x621EU, 0xFD4DU, 0x887CU,
0x8001U, 0xF530U, 0x6A63U, 0x1F52U, 0x21F4U, 0x54C5U, 0xCB96U, 0xBEA7U,
0xC3E9U, 0xB6D8U, 0x298BU, 0x5CBAU, 0x621CU, 0x172DU, 0x887EU, 0xFD4FU,
0xF532U, 0x8003U, 0x1F50U, 0x6A61U, 0x54C7U, 0x21F6U, 0xBEA5U, 0xCB94U,
0xAE5FU, 0xDB6EU, 0x443DU, 0x310CU, 0x0FAAU, 0x7A9BU, 0xE5C8U, 0x90F9U,
0x9884U, 0xEDB5U, 0x72E6U, 0x07D7U, 0x3971U, 0x4C40U, 0xD313U, 0xA622U,
0x1885U, 0x6DB4U, 0xF2E7U, 0x87D6U, 0xB970U, 0xCC41U, 0x5312U, 0x2623U,
0x2E5EU, 0x5B6FU, 0xC43CU, 0xB10DU, 0x8FABU, 0xFA9AU, 0x65C9U, 0x10F8U,
0x7533U, 0x0002U, 0x9F51U, 0xEA60U, 0xD4C6U, 0xA1F7U, 0x3EA4U, 0x4B95U,
0x43E8U, 0x36D9U, 0xA98AU, 0xDCBBU, 0xE21DU, 0x972CU, 0x087FU, 0x7D4EU,
0xF2E3U, 0x87D2U, 0x1881U, 0x6DB0U, 0x5316U, 0x2627U, 0xB974U, 0xCC45U,
0xC438U, 0xB109U, 0x2E5AU, 0x5B6BU, 0x65CDU, 0x10FCU, 0x8FAFU, 0xFA9EU,
0x9F55U, 0xEA64U, 0x7537U, 0x0006U, 0x3EA0U, 0x4B91U, 0xD4C2U, 0xA1F3U,
0xA98EU, 0xDCBFU, 0x43ECU, 0x36DDU, 0x087BU, 0x7D4AU, 0xE219U, 0x9728U,
0x298FU, 0x5CBEU, 0xC3EDU, 0xB6DCU, 0x887AU, 0xFD4BU, 0x6218U, 0x1729U,
0x1F54U, 0x6A65U, 0xF536U, 0x8007U, 0xBEA1U, 0xCB90U, 0x54C3U, 0x21F2U,
0x4439U, 0x3108U, 0xAE5BU, 0xDB6AU, 0xE5CCU, 0x90FDU, 0x0FAEU, 0x7A9FU,
0x72E2U, 0x07D3U, 0x9880U, 0xEDB1U, 0xD317U, 0xA626U, 0x3975U, 0x4C44U,
0x310AU, 0x443BU, 0xDB68U, 0xAE59U, 0x90FFU, 0xE5CEU, 0x7A9DU, 0x0FACU,
0x07D1U, 0x72E0U, 0xEDB3U, 0x9882U, 0xA624U, 0xD315U, 0x4C46U, 0x3977U,
0x5CBCU, 0x298DU, 0xB6DEU, 0xC3EFU, 0xFD49U, 0x8878U, 0x172BU, 0x621AU,
0x6A67U, 0x1F56U, 0x8005U, 0xF534U, 0xCB92U, 0xBEA3U, 0x21F0U, 0x54C1U,
0xEA66U, 0x9F57U, 0x0004U, 0x7535U, 0x4B93U, 0x3EA2U, 0xA1F1U, 0xD4C0U,
0xDCBDU, 0xA98CU, 0x36DFU, 0x43EEU, 0x7D48U, 0x0879U, 0x972AU, 0xE21BU,
0x87D0U, 0xF2E1U, 0x6DB2U, 0x1883U, 0x2625U, 0x5314U, 0xCC47U, 0xB976U,
0xB10BU, 0xC43AU, 0x5B69U, 0x2E58U, 0x10FEU, 0x65CFU, 0xFA9CU, 0x8FADU,
};
/**
* This routine returns the CRC-16 of Cp_ptr.
* This CRC routine is reversed to match the routine used in the EPO.
*
* @param const uint8 *Cp_ptr - data pointer to the bit string to be calculated over
* @param const uint32 Len - the number of bytes pointed to by Cp_ptr
* @return the calculated 16-bit CRC
* @ureq
* -# epoCRC16() shall calculate a 16-bit CRC on a block of data starting at an address of a specified length.
* -# epoCRC16() shall ASSERT if the passed in pointer is NULL.
*/
uint16 epoCRC16( const uint8 *Cp_ptr, const uint32 Len )
{
ASSERT( Cp_ptr != NULL );
// local variable
uint16 crc = 0x0;
// calculate the crc
for ( uint16 i = Len; i > 0; i-- )
{
const uint8 TableIndex = ( *Cp_ptr ^ static_cast<uint8>( crc >> 8 ) );
crc = static_cast<uint16>( crc << 8 );
crc = ( crc ^ s_EPOCRC16Table[TableIndex] );
Cp_ptr++;
}
return crc;
}
答案 0 :(得分:6)
首先需要CRC多项式,您可以在此类表的第二个条目或第128个条目中找到它,具体取决于CRC的位顺序。或者在这种情况下,您可以在评论0x17531
中找到它。 1
之后的x
存在多项式的第一项,它只是定义CRC的长度。它在计算中被删除。您可以在表格的第二个条目中找到0x7531
。
此例程(在C中)仅使用多项式生成上表:
void make_crc_table(unsigned poly, unsigned *table)
{
unsigned n, k, crc;
for (n = 0; n < 256; n++) {
crc = n << 8;
for (k = 0; k < 8; k++)
crc = crc & 0x8000 ? (crc << 1) ^ poly : crc << 1;
table[n] = crc & 0xffff;
}
}
因此会被调用:make_crc_table(0x7531, table)
其中table
是256个无符号整数的数组。
逐位CRC例程看起来大致相同:
unsigned epobit(unsigned char *buf, unsigned len, unsigned poly)
{
unsigned n, k, crc = 0;
for (n = len; n > 0; n--) {
crc ^= (*buf++ << 8);
for (k = 0; k < 8; k++)
crc = crc & 0x8000 ? (crc << 1) ^ poly : crc << 1;
}
return crc & 0xffff;
}
答案 1 :(得分:2)
对于工具,请查看pycrc,其中包含任意CRC的代码生成器。
有关CRC计算的说明,请参阅A Painless Guide to CRC Error Detection Algorithms。
答案 2 :(得分:0)
// Bitise and tablewise CRC-16 can be compared by following source code with polynomial 0x17531 !
// CRC.cpp :
//
#include "stdafx.h"
#include "CRC.h"
#include "afx.h"
#include <conio.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
using namespace std;
#define BUFLENGTH (0x100000*1) //0x100000=1MB
void makeCRC16Table();
void crc16update(unsigned short &crc0, const void *data, int length);
void crc16updateBitwise(unsigned short &crc0, const void *data, int length);
static byte crc8Table[256];
static unsigned short crc16Table[256];
static unsigned long crc32Table[256];
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
unsigned char crc8=0x00;
unsigned short crc16=0x0000;
unsigned long crc32=0x00000000;
byte *dataBuf = new byte[BUFLENGTH];
if(dataBuf==0)
{
cout<<"Not enough memory allocation to dataBuf[] !";
while(!_kbhit());
return nRetCode;
}
for(int i=0; i<BUFLENGTH; i++)
dataBuf[i]=i+1;
makeCRC16Table();
crc16=0x00;
crc16update(crc16, dataBuf, BUFLENGTH);
crc16=0x00;
crc16updateBitwise(crc16, dataBuf, BUFLENGTH);
delete[] dataBuf;
while(!_kbhit());
}
return nRetCode;
}
void makeCRC16Table()
{
/* generate a table for a byte-wise 16-bit CRC caculation on the polynomial ;
*/
CString soutputfile=_T("crc16Table.txt");
CString soutputbuffer;
CStdioFile fileTarget( soutputfile, CFile::modeCreate | CFile::modeWrite );
int i,j;
unsigned long poly, cc;
/* terms of polynomial defining this crc (except x^16) */
//static const byte pp[]={0,5,12};
static const byte pp[]={0,2,15};
/* make exclusive-or pattern from polynomial 0x1021 */
poly=0;
//for(i=0; i<sizeof(pp)/sizeof(byte); i++)
// poly|=1<<pp[i];
poly=0x7531;
//poly=0x1021;
//poly=0x8005;
for(i=0; i<256; i++) {
cc=i<<8;
for(j=0; j<8; j++) {
cc=(cc&0x8000)?(poly^(cc<<1)):(cc<<1); //MSB first transmission
}
crc16Table[i]=cc&0xffff;
soutputbuffer.Format("%3d:%04X\n", i, crc16Table[i]);
fileTarget.WriteString(soutputbuffer);
}
fileTarget.Close();
//ShellExecute(NULL, NULL, soutputfile, NULL, NULL, SW_SHOWNORMAL);
}
void crc16update(unsigned short &crc0, const void *data, int length)
{
CString soutputfile=_T("crc16.txt");
cout<<"\n"<<soutputfile<<"\n";
CString soutputbuffer, soutputbufferTotal;
CStdioFile fileTarget( soutputfile, CFile::modeCreate | CFile::modeWrite );
int percentage=0, ntemp;
unsigned short crc,crc1;
const unsigned char *buf=(const unsigned char *)data;
int i=0, j;
crc=crc0;
while(i<length)
{
ntemp=i/(length/100);
if(ntemp!=percentage)
{
soutputbuffer.Format("%d%% ", percentage );
cout<<soutputbuffer;
percentage=ntemp;
if(ntemp<0)
int nn=0;
}
crc1=crc;
j = ((crc >> 8) ^ buf[i]) & 0xff;
crc = (crc << 8) ^ crc16Table[j];
soutputbuffer.Format("%d:%02X:%04X>%04X\n", i, buf[i], crc1, crc );
fileTarget.WriteString(soutputbuffer);
i++;
}
soutputbuffer.Format("\n%04X>%04X", crc1, crc );
cout<<soutputbuffer;
crc0=crc;
fileTarget.Close();
//ShellExecute(NULL, NULL, soutputfile, NULL, NULL, SW_SHOWNORMAL);
}
void crc16updateBitwise(unsigned short &crc0, const void *data, int length)
{
CString soutputfile=_T("crc16BW.txt");
cout<<"\n"<<soutputfile<<"\n";
CString soutputbuffer;
CStdioFile fileTarget( soutputfile, CFile::modeCreate | CFile::modeWrite );
static const byte BitTable[]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
int percentage=0, ntemp;
unsigned long poly;
/* terms of polynomial defining this crc (except x^16) */
//static const byte pp[]={0,5,12};//CCITT
static const byte pp[]={0,2,15};//GENERAL
/* make exclusive-or pattern from polynomial 0x1021 */
int i;
poly=0;
//for(i=0; i<sizeof(pp)/sizeof(byte); i++)
// poly|=1<<pp[i];
//poly=0x8005;
poly=0x7531;
unsigned short crc,crc1;
const unsigned char *buf=(const unsigned char *)data;
byte a,b,c;
crc=crc0;
i=0;
while(i<length)
{
ntemp=i/(length/100);
if(ntemp!=percentage)
{
soutputbuffer.Format("%d%% ", percentage );
cout<<soutputbuffer;
percentage=ntemp;
}
crc1=crc;
for(int j=0; j<8; j++) {
a=(crc&0x8000)?1:0;//x^16
b=(buf[i]&BitTable[7-j])?1:0;////MSB first transmission
c=a^b;
crc=(c?(poly^(crc<<1)):(crc<<1))&0xffff;
}
soutputbuffer.Format("%d:%02X:%04X>%04X\n", i, buf[i], crc1&0xffff, crc&0xffff );
fileTarget.WriteString(soutputbuffer);
i++;
}
soutputbuffer.Format("\n%04X>%04X", crc1&0xffff, crc&0xffff );
cout<<soutputbuffer;
crc0=crc;
fileTarget.Close();
//ShellExecute(NULL, NULL, soutputfile, NULL, NULL, SW_SHOWNORMAL);
}