CRC校验原理简述及python代码实现CRC检验误码

CRC循环原理简述

要理解CRC的运算过程,先要了解模2运算,这是CRC编码中的运算规则。
在这里插入图片描述

也就是说,模2运算就是对两个长度相同的二进制数进行异或运算(不进位借位的运算)。

CRC的运算过程核心是模二除法,模2除法具有下列三个性质:

当最后余数的位数小于除数位数时,除法停止。
当被除数的位数小于除数位数时,则商数为0,被除数就是余数。
只要被除数或部分余数的位数与除数一样多,且最高位为1,不管其他位是什么数,皆可商1。

接下来给出一个简单的CRC编码的实例
在这里插入图片描述

除数与被除数最高几位(与除数位数相同)做异或,商1。(除数首位必须为1)
余数先去掉首位,若此时余数最高位为1,商1,并对以它为除数继续模2除。
若最高位为0,则商0,重复步骤2。
直到余数位数小于除数位数时,运算结束

在需要加密的数据(图片里的数据桢)后面添加模二取余的余数(FCS、冗余码)得到密文(图片里的传输帧)

解码:
在这里插入图片描述
解密过程和加密过程类似,用需要解密的数据对除数做模2除法,如果余数为0,则代码没有检测出错误(有可能发生了错误但刚好余数也为0)

python代码实现CRC检验误码

CRC检验流程:一个数据帧在发送方进行编码得到传输帧,再通过接收端检查(余数为0)说明数据传输无误
误码概述:如果在传输的过程中数据帧m发生变化,经过编码得到的传输帧在接收端检查余数还为0

代码概述:

  • 1、定义函数XOR进行模二运算
    传入参数str1,str2分别是被除数和除数。
    返回分为首位为0和首位为1俩种情况
  • 2、定义函数CRC_Encoding进行编码
    传入参数分别是数据帧m和除数p
    返回传输帧(数据帧+FCS)
  • 3、定义函数CRC_Decoding进行解码
    传入参数传输帧除数p
    返回余数与0的布尔值
  为什么不直接用python中^运算符呢?
   方便后面解码和编码中的模二除法运算,如果被除数首位为0,用0进行补位
def XOR(str1, str2):    #实现模2加法
    ans = ''
    if str1[0] == '0':
        return '0', str1[1:]
    else:
        for i in range(len(str1)):
            if (str1[i] == '0' and str2[i] == '0'):
                ans = ans + '0'
            elif (str1[i] == '1' and str2[i] == '1'):
                ans = ans + '0'
            else:
                ans = ans + '1'
    return '1', ans[1:]
                

def CRC_Encoding(str1,str2):    #CRC编码  原字符串加上模二取余(FCS) 传入参数分别是数据帧m和除数p
    lenght = len(str2)
    str3 = str1 + '0'*(lenght-1)
    ans = ''
    yus = str3[0:lenght]
    for i in range(len(str1)):         #模二除法  补位
        str4,yus = XOR(yus, str2)
        ans = ans+str4
        if i == len(str1)-1:
            break
        else:
            yus = yus+str3[i+lenght]
    ans = str1 + yus
    return ans                        #返回传输帧  数据帧+余数(FCS)

def CRC_Decoding(str1,str2):    #CRC解码
    lenght = len(str2)
    str3 = str1 + '0'*(lenght-1)
    ans = ''
    yus = str3[0:lenght]
    for i in range(len(str1)):
        str4,yus = XOR(yus, str2)
        ans = ans+str4
        if i == len(str1)-1:
            break
        else:
            yus = yus+str3[i+lenght]
    return yus == '0'*len(yus)

根据CRC检验的误码过程,我们可以理解成:
不同的数据帧m1和m2通过相同的除数p进行编码得到传输帧x1和x2,再将x1和x2用p解码得到的余数都为0时误码成立

def main():
    i = 11                               #可控参数 数据帧的位数
    for m1 in range(2**i):               #定义数据m1
        m1 = (bin(m1)[2:]).zfill(i)      #zfill占位补0
        print(m1)                        #定位  
        for m2 in range(2**(i)):
            m2 = (bin(m2)[2:]).zfill(i)
            for p in range(2**(i-3)):      #定义比特模式p p不能大于被除数m  p首位不为0                
                p = '1' + (bin(p)[2:]).zfill(i-3)
                #print('p = {}'.format(p))
                x1 = CRC_Encoding(m1,p)
                x2 = CRC_Encoding(m2,p)
                flag1 = CRC_Decoding(x1,p)
                flag2 = CRC_Decoding(x2,p)
                if flag1 and flag2 and m1 != m2 and x1 == x2:
                    print('数据m1:{}\n数据m2:{}\nm1加密数据:{}\nm2加密数据:{}\np:{}\n'.format(m1,m2,x1,x2,p))
main()

由于本人能力有限,在此留下浅薄的想法
无法呈现出CRC检验误码的例子,恳请大佬指教

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
CRC16校验是一种常用的校验方法,它可以检测数据传输过程中是否出现了误码。下面是C语言实现CRC16校验的方法: 1. 定义一个CRC16表,用于存储预先计算好的CRC16值。 2. 初始化CRC16值为0xFFFF。 3. 对每个字节进行循环处理,将每个字节与CRC16值进行异或运算,得到一个新的CRC16值。 4. 将新的CRC16值右移8位,并从CRC16表中查找对应的CRC16值,将其与新的CRC16值进行异或运算,得到一个新的CRC16值。 5. 将新的CRC16值左移8位,并从CRC16表中查找对应的CRC16值,将其与新的CRC16值进行异或运算,得到最终的CRC16值。 下面是C语言实现CRC16校验代码: ``` #include <stdio.h> #include <stdint.h> uint16_t crc16(uint8_t *data, uint32_t len) { uint16_t crc = 0xFFFF; uint16_t table[256] = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; for (uint32_t i = 0; i < len; i++) { crc = (crc >> 8) ^ table[(crc ^ data[i]) & 0xFF]; } return crc; } int main() { uint8_t data[] = {0x01, 0x02, 0x03, 0x04}; uint16_t crc = crc16(data, sizeof(data)); printf("CRC16: 0x%04X\n", crc); return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值