通用CRC算法
我正在尝试制定一种通用的 CRC 算法,可用于各种长度(例如 4、5、6、8、16、32 位)。
我已经设法从 Ross Williams 网站 掌握基础知识,但是当遇到各种不同的实现时诸如 CRC-6/CDMA2000-A 之类的算法,在纸面上使用通用算法和我的算法所做的事情是相同的,但不应该与 CRC-6 的特定实现进行比较。
此外,我将我的输出与一些网站进行了比较,例如这个网站,并尝试通过以下方式稍微调整我的代码它如何显示在那里的实现,但我得出的结论是,从我的角度来看,它无法正常工作。
我将在下面发布我的代码以及 CRC-6 的构造方式 通用 CRC
typedef struct
{
uint8 *CRC_Start_Address;
uint32 CRC_Message_Length_In_Bytes;
uint32 CRC_Polynomial;
uint32 CRC_Initial_Remainder;
uint32 CRC_Final_XOR_Val;
uint32 CRC_Reflect_Data;
uint32 CRC_Reflect_Remainder;
uint32 CRC_Width_Of_Poly;
uint32 CRC_Topbit; // = (1<<(CRC_Width_Of_Poly -1 )) ;
uint32 CRC_Mask;
} CRC_Custom_Poly_Type;
CRC_Custom_Poly_Type CRC;
uint32 CRC_CrcCustomPolyTest(uint32 StartAddr, uint32 Length, uint8 SeedValue, uint8 Polynomial)
{
CRC.CRC_Start_Address = (uint8 *)StartAddr;
CRC.CRC_Message_Length_In_Bytes = (uint32)Length;
CRC.CRC_Initial_Remainder = SeedValue;
CRC.CRC_Polynomial = Polynomial;
CRC.CRC_Reflect_Data = FALSE;
CRC.CRC_Reflect_Remainder = FALSE;
CRC.CRC_Final_XOR_Val = 0x0;
CRC.CRC_Width_Of_Poly = 6;
CRC.CRC_Topbit = 1U << (CRC.CRC_Width_Of_Poly - 1U);
CRC.CRC_Mask = (1U << CRC.CRC_Width_Of_Poly) - 1U;
uint8 addrIndex;
uint32 byteIndex;
uint8 copyByteIndex;
if (CRC.CRC_Reflect_Data == TRUE)
{
CRC.CRC_Polynomial = reflect(CRC.CRC_Polynomial, CRC.CRC_Width_Of_Poly);
CRC.CRC_Initial_Remainder = reflect(CRC.CRC_Initial_Remainder, CRC.CRC_Width_Of_Poly);
CRC.CRC_Final_XOR_Val = reflect(CRC.CRC_Final_XOR_Val, CRC.CRC_Width_Of_Poly);
}
for (byteIndex = 0U; byteIndex < CRC.CRC_Message_Length_In_Bytes; byteIndex++)
{
// reflection
copyByteIndex = CRC.CRC_Start_Address[byteIndex];
if (CRC.CRC_Reflect_Data == TRUE)
{
CRC.CRC_Initial_Remainder ^= ((CRC.CRC_Start_Address[byteIndex]));
for (addrIndex = 0; addrIndex < 8; ++addrIndex)
{
uint32 isSetAndReflection;
if (CRC.CRC_Width_Of_Poly < 8)
{
isSetAndReflection = (CRC.CRC_Initial_Remainder & 1U) ^ (copyByteIndex & 0x01);
copyByteIndex >>= 1U;
}
else
{
isSetAndReflection = CRC.CRC_Initial_Remainder & 1U;
}
CRC.CRC_Initial_Remainder >>= 1U;
if (isSetAndReflection)
{
CRC.CRC_Initial_Remainder ^= CRC.CRC_Polynomial;
}
CRC.CRC_Initial_Remainder = CRC.CRC_Initial_Remainder & CRC.CRC_Mask;
}
}
// no reflection
else
{
if (CRC.CRC_Width_Of_Poly > 8U)
{
CRC.CRC_Initial_Remainder ^= (uint32)(CRC.CRC_Start_Address[byteIndex]) >> (CRC.CRC_Width_Of_Poly - 8U);
}
else
{
CRC.CRC_Initial_Remainder ^= ((CRC.CRC_Start_Address[byteIndex]));
}
for (addrIndex = 0; addrIndex < 8; ++addrIndex)
{
uint32 isSetNoReflection;
if (CRC.CRC_Width_Of_Poly < 8U)
{
isSetNoReflection = ((CRC.CRC_Initial_Remainder & CRC.CRC_Topbit) );//^ ((copyByteIndex & 0x80) >> (8U - CRC.CRC_Width_Of_Poly)));
//copyByteIndex <<= 1U;
}
else if (CRC.CRC_Width_Of_Poly == 8U)
{
isSetNoReflection = CRC.CRC_Initial_Remainder & 0x80;
}
else // if (CRC.CRC_Width_Of_Poly > 8U)
{
isSetNoReflection = CRC.CRC_Initial_Remainder & CRC.CRC_Mask;
}
CRC.CRC_Initial_Remainder <<= 1U;
if (isSetNoReflection)
{
CRC.CRC_Initial_Remainder ^= CRC.CRC_Polynomial;
}
CRC.CRC_Initial_Remainder &= CRC.CRC_Mask;
}
}
}
CRC.CRC_Initial_Remainder = CRC.CRC_Initial_Remainder ^ CRC.CRC_Final_XOR_Val;
return CRC.CRC_Initial_Remainder;
}
uint32 reflect(uint32 StartAddr, uint32 Length)
{
uint32 reflection = 0x00000000;
uint8 bit;
/*
* Reflect the data about the center bit.
*/
for (bit = 0; bit < Length; ++bit)
{
/*
* If the LSB bit is set, set the reflection of it.
*/
if (StartAddr & 0x01)
{
reflection |= (1U << ((Length - 1U) - bit));
}
StartAddr = (StartAddr >> 1U);
}
return (reflection);
} /* reflect() */
输入:0x120000 输出:0x08 预期输出:0x30
CRC-6
/* Apply the basic 6-Bit CRC formula for the 2 bits left(slower): */
/* - Polynomial generator = X^6+X^5+X^2+X+1 */
/* - Input bit = B */
/* - New ShiftReg[0] = ShiftReg[5] XOR B */
/* - New ShiftReg[1] = (ShiftReg[5] XOR B) XOR ShiftReg[0] */
/* - New ShiftReg[2] = (ShiftReg[5] XOR B) XOR ShiftReg[1] */
/* - New ShiftReg[3] = ShiftReg[2] */
/* - New ShiftReg[4] = ShiftReg[3] */
/* - New ShiftReg[5] = (ShiftReg[5] XOR B) XOR ShiftReg[4] */
输入:0x120000 输出:0x30
我想知道的是:
- 我的算法是否有问题,不符合 CRC 的基本概念?
- 有没有可能的方法来推广算法以便在不同的宽度上工作?如果不是,为什么,即使从硬件角度来看这是一种不同的方式?
I am trying to make an universally CRC algorithm that can be used for various lengths (e.g. 4, 5, 6, 8, 16, 32 bits).
I've manage to grasp the basics from Ross Williams site but when confronted with different implementation of various algorithms such as CRC-6/CDMA2000-A, on paper using the general algorithm and what my algorithm does it's the same thing, but not as it should be compared to a specific implementation of CRC-6.
Moreover I've compared my output to some sites such as this site and tried to adapt my code a little by how it shows the implementation on there, but I've come to the conclusion that, from my point of view, it's not working properly.
I'll post below my code and how an CRC-6 is constructed
General CRC
typedef struct
{
uint8 *CRC_Start_Address;
uint32 CRC_Message_Length_In_Bytes;
uint32 CRC_Polynomial;
uint32 CRC_Initial_Remainder;
uint32 CRC_Final_XOR_Val;
uint32 CRC_Reflect_Data;
uint32 CRC_Reflect_Remainder;
uint32 CRC_Width_Of_Poly;
uint32 CRC_Topbit; // = (1<<(CRC_Width_Of_Poly -1 )) ;
uint32 CRC_Mask;
} CRC_Custom_Poly_Type;
CRC_Custom_Poly_Type CRC;
uint32 CRC_CrcCustomPolyTest(uint32 StartAddr, uint32 Length, uint8 SeedValue, uint8 Polynomial)
{
CRC.CRC_Start_Address = (uint8 *)StartAddr;
CRC.CRC_Message_Length_In_Bytes = (uint32)Length;
CRC.CRC_Initial_Remainder = SeedValue;
CRC.CRC_Polynomial = Polynomial;
CRC.CRC_Reflect_Data = FALSE;
CRC.CRC_Reflect_Remainder = FALSE;
CRC.CRC_Final_XOR_Val = 0x0;
CRC.CRC_Width_Of_Poly = 6;
CRC.CRC_Topbit = 1U << (CRC.CRC_Width_Of_Poly - 1U);
CRC.CRC_Mask = (1U << CRC.CRC_Width_Of_Poly) - 1U;
uint8 addrIndex;
uint32 byteIndex;
uint8 copyByteIndex;
if (CRC.CRC_Reflect_Data == TRUE)
{
CRC.CRC_Polynomial = reflect(CRC.CRC_Polynomial, CRC.CRC_Width_Of_Poly);
CRC.CRC_Initial_Remainder = reflect(CRC.CRC_Initial_Remainder, CRC.CRC_Width_Of_Poly);
CRC.CRC_Final_XOR_Val = reflect(CRC.CRC_Final_XOR_Val, CRC.CRC_Width_Of_Poly);
}
for (byteIndex = 0U; byteIndex < CRC.CRC_Message_Length_In_Bytes; byteIndex++)
{
// reflection
copyByteIndex = CRC.CRC_Start_Address[byteIndex];
if (CRC.CRC_Reflect_Data == TRUE)
{
CRC.CRC_Initial_Remainder ^= ((CRC.CRC_Start_Address[byteIndex]));
for (addrIndex = 0; addrIndex < 8; ++addrIndex)
{
uint32 isSetAndReflection;
if (CRC.CRC_Width_Of_Poly < 8)
{
isSetAndReflection = (CRC.CRC_Initial_Remainder & 1U) ^ (copyByteIndex & 0x01);
copyByteIndex >>= 1U;
}
else
{
isSetAndReflection = CRC.CRC_Initial_Remainder & 1U;
}
CRC.CRC_Initial_Remainder >>= 1U;
if (isSetAndReflection)
{
CRC.CRC_Initial_Remainder ^= CRC.CRC_Polynomial;
}
CRC.CRC_Initial_Remainder = CRC.CRC_Initial_Remainder & CRC.CRC_Mask;
}
}
// no reflection
else
{
if (CRC.CRC_Width_Of_Poly > 8U)
{
CRC.CRC_Initial_Remainder ^= (uint32)(CRC.CRC_Start_Address[byteIndex]) >> (CRC.CRC_Width_Of_Poly - 8U);
}
else
{
CRC.CRC_Initial_Remainder ^= ((CRC.CRC_Start_Address[byteIndex]));
}
for (addrIndex = 0; addrIndex < 8; ++addrIndex)
{
uint32 isSetNoReflection;
if (CRC.CRC_Width_Of_Poly < 8U)
{
isSetNoReflection = ((CRC.CRC_Initial_Remainder & CRC.CRC_Topbit) );//^ ((copyByteIndex & 0x80) >> (8U - CRC.CRC_Width_Of_Poly)));
//copyByteIndex <<= 1U;
}
else if (CRC.CRC_Width_Of_Poly == 8U)
{
isSetNoReflection = CRC.CRC_Initial_Remainder & 0x80;
}
else // if (CRC.CRC_Width_Of_Poly > 8U)
{
isSetNoReflection = CRC.CRC_Initial_Remainder & CRC.CRC_Mask;
}
CRC.CRC_Initial_Remainder <<= 1U;
if (isSetNoReflection)
{
CRC.CRC_Initial_Remainder ^= CRC.CRC_Polynomial;
}
CRC.CRC_Initial_Remainder &= CRC.CRC_Mask;
}
}
}
CRC.CRC_Initial_Remainder = CRC.CRC_Initial_Remainder ^ CRC.CRC_Final_XOR_Val;
return CRC.CRC_Initial_Remainder;
}
uint32 reflect(uint32 StartAddr, uint32 Length)
{
uint32 reflection = 0x00000000;
uint8 bit;
/*
* Reflect the data about the center bit.
*/
for (bit = 0; bit < Length; ++bit)
{
/*
* If the LSB bit is set, set the reflection of it.
*/
if (StartAddr & 0x01)
{
reflection |= (1U << ((Length - 1U) - bit));
}
StartAddr = (StartAddr >> 1U);
}
return (reflection);
} /* reflect() */
Input: 0x120000
Output: 0x08
Output to be expected: 0x30
CRC-6
/* Apply the basic 6-Bit CRC formula for the 2 bits left(slower): */
/* - Polynomial generator = X^6+X^5+X^2+X+1 */
/* - Input bit = B */
/* - New ShiftReg[0] = ShiftReg[5] XOR B */
/* - New ShiftReg[1] = (ShiftReg[5] XOR B) XOR ShiftReg[0] */
/* - New ShiftReg[2] = (ShiftReg[5] XOR B) XOR ShiftReg[1] */
/* - New ShiftReg[3] = ShiftReg[2] */
/* - New ShiftReg[4] = ShiftReg[3] */
/* - New ShiftReg[5] = (ShiftReg[5] XOR B) XOR ShiftReg[4] */
Input: 0x120000
Output: 0x30
All I want to find out is:
- If is something wrong with my algorithm which does not correspond to the basic concept of CRC?
- Is there any possible way to generalize the algorithm in order to work on different widths ? if not why, even it's a different way form the hardware perspective?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论