AutosarMCAL开发——基于EB CRC驱动

1 CRC校验原理

使用CRC校验的作用在于多机通讯时保证数据发送与接收的一致性

CRC计算主要步骤:

  • 1.选取对应的多项式算子,展开获得CRC除数(例:x4 + x + 1 二进制x为2则算子为1011(提取系数) 省略最高位为0x03)
  • 3.在原始数据末端加0,加0的个数取决于最高次(例:x4 + x + 1 则添加0000至原始数据末尾)
  • 4.从左往右,数据与算子按位异或,最终余数即为CRC校验结果,填充至原始数据加0处

CRC详细关键步骤:
1.初始化CRC寄存器

预留一个寄存器(通常为16位或根据CRC版本不同而有所变化,如CRC-8、CRC-16、CRC-32等),并将其初始化为全1(如0xFFFF对于CRC-16)或特定的初始值(根据CRC算法的具体实现而定)。
2. 处理数据
将要发送的数据的第一个字节(或指定长度的数据块)与CRC寄存器的低几位进行异或操作,高几位保持不变(具体位数取决于CRC版本)。
将得到的CRC寄存器的值向右移动一位,最高位用0填充,并检查移出的位(即原来的最低位)。
3. 模2除法
如果移出的位为0,则重复上一步的右移操作。
如果移出的位为1,则将CRC寄存器与预定义的生成多项式进行异或操作。生成多项式是CRC算法中的一个关键参数,用于检测数据中的错误。
重复上述右移和异或操作,直到处理了数据中的所有字节。
4. 交换CRC寄存器的高低字节(可选)
在某些CRC算法中,需要将最终CRC寄存器的高低字节进行交换,以得到最终的CRC校验码。这一步骤取决于CRC算法的具体实现和接收端的期望格式。
5. 附加CRC校验码到数据帧
将计算得到的CRC校验码附加到原始数据帧的末尾,形成一个新的数据帧进行发送。
6. 接收端校验
接收端在接收到数据后,使用相同的生成多项式对包括CRC校验码在内的整个数据帧进行模2除法运算。
如果运算结果为0(即没有余数),则认为数据在传输过程中没有发生错误;否则,认为数据存在错误

计算细节可参考以下链接:
链接: [CRC校验]手算与直观演示

CRC-16-CCITT-FALSE C语言基础实现

在这里插入图片描述

链接: C语言在线编译工具
链接: CRC校验在线计算工具

#include <stdio.h>  
#include <stdint.h>  
#define Poly 0x1021//1.确定多项式算子 省略最高位的1
uint16_t crc16_ccitt(uint8_t *data, size_t len) {  
    uint16_t crc = 0xFFFF; // 1.初始化CRC寄存器 初始值  
    uint8_t i;  
  
    while (len--) {  
        crc ^= (uint16_t)(*data++ << 8); // 2.从左到右运算预处理 将数据左移8位后异或到CRC的高8位  
        for (i = 0; i < 8; i++) {  
            if (crc & 0x8000) { // 检查最高位(第16位)  
                crc = (crc << 1) ^ Poly; // 3. 先左移在异或是因为算子省略了最高位 左移一位,如果最高位是1,则异或多项式  
            } else {  
                crc = crc << 1;  
            }  
        }  
    }  
    return crc;  //4.最终CRC校验结果
}  
  
int main() {  
    uint8_t data[] = {0x12, 0x56, 0x78,0x34};  
    size_t len = sizeof(data) / sizeof(data[0]);  
    uint16_t crc = crc16_ccitt(data, len);  
  
    // 如果需要交换高低字节(例如,某些协议要求)  
    // 注意:这个步骤是在CRC计算之后进行的  
    uint16_t swapped_crc = (crc >> 8) | (crc << 8);  
  
    printf("CRC-16 (without swapping): 0x%04X\n", crc);  
    printf("CRC-16 (with swapping): 0x%04X\n", swapped_crc);  
  
    return 0;  
}

代码验证:
在这里插入图片描述
在这里插入图片描述

CRC-32 查表法C语言基础实现

#include <stdio.h>  
#include <stdint.h>  
  
// CRC-32表  
uint32_t crc_table[256];  
  
// 初始化CRC表  
void init_crc_table() {  
    for (uint32_t i = 0; i < 256; i++) {  
        uint32_t crc = i;  
        for (uint8_t j = 0; j < 8; j++) {  
            if (crc & 1) {  
                crc = (crc >> 1) ^ 0xEDB88320; // 多项式0x04C11DB7的逆  
            } else {  
                crc >>= 1;  
            }  
        }  
        crc_table[i] = crc;  
    }  
}  
  
// 使用查表法计算CRC-32  
uint32_t crc32(uint8_t *buf, size_t len) {  
    uint32_t crc = 0xFFFFFFFF; // 初始CRC值  
    while (len--) {  
        crc = crc_table[(crc ^ *buf++) & 0xFF] ^ (crc >> 8);  
    }  
    return ~crc; // 返回最终的CRC值(按惯例取反)  
}  
  
int main() {  
    // 初始化CRC表  
    init_crc_table();  
  
    // 测试字符串  
    char test_str[] = "Hello, World!";  
  
    // 计算CRC-32  
    uint32_t crc = crc32((uint8_t*)test_str, sizeof(test_str) - 1);  
  
    // 输出结果  
    printf("CRC-32 of '%s' is 0x%08X\n", test_str, crc);  
  
    return 0;  
}

代码验证:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 EB配置以及接口应用

配置步骤:
1.选择是否需要输入参数无效故障诊断
2.对应的CRC标准实现方式

1.选择是否需要输入参数无效故障诊断
在这里插入图片描述
2.对应的CRC标准实现方式
在这里插入图片描述
接口应用步骤
1.直接调用对应接口

接口名传入参数说明返回参数说明
Crc_CalculateCRC8Crc_DataRefType Crc_DataPtr, uint32 Crc_Length, uint8 Crc_StartValue8, boolean Crc_IsFirstCall数据buffer,数据长度,自定义初始值,设置初始值调用方式 (0 使用默认值^自定义值 1使用默认值)FUNC(uint8, CRC_CODE)返回CRC校验值
Crc_CalculateCRC16同上同上同上同上
Crc_CalculateCRC32同上同上同上同上
Crc_CalculateCRC8H2F同上同上同上同上
Crc_CalculateCRC32P4同上同上同上同上

3 总结

本文为博主个人学习总结记录,如有不正,欢迎指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值