CRC-16 校验码计算
CRC-16 循环冗余校验码计算工具,支持多种 CRC-16 算法
需要 CRC-8 或 CRC-32?打开通用 CRC 计算器
工具简介:CRC-16 校验码计算工具
CRC-16(16位循环冗余校验)是一种广泛使用的错误检测算法,主要用于数据传输和存储中的完整性验证。本工具支持多种CRC-16算法变体,适用于不同的应用场景。
什么是CRC-16 校验码计算工具?
CRC-16 校验码计算用于根据输入参数计算结果,适合快速估算与校验。
如何使用
- 填写必要的数值参数。
- 选择单位或计算条件。
- 点击计算并查看结果。
常见应用场景
- 学习与教学中的公式验证
- 工程或设计中的快速估算
- 日常记录与结果核对
❓ 常见问题 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位校验码相对较短
⚠️ 使用建议
- 算法选择: 根据具体协议选择合适的CRC-16变体
- 性能优化: 使用查找表提高计算效率
- 错误处理: 实现完善的错误检测和处理机制
- 测试验证: 使用标准测试向量验证实现正确性
📚 技术参考
- ITU-T V.41: CCITT CRC-16标准
- Modbus规范: Modbus CRC-16实现
- RFC 1662: PPP中的CRC-16使用
- ISO 3309: HDLC中的CRC标准