算法 - 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;
}
相关推荐
沉默-_-12 小时前
备战蓝桥杯-哈希
c++·学习·算法·蓝桥杯·哈希算法
guygg8812 小时前
基于STM32的智能小区管理系统设计
stm32·单片机·嵌入式硬件
拼好饭和她皆失12 小时前
基础算法--写给算法小白的模板指南:快速掌握核心代码,蓝桥杯必备模板
算法
吞下星星的少年·-·12 小时前
rotate函数应用模板
算法
AI科技星12 小时前
人类首张【全域数学公理体系】黑洞内部结构图—基于「0-1-∞」三元本源的全维深度解析
人工智能·算法·机器学习·数学建模·数据挖掘·量子计算
Deitymoon12 小时前
STM32——震动传感器控制led
stm32·单片机·嵌入式硬件
paeamecium12 小时前
【PAT甲级真题】- Recover the Smallest Number (30)
数据结构·算法·pat考试·pat
Dillon Dong12 小时前
【风电控制】变流器转矩控制回路深度解析:从指令生成到闭环控制
算法·变流器·风电控制
玛丽莲茼蒿12 小时前
Leetcode hot100 在排序数组中查找元素的第一个和最后一个位置【中等】
数据结构·算法
墨染天姬12 小时前
[AI]OPENAI的PPO算法
人工智能·算法