算法 - 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;
}
相关推荐
Aldrich_3215 小时前
蓝桥杯嵌入式赛道—-软件篇(GPIO输出模式配置)
c语言·vscode·stm32·单片机·嵌入式硬件·蓝桥杯
Kisorge15 小时前
【电机控制】基于STM32F103C8T6的二轮平衡车设计——LQR线性二次线控制器(算法篇)
stm32·嵌入式硬件·算法
铭哥的编程日记16 小时前
深入浅出蓝桥杯:算法基础概念与实战应用(二)基础算法(下)
算法·职场和发展·蓝桥杯
Swift社区16 小时前
LeetCode 421 - 数组中两个数的最大异或值
算法·leetcode·职场和发展
cici1587416 小时前
基于高光谱成像和偏最小二乘法(PLS)的苹果糖度检测MATLAB实现
算法·matlab·最小二乘法
范纹杉想快点毕业17 小时前
《嵌入式开发硬核指南:91问一次讲透底层到架构》
java·开发语言·数据库·单片机·嵌入式硬件·mongodb
StarPrayers.17 小时前
自蒸馏学习方法
人工智能·算法·学习方法
大锦终17 小时前
【动规】背包问题
c++·算法·动态规划
智者知已应修善业18 小时前
【c语言蓝桥杯计算卡片题】2023-2-12
c语言·c++·经验分享·笔记·算法·蓝桥杯
一叶知秋0618 小时前
英集芯-IP5385 IIC通信异常原因深入分析及解决方案 21
单片机·嵌入式硬件