算法 - PEC校验

PEC基于CRC-8,一般用在I2C / SMBus这样的地方,它没有纠错能力,只能判断数据是否完整可靠;

主要逻辑为:

发送端在发送数据时,利用一个式子把需要校验的数据进行计算,得到一个PEC校验码;

接收端接收到数据后,也用相同式子计算,对比两者PEC校验码是否相同,相同的话认为数据完整可靠,不同认为这个包错误;

伪代码示例

cpp 复制代码
#include <stdio.h>
#include <stdint.h>

// CRC-8 PEC计算函数(I2C标准多项式:0x07)
uint8_t i2c_calculate_pec(const uint8_t *data, uint16_t length) {
    uint8_t crc = 0x00;  // 初始值为0
    for (uint16_t i = 0; i < length; i++) {
        crc ^= data[i];  // 与当前数据字节异或
        // 对每个比特位进行处理
        for (uint8_t bit = 0; bit < 8; bit++) {
            if (crc & 0x80) {  // 最高位为1时,左移后与多项式异或
                crc = (crc << 1) ^ 0x07;
            } else {  // 最高位为0时,仅左移
                crc <<= 1;
            }
            crc &= 0xFF;  // 保持8位
        }
    }
    return crc;
}

// 模拟I2C发送端:生成包含PEC的数据帧
void i2c_transmit(uint8_t *tx_data, uint16_t data_len) {
    // 计算PEC校验值(包含地址、命令、数据等所有传输内容)
    uint8_t pec = i2c_calculate_pec(tx_data, data_len);
    
    // 打印发送信息(实际I2C中会通过硬件发送)
    printf("I2C发送数据: ");
    for (uint16_t i = 0; i < data_len; i++) {
        printf("0x%02X ", tx_data[i]);
    }
    printf("| PEC: 0x%02X\n", pec);
}

// 模拟I2C接收端:验证PEC是否正确
bool i2c_receive(const uint8_t *rx_data, uint16_t data_len, uint8_t received_pec) {
    // 对接收到的数据重新计算PEC
    uint8_t calculated_pec = i2c_calculate_pec(rx_data, data_len);
    
    // 验证PEC是否一致
    if (calculated_pec == received_pec) {
        printf("I2C接收验证成功:PEC匹配\n");
        return true;
    } else {
        printf("I2C接收验证失败:计算PEC=0x%02X,接收PEC=0x%02X\n", 
               calculated_pec, received_pec);
        return false;
    }
}

int main() {
    // 示例:I2C数据帧(包含从机地址、命令、数据)
    uint8_t i2c_frame[] = {0xA0, 0x01, 0x34, 0x56};  // 地址0xA0,命令0x01,数据0x34、0x56
    uint16_t frame_len = sizeof(i2c_frame) / sizeof(i2c_frame[0]);
    
    // 发送端生成并发送数据+PEC
    uint8_t tx_pec = i2c_calculate_pec(i2c_frame, frame_len);
    i2c_transmit(i2c_frame, frame_len);
    
    // 模拟接收过程(正常情况)
    printf("\n--- 正常接收场景 ---\n");
    i2c_receive(i2c_frame, frame_len, tx_pec);  // 验证通过
    
    // 模拟接收过程(数据被干扰的情况)
    printf("\n--- 数据错误场景 ---\n");
    uint8_t corrupted_frame[] = {0xA0, 0x01, 0x35, 0x56};  // 第3字节被篡改(0x34→0x35)
    i2c_receive(corrupted_frame, frame_len, tx_pec);  // 验证失败
    
    return 0;
}
相关推荐
清风6666664 小时前
基于单片机的全自动洗衣机控制器设计
单片机·嵌入式硬件·毕业设计·课程设计·期末大作业
再卷也是菜4 小时前
算法基础篇(8)贪心算法
算法·贪心算法·1024程序员节
AI科技星4 小时前
接近光速运动下的光速不变性:基于张祥前统一场论的推导与验证
数据结构·人工智能·经验分享·算法·计算机视觉
陈苏同学5 小时前
笔记1.4:机器人学的语言——三维空间位姿描述 (旋转矩阵 - 齐次变换矩阵 - 欧拉角 - 四元数高效表示旋转)
笔记·线性代数·算法·机器人
scx201310045 小时前
20251025 分治总结
数据结构·c++·算法
碧海银沙音频科技研究院5 小时前
DiVE长尾识别的虚拟实例蒸馏方法
arm开发·人工智能·深度学习·算法·音视频
帅帅兔子6 小时前
2.4寸SPI串口ILI9341芯片彩色LCD驱动
stm32·单片机·嵌入式硬件·mcu
居7然7 小时前
DeepSeek OCR:重新定义AI文档处理的“降本增效”新范式
人工智能·算法·语言模型·自然语言处理·大模型·ocr
蓝天居士7 小时前
PY32F040单片机介绍(1)
单片机·国产mcu·1024程序员节