1、CRC7的多项式和初始值
#define CRC_Hardware_POLYNOMIAL_7B 0x09
//硬件CRC多项式为0x09
//SD卡中的校验算法CRC7,生成多项式为x^7 + x^3 + 1,由于bit7不存在,只有bit3=1和bit0=1,所以多项式为0x09
#define CRC7_INIT_VALUE 0x00 //“CRC寄存器”的初始为0x00
2、软件CRC7校验
/* Table of CRC7 values */
const unsigned char CRC7_Table[] = {
0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,
0x19,0x10,0x0b,0x02,0x3d,0x34,0x2f,0x26,0x51,0x58,0x43,0x4a,0x75,0x7c,0x67,0x6e,
0x32,0x3b,0x20,0x29,0x16,0x1f,0x04,0x0d,0x7a,0x73,0x68,0x61,0x5e,0x57,0x4c,0x45,
0x2b,0x22,0x39,0x30,0x0f,0x06,0x1d,0x14,0x63,0x6a,0x71,0x78,0x47,0x4e,0x55,0x5c,
0x64,0x6d,0x76,0x7f,0x40,0x49,0x52,0x5b,0x2c,0x25,0x3e,0x37,0x08,0x01,0x1a,0x13,
0x7d,0x74,0x6f,0x66,0x59,0x50,0x4b,0x42,0x35,0x3c,0x27,0x2e,0x11,0x18,0x03,0x0a,
0x56,0x5f,0x44,0x4d,0x72,0x7b,0x60,0x69,0x1e,0x17,0x0c,0x05,0x3a,0x33,0x28,0x21,
0x4f,0x46,0x5d,0x54,0x6b,0x62,0x79,0x70,0x07,0x0e,0x15,0x1c,0x23,0x2a,0x31,0x38,
0x41,0x48,0x53,0x5a,0x65,0x6c,0x77,0x7e,0x09,0x00,0x1b,0x12,0x2d,0x24,0x3f,0x36,
0x58,0x51,0x4a,0x43,0x7c,0x75,0x6e,0x67,0x10,0x19,0x02,0x0b,0x34,0x3d,0x26,0x2f,
0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,
0x6a,0x63,0x78,0x71,0x4e,0x47,0x5c,0x55,0x22,0x2b,0x30,0x39,0x06,0x0f,0x14,0x1d,
0x25,0x2c,0x37,0x3e,0x01,0x08,0x13,0x1a,0x6d,0x64,0x7f,0x76,0x49,0x40,0x5b,0x52,
0x3c,0x35,0x2e,0x27,0x18,0x11,0x0a,0x03,0x74,0x7d,0x66,0x6f,0x50,0x59,0x42,0x4b,
0x17,0x1e,0x05,0x0c,0x33,0x3a,0x21,0x28,0x5f,0x56,0x4d,0x44,0x7b,0x72,0x69,0x60,
0x0e,0x07,0x1c,0x15,0x2a,0x23,0x38,0x31,0x46,0x4f,0x54,0x5d,0x62,0x6b,0x70,0x79
};
//函数功能:查表计算CRC7的值
unsigned char Get_CRC7( unsigned char *buff, int len)
{
uint16_t crc = CRC7_INIT_VALUE; //向“CRC寄存器”写入初始为0x00
unsigned int i= 0;
for (i=0; i < len; i++)
{
crc = CRC7_Table[(crc << 1) ^ buff[i]];
}
return crc;
}
3、生成CRC7的表格
#define TAB_LEN 256
//函数功能:生成CRC7的表
void Table_Gen8(void)
{
unsigned char ccitt7 = CRC_Hardware_POLYNOMIAL_7B; //x^7+x^3+1多项式的值为0x09
int i,j;
unsigned char tmp;
unsigned char data_Buff[TAB_LEN] = {0};
for(i=0;i<TAB_LEN;i++)
{
tmp = i;
for(j=0;j<8;j++)
{
if(tmp & 0x80) tmp ^= ccitt7;
tmp <<= 1;
}
data_Buff[i] = tmp>>1; //余数为7bit,计算中用了8bit,结尾多一位0要去掉
}
打印CRC7表//
for(i=0;i<TAB_LEN/8;i++)
{
for(j=0;j<8;j++) printf("0x%02x ",data_Buff[i*8+j]);
printf("\r\n");
}
printf("\r\n");
}
4、硬件CRC7
uint8_t Get_CRC7_A(uint8_t pBuffer[], uint8_t BufferLength)
{
CRC_HandleTypeDef hcrc;
uint8_t uwCRCValue;
__HAL_RCC_CRC_CLK_ENABLE();//使能CRC外设时钟
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;//告诉编译器将使用用户定义的“多项式”
hcrc.Init.GeneratingPolynomial = CRC_Hardware_POLYNOMIAL_7B;
//设置CRC_POL寄存器的值
//用户定义的“CRC多项式”,CRC_Hardware_POLYNOMIAL_16B是用户定义的“多项式”值
hcrc.Init.CRCLength = CRC_POLYLENGTH_7B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=11b,7位多项式
// hcrc.Init.CRCLength = CRC_POLYLENGTH_8B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=10b,8位多项式
// hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=01b,16位多项式
// hcrc.Init.CRCLength = CRC_POLYLENGTH_32B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=00b,32位多项式
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;//告诉编译器将使用用户定义的“CRC初始值”
hcrc.Init.InitValue=CRC7_INIT_VALUE;
//如果使用DEFAULT_INIT_VALUE_DISABLE,则使用hcrc.Init.InitValue的值配置RC_INIT寄存器Bits 31:0(CRC_INIT[31:0])
//用户定义的“CRC初始值”,User-defined CRC init value
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
//告诉后面的计算函数将对“16位字节的数据块”进行CRC计算,调用CRC_Handle_8()
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
//CRC_CR寄存器Bit6:5(REV_IN[1:0]),REV_IN[1:0]=00b,输入8位数据不执行“位反转”
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
//CRC_CR寄存器Bit7(REV_OUT),令REV_OUT=0,输出数据不执行“位反转”
HAL_CRC_Init(&hcrc);
uwCRCValue = HAL_CRC_Accumulate(&hcrc, (uint32_t *)pBuffer, BufferLength);
return(uwCRCValue);
}
uint8_t Get_CRC7_B(uint8_t pBuffer[], uint8_t BufferLength)
{
CRC_HandleTypeDef hcrc;
uint8_t uwCRCValue;
__HAL_RCC_CRC_CLK_ENABLE();//使能CRC外设时钟
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;//告诉编译器将使用用户定义的“多项式”
hcrc.Init.GeneratingPolynomial = CRC_Hardware_POLYNOMIAL_7B;
//设置CRC_POL寄存器的值
//用户定义的“CRC多项式”,CRC_Hardware_POLYNOMIAL_16B是用户定义的“多项式”值
hcrc.Init.CRCLength = CRC_POLYLENGTH_7B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=11b,7位多项式
// hcrc.Init.CRCLength = CRC_POLYLENGTH_8B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=10b,8位多项式
// hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=01b,16位多项式
// hcrc.Init.CRCLength = CRC_POLYLENGTH_32B;
//CRC_CR寄存器Bit4:3(REV_IN[1:0]),POLYSIZE[1:0]=00b,32位多项式
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;//告诉编译器将使用用户定义的“CRC初始值”
hcrc.Init.InitValue=CRC7_INIT_VALUE;
//如果使用DEFAULT_INIT_VALUE_DISABLE,则使用hcrc.Init.InitValue的值配置RC_INIT寄存器Bits 31:0(CRC_INIT[31:0])
//用户定义的“CRC初始值”,User-defined CRC init value
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
//告诉后面的计算函数将对“16位字节的数据块”进行CRC计算,调用CRC_Handle_8()
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
//CRC_CR寄存器Bit6:5(REV_IN[1:0]),REV_IN[1:0]=00b,输入8位数据不执行“位反转”
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
//CRC_CR寄存器Bit7(REV_OUT),令REV_OUT=0,输出数据不执行“位反转”
HAL_CRC_Init(&hcrc);
uwCRCValue = HAL_CRC_Calculate(&hcrc, (uint32_t *)pBuffer, BufferLength);
return(uwCRCValue);
}
5、测试结果
#define CRC7_DATA8_Size 9
uint8_t CRC7_DATA8[CRC7_DATA8_Size] = {0x4D,0x3C,0x2B,0x1A,0xBE,0x71,0xC9,0x8A,0x5E};
uint8_t uwExpectedCRCValue = 0x54;
void Test_CRC7(void)
{
uint32_t uwCRCValue;
uwCRCValue = Get_CRC7_A(CRC7_DATA8, CRC7_DATA8_Size);
printf("hCRC1=0x%x\r\n",uwCRCValue);
if (uwCRCValue != uwExpectedCRCValue)
{
printf("hCRC1 Error!\r\n");
}
uwCRCValue = Get_CRC7_B(CRC7_DATA8, CRC7_DATA8_Size);
printf("hCRC2=0x%x\r\n",uwCRCValue);
if (uwCRCValue != uwExpectedCRCValue)
{
printf("hCRC2 Error!\r\n");
}
uwCRCValue = Get_CRC7( CRC7_DATA8, CRC7_DATA8_Size);
printf("Software_CRC=0x%x\r\n",uwCRCValue);
if (uwCRCValue != uwExpectedCRCValue)
{
printf("Software_CRC Error!\r\n");
}
Table_Gen8();
}
6、CRC(循环冗余校验)在线计算
工具连接:CRC(循环冗余校验)在线计算_ip33.com