CRC校验

CRC校验

本文只说明如何实现CRC-8,其它参数模型解释请看其它大佬的文章
模二运算相关内容不再赘述

动画推荐

B站up
【[CRC校验]手算与直观演示】 https://www.bilibili.com/video/BV1V4411Z7VA/?share_source=copy_web&vd_source=734d9fe130776e8ae82b2b5371a5f5b8

CRC校验网站推荐

http://www.ip33.com/crc.html

一个大佬的文章

他代码本人看不懂,不知道他是如何实现的。

https://blog.youkuaiyun.com/u013073067/article/details/86621770

本人代码

思路就是动画里这个
在这里插入图片描述
就跟“流”进来数据似的
关键就是,将变量CRC左移1位,最低位补入1比特新的数据(来自需要校验的字符串str)

/**
 * 左移一位并补充最后一位的数据.
 *
 * \param D_now 当前字节指针
 * \param D_next 下一字节
 * \param i 序号
 * \note 在循环中使用
 */
void left_and_supply(uint8_t* crc, uint8_t data, int i);

void left_and_supply(uint8_t* D_now, uint8_t D_next, int i)
{
    (*D_now) <<= 1;
    if (D_next & (0x80 >> i))
        (*D_now) |= 0x01;    
}

这样使用这个函数

uint8_t arr[4] = { 0x31, 0x32, 0x33, 0x34 };

uint8_t temp = arr[0];
uint8_t* p = arr;
for (; p < &arr[3]; )
{
	p++;
	for (int i = 0; i < 8; i++)
	{
		left_and_supply(&temp, *p, i);
		printf("  i = %d  ", i); binPrintf(temp); printf(" %#0X\n", temp);
	}
	puts("");
}

binPrintf()调试用的,二进制打印一个字节

/*
* @brief 调试用二进制打印一个字节
*/
void binPrintf(uint8_t binData)
{
    for (int i = 0; i < 8; i++)
    {
        if (binData & (0x80 >> i))
            putchar('1');
        else
            putchar('0');
    }
}

测试结果为
i = 0 01100010 0X62
……
i = 7 00110010 0X32

i = 0 01100100 0X64
……
i = 7 00110011 0X33

i = 0 01100110 0X66
……
i = 7 00110100 0X34

CRC-8校验实现
有了准备可容易实现

注意,它多项式为x8 + x2 + x + 1,也就是 1 0000 0111
做模二除法时“找到开头的1”然后后面异或就行。
在这里插入图片描述
所以

#define POLY_8 0x07 //0000 0111
void myCRC_8(const void* pStart, size_t count, void* pResult)
{
    uint8_t* pEnd = (uint8_t*)pStart + count - 1;
    uint8_t* p = (uint8_t*)pStart;
    uint8_t crc = *p; 
    int i;

    for (; p < pEnd; )
    {
        p++;
        for (i = 0; i < 8; i++)                //循环8位 
        {
            if (crc & 0x80)//最高位为1,应当再次左移后与多项式异或
            {
                left_and_supply(&crc, *p, i);
                crc ^= POLY_8;
            }
            else
            {
                left_and_supply(&crc, *p, i);
            }
        }
    }

    uint8_t tem = 0x00;//补8个0
    p = &tem;
    for (i = 0; i < 8; i++)                //循环8位 
    {
        if (crc & 0x80)//最高位为1,应当再次左移后与多项式异或
        {
            left_and_supply(&crc, *p, i);
            crc ^= POLY_8;
        }
        else                               //否则直接左移
        {
            left_and_supply(&crc, *p, i);
        }
    }
    *((uint8_t*)pResult) = crc;
}

当然,那个函数可以直接写进去
得到最终代码

/**
 * @brief CRC-8校验
 * 
 * @param pStart 校验数据起始位置
 * @param count 校验数据长度
 * @param pResult 校验码保存位置
 */
void CRC_8(const void* pStart, size_t count, void* pResult);
 
void CRC_8(const void* pStart, size_t count, void* pResult)
{
    uint8_t* pEnd = (uint8_t*)pStart + count - 1;//数据结束位置
    uint8_t* p = (uint8_t*)pStart;
    uint8_t crc = *p; 
    int i;

    for (; p < pEnd; )
    {
        p++;
        for (i = 0; i < 8; i++)//循环8位 
        {
            if (crc & 0x80)//最高位为1,应当再次左移后与多项式异或
            {
                crc <<= 1;
                if (*p & (0x80 >> i))
                    crc |= 0x01;
                crc ^= POLY_8;
            }
            else
            {
                crc <<= 1;
                if (*p & (0x80 >> i))
                    crc |= 0x01;
            }
        }
    }

    uint8_t tem = 0x00;//补8个0
    p = &tem;
    for (i = 0; i < 8; i++)//循环8位 
    {
        if (crc & 0x80)//最高位为1,应当再次左移后与多项式异或
        {
            crc <<= 1;
            if (*p & (0x80 >> i))
                crc |= 0x01;
            crc ^= POLY_8;
        }
        else//否则直接左移
        {
            crc <<= 1;
            if (*p & (0x80 >> i))
                crc |= 0x01;
        }
    }
    *((uint8_t*)pResult) = crc;
}

其它

谁能解释一下大佬的代码是怎么实现的,真看不懂
https://blog.youkuaiyun.com/u013073067/article/details/86621770
直接左移是补0呀……

#define POLY_8 0x07 //0000 0111
void bigCRC_8(const void* pStart, size_t count, void* pResult)
{
    uint8_t crc = 0x00;                   //初始值
    uint8_t* p = (uint8_t*)pStart;
    uint8_t* pEnd = (uint8_t*)pStart + count - 1;
    int i;
    for (; p<=pEnd; p++)
    {        
        crc ^= *p;                    //与crc初始值异或
        for (i = 0; i < 8; i++)       //循环8位 
        {
            if (crc & 0x80)           //左移移出的位为1,左移后与多项式异或
            {
                crc <<= 1;
                crc ^= POLY_8;
            }
            else                      //否则直接左移
            {
                crc <<= 1;
            }
        }

    }

    *((uint8_t*)pResult) = crc;
}

?????

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

菜哥万岁万岁万万岁

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

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

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

打赏作者

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

抵扣说明:

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

余额充值