#include "hamming.h" /** * @brief 计算一个字节中1的个数 * @param byte 输入字节 * @return 返回字节中1的个数 */ static inline int countOnes(unsigned char byte) { static const unsigned char ones[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; return ones[byte & 0x0F] + ones[byte >> 4]; } /** * @brief 计算汉明码的校验位 * @param data 输入数据数组 * @param size 数据大小 * @param parity 输出的校验位数组(3字节) * @note 校验位计算包括: * - 对每个数据位进行异或运算生成校验位 * - 最后一个校验字节的最高位用于总体奇偶校验 */ void calculateParity(const unsigned char *data, int size, unsigned char *parity) { // 初始化校验位数组 memset(parity, 0, PARITY_BYTES); int totalOnes = 0; // 对每个数据字节 for(int i = 0; i < size; i++) { unsigned char byte = data[i]; totalOnes += countOnes(byte); // 对字节中的每一位 for(int j = 0; j < 8; j++) { if(byte & (1 << j)) { // 计算该位在整个数据中的位置 int bitPos = i * 8 + j; // 更新相应的校验位 for(int k = 0; k < 20; k++) { if(bitPos & (1 << k)) { if(k < 8) parity[0] ^= (1 << k); else if(k < 16) parity[1] ^= (1 << (k - 8)); else parity[2] ^= (1 << (k - 16)); } } } } } // 添加总体奇偶校验 if(totalOnes % 2) { parity[2] |= 0x08; // 设置最高位 } } /** * @brief 检测并纠正数据中的错误 * @param data 需要检查的数据 * @param size 数据大小 * @param parity 原始校验位 * @return 返回检测结果: * 0 - 无错误 * 1 - 检测到并纠正了单比特错误 * -1 - 校验位错误 * -2 - 检测到多位错误 */ int detectAndCorrect(unsigned char *data, int size, const unsigned char *parity) { unsigned char currentParity[PARITY_BYTES]; calculateParity(data, size, currentParity); // printf("parity: %02X %02X %02X\n", parity[2], parity[1], parity[0]); // printf("currentParity: %02X %02X %02X\n", currentParity[2], currentParity[1], currentParity[0]); // 计算syndrome unsigned int syndrome = 0; syndrome |= (currentParity[0] ^ parity[0]); syndrome |= (currentParity[1] ^ parity[1]) << 8; syndrome |= ((currentParity[2] ^ parity[2]) & 0x07) << 16; // 检查总体奇偶校验 int parityError = ((currentParity[2] ^ parity[2]) & 0x08) ? 1 : 0; if(syndrome == 0) { if(parityError) { return -2; // 检测到多位错误 } return 0; // 无错误 } if(!parityError) { return -1; // 校验位错误(syndrome不为0但奇偶校验正确) } // 单比特错误 int bitPos = syndrome; int bytePos = bitPos / 8; int bitInByte = bitPos % 8; if(bytePos < size) { data[bytePos] ^= (1 << bitInByte); // printf("纠正位置:字节 %d,位 %d\n", bytePos, bitInByte); return 1; } return -2; // 检测到多位错误 }