04.01_CRC-所有内置的CRC模型
测试步骤
先后计算01 02 03 04 05不同模型下的结果,然后和已知的CRC结果进行对比。
实测数据
| 参数模型 | 计算结果,数据:{1, 2, 3, 4, 5} | 测试结果 |
|---|---|---|
| CRC8 | 0xBC | 正确 |
| CRC8_ITU | 0xE9 | 正确 |
| CRC8_MAXIM | 0x2A | 正确 |
| CRC8_ROHC | 0xFE | 正确 |
| CRC16_IBM | 0xBB0E | 正确 |
| CRC16_MAXIM | 0x44F1 | 正确 |
| CRC16_USB | 0x44D5 | 正确 |
| CRC16_MODBUS | 0xBB2A | 正确 |
| CRC16_CCITT | 0xED9B | 正确 |
| CRC16_CCITT_FALSE | 0x9304 | 正确 |
| CRC16_X25 | 0x22EC | 正确 |
| CRC16_XMODEM | 0x8208 | 正确 |
| CRC16_DNP | 0xE674 | 正确 |
| CRC32 | 0x470B99F4 | 正确 |
| CRC32_MPEG_2 | 0xE28F4B83 | 正确 |
参考代码
04.01_CRC_Calc.c
/**
* @brief CRC-所有内置的CRC模型
* @details
* 先后计算01 02 03 04 05不同模型下的结果,然后和已知的CRC结果进行对比。
*/
#include "lks32mc09x_lib.h"
u8 crc_data[5] = {1, 2, 3, 4, 5};
volatile uint32_t crc8_answer, crc8_ITU_answer, crc8_ROHC_answer, crc8_MAXIM_answer;
volatile uint32_t crc16_IBM_answer, crc16_MAXIM_answer, crc16_USB_answer, crc16_MODBUS_answer, crc16_CCITT_answer, crc16_CCITT_FALSE_answer, crc16_X25_answer, crc16_XMODEM_answer, crc16_DNP_answer;
volatile uint32_t crc32_answer, crc32_MPEG_2_answer;
volatile uint32_t crc8_errflg = 0;
volatile uint32_t crc8_ITU_errflg = 0;
volatile uint32_t crc8_ROHC_errflg = 0;
volatile uint32_t crc8_MAXIM_errflg = 0;
volatile uint32_t crc16_IBM_errflg = 0;
volatile uint32_t crc16_MAXIM_errflg = 0;
volatile uint32_t crc16_USB_errflg = 0;
volatile uint32_t crc16_MODBUS_errflg = 0;
volatile uint32_t crc16_CCITT_errflg = 0;
volatile uint32_t crc16_CCITT_FALSE_errflg = 0;
volatile uint32_t crc16_X25_errflg = 0;
volatile uint32_t crc16_XMODEM_errflg = 0;
volatile uint32_t crc16_DNP_errflg = 0;
volatile uint32_t crc32_errflg = 0;
volatile uint32_t crc32_MPEG_2_errflg = 0;
int main(void)
{
crc8_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_8); ///< 计算CRC_8
crc8_ITU_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_8_ITU); ///< 计算CRC_8_ITU
crc8_ROHC_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_8_ROHC); ///< 计算CRC_8_ROHC
crc8_MAXIM_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_8_MAXIMx); ///< 计算CRC_8_MAXIMx
crc16_IBM_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_IBMx1); ///< 计算CRC_16_IBMx1
crc16_MAXIM_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_MAXIM); ///< 计算CRC_16_MAXIM
crc16_USB_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_USBx1); ///< 计算CRC_16_USBx1
crc16_MODBUS_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_MODBU); ///< 计算CRC_16_MODBU
crc16_CCITT_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_CCITT); ///< 计算CRC_16_CCITT
crc16_CCITT_FALSE_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_CCITT_FALSE); ///< 计算CRC_16_CCITT_FALSE
crc16_X25_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_X25); ///< 计算CRC_16_X25
crc16_XMODEM_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_XMODEM); ///< 计算CRC_16_XMODEM
crc16_DNP_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_16_DNP); ///< 计算CRC_16_DNP
crc32_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_32); ///< 计算CRC_32
crc32_MPEG_2_answer = CRC_CalcCommon(CRC0, crc_data, sizeof(crc_data), CRC_MODEL_CRC_32_MPEG_2); ///< 计算CRC_32_MPEG_2
if (crc8_answer != 0xbc)
{
crc8_errflg = 1;
}
if (crc8_ITU_answer != 0xe9)
{
crc8_ITU_errflg = 1;
}
if (crc8_ROHC_answer != 0xfe)
{
crc8_ROHC_errflg = 1;
}
if (crc8_MAXIM_answer != 0x2a)
{
crc8_MAXIM_errflg = 1;
}
if (crc16_IBM_answer != 0xbb0e)
{
crc16_IBM_errflg = 1;
}
if (crc16_MAXIM_answer != 0x44f1)
{
crc16_MAXIM_errflg = 1;
}
if (crc16_USB_answer != 0x44d5)
{
crc16_USB_errflg = 1;
}
if (crc16_MODBUS_answer != 0xbb2a)
{
crc16_MODBUS_errflg = 1;
}
if (crc16_CCITT_answer != 0xed9b)
{
crc16_CCITT_errflg = 1;
}
if (crc16_CCITT_FALSE_answer != 0x9304)
{
crc16_CCITT_FALSE_errflg = 1;
}
if (crc16_X25_answer != 0x22ec)
{
crc16_X25_errflg = 1;
}
if (crc16_XMODEM_answer != 0x8208)
{
crc16_XMODEM_errflg = 1;
}
if (crc16_DNP_answer != 0xe674)
{
crc16_DNP_errflg = 1;
}
if (crc32_answer != 0x470b99f4)
{
crc32_errflg = 1;
}
if (crc32_MPEG_2_answer != 0xe28f4b83)
{
crc32_MPEG_2_errflg = 1;
}
for (;;)
{
}
}
使用到的库函数
库函数部分代码
#define CRC0 ((CRC_TypeDef *)CRC0_BASE)
#define CRC_MODEL_CRC_16_CCITT 8
#define CRC_MODEL_CRC_16_CCITT_FALSE 9
#define CRC_MODEL_CRC_16_DNP 12
#define CRC_MODEL_CRC_16_MAXIM 5
#define CRC_MODEL_CRC_16_MODBU 7
#define CRC_MODEL_CRC_16_X25 10
#define CRC_MODEL_CRC_16_XMODEM 11
#define CRC_MODEL_CRC_32 13
#define CRC_MODEL_CRC_32_MPEG_2 14
#define CRC_MODEL_CRC_8 0
#define CRC_MODEL_CRC_8_ITU 1
#define CRC_MODEL_CRC_8_ROHC 2
#define CRC_WIDTH_16 1
#define CRC_WIDTH_32 0
#define CRC_WIDTH_7 3
#define CRC_WIDTH_8 2
#define REG_RESET(reg,mask) reg &= ~(mask)
#define REG_SET(reg,mask) reg |= (mask)
#define REG_WRITE(reg,mask) reg = (mask)
#define SYS0 ((SYS_TypeDef *)(SYS_BASE))
#define SYS_MODULE_CRC0 BIT16
/**
* @brief CRC初始化结构体
*/
typedef struct CRC_InitTypeDef {
uint32_t POLY;
uint32_t INIT;
uint32_t XOROUT;
uint8_t REFIN;
uint8_t REFOUT;
uint8_t WIDTH;
uint8_t null;
};
/**
* @brief CRC计算初始化
*/
void CRC_Init(CRC_TypeDef *CRCx, CRC_InitTypeDef *CRC_InitStruct)
{
if (CRC_InitStruct->WIDTH > 3)
{
switch (CRC_InitStruct->WIDTH)
{
case 7:
CRC_InitStruct->WIDTH = CRC_WIDTH_7;
break;
case 8:
CRC_InitStruct->WIDTH = CRC_WIDTH_8;
break;
case 16:
CRC_InitStruct->WIDTH = CRC_WIDTH_16;
break;
case 32:
CRC_InitStruct->WIDTH = CRC_WIDTH_32;
break;
default:
CRC_InitStruct->WIDTH = CRC_WIDTH_8;
break;
}
}
else
{
__NOP();
}
CRC_Enable(CRCx);
SYS_SoftResetModule(SYS_MODULE_CRC0);
CRC0_CR = (u32)(CRC_InitStruct->REFOUT << 12) | (u32)(CRC_InitStruct->REFIN << 8) | (u32)(CRC_InitStruct->WIDTH << 4);
CRC0_CR |= BIT0; // 复位
CRC0_POL = CRC_InitStruct->POLY;
CRC0_INIT = CRC_InitStruct->INIT;
if (CRC_InitStruct->WIDTH == CRC_WIDTH_16)
{
CRC_XOROUT = CRC_InitStruct->XOROUT << 16;
}
else
{
CRC_XOROUT = CRC_InitStruct->XOROUT;
}
}
/**
* @brief 使用常见模型计算CRC值
* @param CRCx CRC模块指针
* @param data 数据指针
* @param len 数据长度
* @param CRC_MODEL_x CRC模型
* @return 计算得到的CRC值
*/
uint32_t CRC_CalcCommon(CRC_TypeDef *CRCx, uint8_t *data, uint32_t len, uint16_t CRC_MODEL_x)
{
u32 val;
CRC_InitTypeDef CRC_InitStruct;
switch (CRC_MODEL_x)
{
case CRC_MODEL_CRC_8: // 8 07 00 00 false false
CRC_InitStruct.WIDTH = CRC_WIDTH_8; // 宽度
CRC_InitStruct.POLY = 0x07; // 多项式
CRC_InitStruct.INIT = 0x00; // 初始值
CRC_InitStruct.XOROUT = 0x00; // 结果异或值
CRC_InitStruct.REFIN = DISABLE; // 输入数据反转
CRC_InitStruct.REFOUT = DISABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_8_ITU: // 8 07 00 55 false false
CRC_InitStruct.WIDTH = CRC_WIDTH_8; // 宽度
CRC_InitStruct.POLY = 0x07; // 多项式
CRC_InitStruct.INIT = 0x00; // 初始值
CRC_InitStruct.XOROUT = 0x55; // 结果异或值
CRC_InitStruct.REFIN = DISABLE; // 输入数据反转
CRC_InitStruct.REFOUT = DISABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_8_ROHC: // 8 07 FF 00 true true
CRC_InitStruct.WIDTH = CRC_WIDTH_8; // 宽度
CRC_InitStruct.POLY = 0x07; // 多项式
CRC_InitStruct.INIT = 0xff; // 初始值
CRC_InitStruct.XOROUT = 0x00; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_8_MAXIMx: // 8 31 00 00 true true
CRC_InitStruct.WIDTH = CRC_WIDTH_8; // 宽度
CRC_InitStruct.POLY = 0x31; // 多项式
CRC_InitStruct.INIT = 0x00; // 初始值
CRC_InitStruct.XOROUT = 0x00; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_IBMx1: // 16 8005 0000 0000 true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x8005; // 多项式
CRC_InitStruct.INIT = 0x0000; // 初始值
CRC_InitStruct.XOROUT = 0x0000; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_MAXIM: // 16 8005 0000 FFFF true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x8005; // 多项式
CRC_InitStruct.INIT = 0x0000; // 初始值
CRC_InitStruct.XOROUT = 0xffff; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_USBx1: // 16 8005 FFFF FFFF true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x8005; // 多项式
CRC_InitStruct.INIT = 0xffff; // 初始值
CRC_InitStruct.XOROUT = 0xffff; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_MODBU: // 16 8005 FFFF 0000 true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x8005; // 多项式
CRC_InitStruct.INIT = 0xffff; // 初始值
CRC_InitStruct.XOROUT = 0x0000; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_CCITT: // 16 1021 0000 0000 true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x1021; // 多项式
CRC_InitStruct.INIT = 0x0000; // 初始值
CRC_InitStruct.XOROUT = 0x0000; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_CCITT_FALSE: // 16 1021 FFFF 0000 false false
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x1021; // 多项式
CRC_InitStruct.INIT = 0xffff; // 初始值
CRC_InitStruct.XOROUT = 0x0000; // 结果异或值
CRC_InitStruct.REFIN = DISABLE; // 输入数据反转
CRC_InitStruct.REFOUT = DISABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_X25: // 16 1021 FFFF FFFF true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x1021; // 多项式
CRC_InitStruct.INIT = 0xffff; // 初始值
CRC_InitStruct.XOROUT = 0xffff; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_XMODEM: // 16 1021 0000 0000 false false
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x1021; // 多项式
CRC_InitStruct.INIT = 0x0000; // 初始值
CRC_InitStruct.XOROUT = 0x0000; // 结果异或值
CRC_InitStruct.REFIN = DISABLE; // 输入数据反转
CRC_InitStruct.REFOUT = DISABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_16_DNP: // 16 3D65 0000 FFFF true true
CRC_InitStruct.WIDTH = CRC_WIDTH_16; // 宽度
CRC_InitStruct.POLY = 0x3d65; // 多项式
CRC_InitStruct.INIT = 0x0000; // 初始值
CRC_InitStruct.XOROUT = 0xffff; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_32: // 32 04C11DB7 FFFFFFFF FFFFFFFF true true
CRC_InitStruct.WIDTH = CRC_WIDTH_32; // 宽度
CRC_InitStruct.POLY = 0x04C11DB7; // 多项式
CRC_InitStruct.INIT = 0xFFFFFFFF; // 初始值
CRC_InitStruct.XOROUT = 0xFFFFFFFF; // 结果异或值
CRC_InitStruct.REFIN = ENABLE; // 输入数据反转
CRC_InitStruct.REFOUT = ENABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
case CRC_MODEL_CRC_32_MPEG_2: // 32 04C11DB7 FFFFFFFF 00000000 false false
CRC_InitStruct.WIDTH = CRC_WIDTH_32; // 宽度
CRC_InitStruct.POLY = 0x04C11DB7; // 多项式
CRC_InitStruct.INIT = 0xFFFFFFFF; // 初始值
CRC_InitStruct.XOROUT = 0x00000000; // 结果异或值
CRC_InitStruct.REFIN = DISABLE; // 输入数据反转
CRC_InitStruct.REFOUT = DISABLE; // 输出数据反转
CRC_Init(CRCx, &CRC_InitStruct);
break;
}
val = CRC_Calc(CRCx, data, len);
if (CRC_InitStruct.REFOUT)
{
switch (CRC_InitStruct.WIDTH)
{
case CRC_WIDTH_8:
val >>= 24;
break;
case CRC_WIDTH_16:
val >>= 16;
break;
default:
break;
}
}
else
{
__NOP();
}
return val;
}
/**
* @brief 使能CRC模块
* @param CRCx CRC模块指针
*/
void CRC_Enable(CRC_TypeDef *CRCx)
{
if (CRCx == CRC0)
{
SYS_ModuleClockCmd(SYS_MODULE_CRC0, ENABLE);
}
else
{
__NOP();
}
}
/**
* @brief 数字模块时钟使能
* @param nModule 模块编号
* @param state 使能或禁用状态
*/
void SYS_ModuleClockCmd(uint32_t nModule, uint8_t state)
{
REG_WRITE(SYS0->PROTECT, 0x7a83);
if (state)
{
REG_SET(SYS0->CLK_FEN, nModule);
}
else
{
REG_RESET(SYS0->CLK_FEN, nModule);
}
REG_WRITE(SYS0->PROTECT, 0);
}
/**
* @brief 计算CRC值
* @param CRCx CRC模块指针
* @param data 数据指针
* @param len 数据长度
* @return 计算得到的CRC值
*/
uint32_t CRC_Calc(CRC_TypeDef *CRCx, uint8_t *data, uint32_t len)
{
u32 val;
if (len == 0)
{
return 0;
}
else
{
while ((len--) != 0)
{
REG8(&CRCx->DR) = *data;
data++;
}
}
val = (REG32(&CRCx->DR)) ^ CRC_XOROUT;
return val;
}
/**
* @brief 软复位模块
* @param nModule 模块编号
*/
void SYS_SoftResetModule(uint32_t nModule)
{
REG_WRITE(SYS0->PROTECT, 0x7a83);
REG_SET(SYS0->SFT_RST, nModule);
REG_RESET(SYS0->SFT_RST, nModule); // 触发复位后需清除复位位
REG_WRITE(SYS0->PROTECT, 0);
}