CRC-16 校验码计算

CRC-16 循环冗余校验码计算工具,支持多种 CRC-16 算法

需要 CRC-8 或 CRC-32?打开通用 CRC 计算器

工具简介:CRC-16 校验码计算工具

CRC-16(16位循环冗余校验)是一种广泛使用的错误检测算法,主要用于数据传输和存储中的完整性验证。本工具支持多种CRC-16算法变体,适用于不同的应用场景。

什么是CRC-16 校验码计算工具?

CRC-16 校验码计算用于根据输入参数计算结果,适合快速估算与校验。

如何使用

  1. 填写必要的数值参数。
  2. 选择单位或计算条件。
  3. 点击计算并查看结果。

常见应用场景

  • 学习与教学中的公式验证
  • 工程或设计中的快速估算
  • 日常记录与结果核对

❓ 常见问题 FAQ

Q1:结果精度如何?
A:可根据需要保留小数位或进行四舍五入。

Q2:单位不一致怎么办?
A:先统一单位再进行计算,避免误差。

Q3:适用范围是什么?
A:适用于常见范围内的快速计算与参考。

🔧 支持的算法

CRC-16 Standard

  • 多项式: 0x8005 (x^16 + x^15 + x^2 + 1)
  • 初始值: 0x0000
  • 应用: 通用数据校验

CRC-16 CCITT

  • 多项式: 0x1021 (x^16 + x^12 + x^5 + 1)
  • 初始值: 0xFFFF
  • 应用: 通信协议、X.25、HDLC

CRC-16 Modbus

  • 多项式: 0x8005
  • 初始值: 0xFFFF
  • 应用: Modbus通信协议

CRC-16 XMODEM

  • 多项式: 0x1021
  • 初始值: 0x0000
  • 应用: XMODEM文件传输协议

💡 使用场景

1. 数据完整性验证

// 数据传输完整性检查
class DataIntegrityChecker {
  constructor() {
    this.checksums = new Map();
  }

  // 计算并存储数据的CRC-16校验码
  storeChecksum(dataId, data) {
    const crc16 = this.calculateCRC16(data, 'crc16');
    this.checksums.set(dataId, crc16);
    return crc16;
  }

  // 验证数据完整性
  verifyIntegrity(dataId, currentData) {
    const originalCRC = this.checksums.get(dataId);
    if (!originalCRC) {
      return { valid: false, reason: '未找到原始校验码' };
    }

    const currentCRC = this.calculateCRC16(currentData, 'crc16');
    const isValid = originalCRC === currentCRC;

    return {
      valid: isValid,
      originalCRC: '0x' + originalCRC.toString(16).toUpperCase(),
      currentCRC: '0x' + currentCRC.toString(16).toUpperCase(),
      reason: isValid ? '数据完整' : '数据已被修改'
    };
  }

  calculateCRC16(data, algorithm) {
    // 实际实现中使用专业的CRC库
    return this.crcCalculate(data, algorithm);
  }
}

// 使用示例
const checker = new DataIntegrityChecker();

// 存储原始数据的校验码
const originalData = "重要的业务数据";
const checksum = checker.storeChecksum('data001', originalData);
console.log('存储的校验码:', checksum);

// 验证数据完整性
const currentData = "重要的业务数据"; // 未修改
const verification = checker.verifyIntegrity('data001', currentData);
console.log('完整性验证结果:', verification);

2. 通信协议实现

// Modbus通信协议CRC校验
class ModbusProtocol {
  constructor() {
    this.crcTable = this.generateCRCTable(0x8005);
  }

  // 生成CRC查找表
  generateCRCTable(polynomial) {
    const table = [];
    for (let i = 0; i < 256; i++) {
      let crc = i;
      for (let j = 0; j < 8; j++) {
        if (crc & 1) {
          crc = (crc >>> 1) ^ polynomial;
        } else {
          crc = crc >>> 1;
        }
      }
      table[i] = crc & 0xFFFF;
    }
    return table;
  }

  // 计算Modbus CRC-16
  calculateModbusCRC(data) {
    let crc = 0xFFFF;
    const bytes = typeof data === 'string' ? 
      new TextEncoder().encode(data) : data;

    for (const byte of bytes) {
      const tableIndex = (crc ^ byte) & 0xFF;
      crc = ((crc >>> 8) ^ this.crcTable[tableIndex]) & 0xFFFF;
    }

    return crc;
  }

  // 创建Modbus消息帧
  createFrame(deviceId, functionCode, data) {
    const frame = [deviceId, functionCode, ...data];
    const crc = this.calculateModbusCRC(new Uint8Array(frame));
    
    // CRC以小端序添加到帧末尾
    frame.push(crc & 0xFF);
    frame.push((crc >>> 8) & 0xFF);
    
    return new Uint8Array(frame);
  }

  // 验证Modbus消息帧
  verifyFrame(frame) {
    if (frame.length < 4) {
      return { valid: false, reason: '帧长度不足' };
    }

    const dataLength = frame.length - 2;
    const data = frame.slice(0, dataLength);
    const receivedCRC = frame[dataLength] | (frame[dataLength + 1] << 8);
    const calculatedCRC = this.calculateModbusCRC(data);

    return {
      valid: receivedCRC === calculatedCRC,
      receivedCRC: '0x' + receivedCRC.toString(16).toUpperCase(),
      calculatedCRC: '0x' + calculatedCRC.toString(16).toUpperCase(),
      reason: receivedCRC === calculatedCRC ? 'CRC校验通过' : 'CRC校验失败'
    };
  }
}

// 使用示例
const modbus = new ModbusProtocol();

// 创建读取保持寄存器的请求帧
const frame = modbus.createFrame(0x01, 0x03, [0x00, 0x00, 0x00, 0x02]);
console.log('Modbus帧:', Array.from(frame).map(b => '0x' + b.toString(16).toUpperCase()));

// 验证接收到的帧
const verification = modbus.verifyFrame(frame);
console.log('帧验证结果:', verification);

3. 文件校验系统

// 文件完整性校验系统
class FileIntegritySystem {
  constructor() {
    this.fileChecksums = new Map();
  }

  // 计算文件的CRC-16校验码
  async calculateFileCRC(file, algorithm = 'crc16') {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      
      reader.onload = (event) => {
        try {
          const arrayBuffer = event.target.result;
          const bytes = new Uint8Array(arrayBuffer);
          const crc = this.calculateCRC16(bytes, algorithm);
          
          resolve({
            filename: file.name,
            size: file.size,
            algorithm: algorithm,
            checksum: crc,
            checksumHex: '0x' + crc.toString(16).toUpperCase(),
            timestamp: new Date().toISOString()
          });
        } catch (error) {
          reject(error);
        }
      };
      
      reader.onerror = reject;
      reader.readAsArrayBuffer(file);
    });
  }

  // 批量处理文件
  async processFiles(files, algorithm = 'crc16') {
    const results = [];
    
    for (const file of files) {
      try {
        const result = await this.calculateFileCRC(file, algorithm);
        results.push(result);
        this.fileChecksums.set(file.name, result);
      } catch (error) {
        results.push({
          filename: file.name,
          error: error.message,
          success: false
        });
      }
    }
    
    return results;
  }

  // 检测重复文件
  findDuplicates() {
    const checksumMap = new Map();
    const duplicates = [];

    for (const [filename, info] of this.fileChecksums) {
      const key = `${info.checksum}_${info.size}`;
      
      if (checksumMap.has(key)) {
        const existing = checksumMap.get(key);
        duplicates.push({
          group: [existing.filename, filename],
          checksum: info.checksumHex,
          size: info.size
        });
      } else {
        checksumMap.set(key, info);
      }
    }

    return duplicates;
  }

  calculateCRC16(data, algorithm) {
    // 实际的CRC-16计算实现
    // 这里简化处理,实际应用中使用专业库
    let crc = algorithm === 'crc16_modbus' ? 0xFFFF : 0x0000;
    const polynomial = algorithm.includes('ccitt') || algorithm.includes('xmodem') ? 0x1021 : 0x8005;
    
    for (const byte of data) {
      crc ^= byte;
      for (let i = 0; i < 8; i++) {
        if (crc & 1) {
          crc = (crc >>> 1) ^ polynomial;
        } else {
          crc = crc >>> 1;
        }
      }
    }
    
    return crc & 0xFFFF;
  }
}

// 使用示例
const fileSystem = new FileIntegritySystem();

// 处理文件上传
document.getElementById('fileInput').addEventListener('change', async (event) => {
  const files = Array.from(event.target.files);
  
  if (files.length > 0) {
    console.log('开始处理文件...');
    const results = await fileSystem.processFiles(files, 'crc16_modbus');
    
    results.forEach(result => {
      if (result.error) {
        console.error(`文件 ${result.filename} 处理失败:`, result.error);
      } else {
        console.log(`文件: ${result.filename}`);
        console.log(`大小: ${result.size} 字节`);
        console.log(`CRC-16: ${result.checksumHex}`);
        console.log(`算法: ${result.algorithm}`);
        console.log('---');
      }
    });
    
    // 检查重复文件
    const duplicates = fileSystem.findDuplicates();
    if (duplicates.length > 0) {
      console.log('发现重复文件:');
      duplicates.forEach(dup => {
        console.log(`重复组: ${dup.group.join(', ')}`);
        console.log(`校验码: ${dup.checksum}`);
      });
    }
  }
});

🔍 算法特点

优势

  • 快速计算: 相比MD5、SHA等算法更快
  • 硬件友好: 易于硬件实现
  • 标准化: 多种标准算法可选
  • 实时性: 适合实时数据校验

局限性

  • 安全性: 不适用于密码学安全
  • 碰撞: 可能存在校验码相同的不同数据
  • 长度: 16位校验码相对较短

⚠️ 使用建议

  1. 算法选择: 根据具体协议选择合适的CRC-16变体
  2. 性能优化: 使用查找表提高计算效率
  3. 错误处理: 实现完善的错误检测和处理机制
  4. 测试验证: 使用标准测试向量验证实现正确性

📚 技术参考

  • ITU-T V.41: CCITT CRC-16标准
  • Modbus规范: Modbus CRC-16实现
  • RFC 1662: PPP中的CRC-16使用
  • ISO 3309: HDLC中的CRC标准