算法 - 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;
}
相关推荐
程序员-King.13 小时前
day158—回溯—全排列(LeetCode-46)
算法·leetcode·深度优先·回溯·递归
Y1rong14 小时前
STM32之中断(二)
stm32·单片机·嵌入式硬件
Y1rong14 小时前
STM32之中断(一)
stm32·单片机·嵌入式硬件
月挽清风14 小时前
代码随想录第七天:
数据结构·c++·算法
小O的算法实验室14 小时前
2026年AEI SCI1区TOP,基于改进 IRRT*-D* 算法的森林火灾救援场景下直升机轨迹规划,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
LaoZhangGong12315 小时前
学习TCP/IP的第3步:和SYN相关的数据包
stm32·单片机·网络协议·tcp/ip·以太网
小郭团队15 小时前
2_1_七段式SVPWM (经典算法)算法理论与 MATLAB 实现详解
嵌入式硬件·算法·硬件架构·arm·dsp开发
充值修改昵称15 小时前
数据结构基础:从二叉树到多叉树数据结构进阶
数据结构·python·算法
Deepoch15 小时前
Deepoc数学大模型:发动机行业的算法引擎
人工智能·算法·机器人·发动机·deepoc·发动机行业
bai54593615 小时前
STM32 CubeIDE 使用蓝牙模块实现手机控制LED灯
stm32·单片机·嵌入式硬件