C语言计算任意多项式的CRC7、CRC8和CRC16的程序代码

三种CRC校验其实大体上都是相同的,就是几个参数不同而已:

#include <stdint.h>
#include <stdio.h>

#define POLYNOMIAL_CRC7 0x89ul
#define POLYNOMIAL_CRC8 0x131
#define POLYNOMIAL_CRC16 0x11021ul

/* 计算CRC7校验码 */
uint8_t calc_crc7(const void *data, int len)
{
	const uint8_t *p = data;
	int i, j;
	uint16_t temp = 0;

	if (len != 0)
		temp = p[0] << 8;

	for (i = 1; i <= len; i++)
	{
		if (i != len)
			temp |= p[i];
		for (j = 0; j < 8; j++)
		{
			if (temp & 0x8000)
				temp ^= POLYNOMIAL_CRC7 << 8;
			temp <<= 1;
		}
	}
	return temp >> 9;
}

/* 计算CRC8校验码 */
uint8_t calc_crc8(const void *data, int len)
{
	const uint8_t *p = data;
	int i, j;
	uint16_t temp = 0;

	if (len != 0)
		temp = p[0] << 8;

	for (i = 1; i <= len; i++)
	{
		if (i != len)
			temp |= p[i];
		for (j = 0; j < 8; j++)
		{
			if (temp & 0x8000)
				temp ^= POLYNOMIAL_CRC8 << 7;
			temp <<= 1;
		}
	}
	return temp >> 8;
}

/* 计算CRC16校验码 */
uint16_t calc_crc16(const void *data, int len)
{
	const uint8_t *p = data;
	int i, j;
	uint32_t temp = 0;

	if (len & 1)
	{
		printf("%s: data size %d is odd!\n", __FUNCTION__, len);
		len--; // 不允许出现奇数长度
	}
	if (len != 0)
		temp = (p[0] << 24) | (p[1] << 16); // 填充前二分之一
	if (len > 2)
		temp |= p[2] << 8; // 填充到四分之三

	for (i = 3; i <= len + 2; i++)
	{
		if (i < len)
			temp |= p[i]; // 每次都填充最后四分之一的空间
		
		// 从左数第0~7位计算到左数第16~23位
		for (j = 0; j < 8; j++)
		{
			if (temp & 0x80000000)
				temp ^= POLYNOMIAL_CRC16 << 15;
			temp <<= 1;
		}
	}
	return temp >> 16;
}

/* 计算CRC时翻转字节位 */
uint8_t invert_byte(uint8_t byte)
{
	int i;
	uint8_t value = 0;
	
	for (i = 0; i < 8; i++)
	{
		if (byte & (1 << i))
			value |= 1 << (7 - i);
	}
	return value;
}

/* 计算CRC8Inv校验码 */
uint8_t calc_crc8_inv(const void *data, int len)
{
	const uint8_t *p = data;
	int i, j;
	uint16_t temp = 0;

	if (len != 0)
		temp = invert_byte(p[0]) << 8; // 输入数据反转(REFIN)

	for (i = 1; i <= len; i++)
	{
		if (i != len)
			temp |= invert_byte(p[i]);
		for (j = 0; j < 8; j++)
		{
			if (temp & 0x8000)
				temp ^= POLYNOMIAL_CRC8 << 7;
			temp <<= 1;
		}
	}
	return invert_byte(temp >> 8); // 输出数据反转(REFOUT)
}

int main(void)
{
	uint8_t data[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef};

	printf("CRC7: 0x%02x\n", calc_crc7(data, sizeof(data)));
	printf("CRC8: 0x%02x\n", calc_crc8(data, sizeof(data)));
	printf("CRC16: 0x%04x\n", calc_crc16(data, sizeof(data)));

	printf("CRC8Inv: 0x%02x\n", calc_crc8_inv(data, sizeof(data)));

	return 0;
}

程序运行结果:

CRC7: 0x7f
CRC8: 0x22
CRC16: 0x2fbc
CRC8Inv: 0xbe

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
CRC(Cyclic Redundancy Check,循环冗余校验)是一种常见的数据错误检测方法,用于验证传输或存储的数据是否完整无误。在C语言中,CRC8和CRC16是两种常用的CRC校验算法,它们分别基于8位和16位的二进制计算。 **CRC8计算:** CRC8通常使用的是X.128标准,采用一位多项式除法。计算过程涉及到对数据逐位进行异或操作,并根据特定的生成多项式更新一个寄存器值。C语言库中可能没有内置函数直接计算CRC8,但你可以手动编写一个函数,例如使用奇偶检验位的方式来进行。 ```c // 示例函数,假设生成多项式为0x31 (0b00100001) uint8_t crc8(uint8_t data[], int length, uint8_t poly) { uint8_t crc = 0; for (int i = 0; i < length; i++) { crc ^= data[i]; for (int j = 0; j < 8; j++) { if (crc & 0x80) { crc = (crc << 1) ^ poly; } else { crc <<= 1; } } } return crc; } ``` **CRC16计算:** CRC16使用的是一些固定的16位生成多项式,比如CRC-CCITT或CRC-16/ANSI。C语言库提供了如`ccitt_crc16`这样的函数来方便计算,通常用於处理网络数据包、文件系统等。 ```c #include <stdlib.h> uint16_t crc16(uint16_t data[], int length, uint16_t init_val, uint16_t poly) { uint16_t crc = init_val; for (int i = 0; i < length; i++) { crc = crc16_table[(crc >> 8) ^ data[i]] ^ (crc & 0xff); crc = (crc >> 8) ^ crc16_table[crc & 0xff]; } return crc; } ``` 在这个例子中,`crc16_table`是一个预计算好的CRC-CCITT表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巨大八爪鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值