【物联网开发】、【小程序蓝牙通讯数据校验】JS CRC-16-MODBUS 验证 高位在前低位在后;JS异或校验;16进制字符串和float互转

本文介绍了CRC-16/MODBUS校验算法,异或校验生成校验码的方法,以及16进制与浮点数之间的转换,涉及ArrayBuffer和DataView在数据处理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.CRC校验

/*计算CRC-16/MODBUS校验位高低位*/
function calculateCRC16Modbus(dataHexString) {
	const dataBytes = [];
	for (let i = 0; i < dataHexString.length; i += 2) {
		dataBytes.push(parseInt(dataHexString.substr(i, 2), 16));
	}

	let crc = 0xFFFF;
	const polynomial = 0xA001; // This is the polynomial x^16 + x^15 + x^2 + 1

	for (const byte of dataBytes) {
		crc ^= byte;
		for (let i = 0; i < 8; i++) {
			if (crc & 0x0001) {
				crc = ((crc >> 1) ^ polynomial) & 0xFFFF;
			} else {
				crc >>= 1;
			}
		}
	}

	crc = pad(crc.toString(16).toUpperCase(),4);//补0(不然会出八阿哥)
	let crcArr = new Array(2)
	console.log('crc='+crc)
	crcArr[0] = crc.substring(2, 4)
	crcArr[1] = crc.substring(0, 2)
	let code = crcArr[0] + crcArr[1]
	return code
}

2.异或校验

// 生成校验码
function genCheckCode(msgBodyCode) {
	let firstByte = null;
	for (let i = 0; i < msgBodyCode.length; i = i + 2) {
		const curCode = '0x' + msgBodyCode.substring(i, i + 2);
		if (i == 0) {
			firstByte = curCode
		} else {
			firstByte = firstByte ^ curCode
		}
	}
	firstByte = parseInt(firstByte)
	const codePad = pad(firstByte.toString(16), 2)
	console.log('校验码==' + codePad)
	return codePad;
}

3.pad 左侧补0方法

// 左侧补齐0
function pad(str, max) {
	str = str.toString();
	return str.length < max ? pad("0" + str, max) : str;
}

4.16进制和float(4字节)互转

/*4字节byte十六进制转浮点数      解析   */
function hex2float(hexString, precision) {
	//hex2float('EC519A44', 2))
	precision = parseInt(precision)
	if (isNaN(precision) || precision < 0) {
		precision = 2
	}

	// 高低位转换
	const byteArray = [];
	for (let i = 0; i < hexString.length; i += 2) {
		byteArray.unshift(hexString.substr(i, 2));
	}

	// 创建一个包含十六进制数的 ArrayBuffer
	const hexValue = '0x' + byteArray.join('');
	const buffer = new ArrayBuffer(4);
	const dataView = new DataView(buffer);
	dataView.setUint32(0, hexValue, false);

	// 从 DataView 中读取浮点数
	const floatValue = dataView.getFloat32(0, false);
	return floatValue.toFixed(precision);
}


/*浮点数转4字节十六进制      发送*/
function float2hex(floatNumber) {
	// 创建一个 4 字节的 ArrayBuffer
	const buffer = new ArrayBuffer(4);

	// 使用 DataView 来操作 ArrayBuffer
	const dataView = new DataView(buffer);

	// 将浮点数写入到 DataView 中
	dataView.setFloat32(0, floatNumber, false); // 第二个参数是偏移量,false 表示使用大端字节序

	// 从 DataView 中读取十六进制表示
	const hexString = dataView.getUint32(0, false).toString(16).toUpperCase();

	// 高低位转换
	const byteArray = [];
	for (let i = 0; i < hexString.length; i += 2) {
		byteArray.unshift(hexString.substr(i, 2));
	}
	return byteArray.join('');
}
<think>好的,用户想详细了解CRC-16Modbus)算法,以及Modbus通讯中是否还有其他校验算法。我需要分步骤来整理这些信息,确保准确且清晰。 首先,CRC-16的基础知识。CRC是循环冗余校验,用于检测数据传输中的错误。Modbus使用的特定CRC-16变体,参数需要明确:多项式、初始值、输入输出处理等。可能需要查标准文档确认具体参数,比如多项式是否是0x8005,初始值是否为0xFFFF,是否是低位先传输(LSB First)。 然后,算法的具体步骤。用户可能需要了解如何计算CRC,包括初始化寄存器、逐位或逐字节处理数据异或操作、移位方向等。这里要详细说明每一步,并给出示例,比如示例计算过程,或者代码片段,但用户可能需要中文解释而不是代码。 接下来,Modbus中的其他校验算法。记得Modbus有ASCIIRTU模式,ASCII模式使用LRC校验,而RTU使用CRC。需要解释LRC的原理,如何计算,比如求的二进制反码,可能举例说明。 还需要注意,虽然用户可能知道Modbus,但可能需要简要介绍两种传输模式的区别,以及为何使用不同的校验方法。比如RTU模式使用二进制数据,需要更强的校验,而ASCII模式使用可打印字符,LRC足够。 然后,可能需要比较CRC-16LRC的区别,比如错误检测能力,计算复杂度,适用场景等。这有助于用户理解为何Modbus选择这两种校验。 另外,是否还有其他校验算法?比如在Modbus/TCP中是否使用不同的校验?可能需要说明Modbus TCP是基于TCP的,本身有校验机制,因此可能不需要额外的CRC或LRC,但用户可能想知道传统的串行链路中的情况。 在整理过程中要确保技术细节准确,例如多项式是否正确,初始值反转是否正确。如果有不确定的地方,需要参考Modbus标准文档,比如Modbus over serial line specification,确认CRC-16的参数。 最后,结构要清晰,分点回答,先介绍CRC-16Modbus)的算法,步骤,再说明其他校验算法如LRC,最后可能提及TCP的情况。确保用中文,行内公式用$...$,独立公式用$$...$$,但用户的问题里没有数学公式,可能需要举例时使用,比如多项式表示,计算过程等。 检查是否有遗漏,比如ModbusCRC是否真的是CRC-16/MODBUS,或者其他名称,例如有的资料可能称为CRC-16-IBM,但具体参数是否相同。需要确认这点,避免错误。 总结:先详细解释CRC-16Modbus)的算法步骤,参数,计算过程,然后介绍LRC,最后其他可能的校验方式。确保回答结构清晰,步骤正确,符合用户要求。</think>以下是对CRC-16Modbus)算法及Modbus校验机制的详细说明: --- ### 一、CRC-16Modbus)算法详解 #### 1. 算法参数 - **多项式**:$x^{16} + x^{15} + x^2 + 1$,对应十六进制值为`0x8005`(实际计算需反转位序为`0xA001`)。 - **初始值**:`0xFFFF` - **输入/输出处理**:输入数据按字节**低位优先(LSB First)**处理,最终结果**高低字节交换**。 #### 2. 计算步骤 1. **初始化寄存器**: 设置16位寄存器为初始值`0xFFFF`。 2. **逐字节处理数据**: 对每个数据字节执行以下操作: - 寄存器与当字节**异或(XOR)**。 - 对寄存器执行8次循环右移: ```plaintext for (int i = 0; i < 8; i++) { if (寄存器最低位为1) { 寄存器 = (寄存器 >> 1) XOR 0xA001; // 0xA001是0x8005的反转 } else { 寄存器 = 寄存器 >> 1; } } ``` 3. **最终处理**: 完成所有字节处理后,交换寄存器的高8位与低8位,得到最终CRC值。 #### 3. 示例计算 假设数据为`0x01 0x03`: 1. 初始值`0xFFFF` 2. 处理`0x01`: - `0xFFFF XOR 0x01 = 0xFFFE` - 8次右移后结果为`0x7FBF` 3. 处理`0x03`: - `0x7FBF XOR 0x03 = 0x7FBC` - 8次右移后结果为`0x1E0E` 4. 交换高低字节:最终CRC为`0x0E1E`。 --- ### 二、Modbus通讯中的其他校验算法 #### 1. **LRC(纵向冗余校验)** - **适用场景**:Modbus **ASCII模式**。 - **计算规则**: 1. 计算所有数据字节的**8位**。 2. 对结果取**二进制补码**(即按位取反后加1)。 3. 最终结果为1字节校验码。 - **示例**: 数据`0x3A 0x30 0x31`的为`0x3A+0x30+0x31=0x9B`,补码为`0x65`。 #### 2. **CRC与LRC对比** | 特性 | CRC-16Modbus) | LRC | |-----------|-----------------------|-------------------| | 错误检测能力 | 强(可检测多比特、突发错误) | 弱(仅单比特错误) | | 计算复杂度 | 高 | 低 | | 校验码长度 | 2字节 | 1字节 | | 适用模式 | RTU模式 | ASCII模式 | --- ### 三、特殊场景说明 - **Modbus TCP**:基于TCP协议,依赖TCP层的校验机制,**无需额外CRC/LRC**。 - **扩展变体**:非Modbus场景中,存在其他CRC-16变体(如CRC-16-CCITT),但参数不同。 --- ### 四、核心作用 CRC-16LRC均用于保障Modbus通讯的**数据完整性**,其中CRC-16因更强的检错能力成为RTU模式的首选。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值