查询指令的生成,直接查询多少个寄存器。可以优化成,查询多少个灯。
查询结果,翻译成可读性信息。
代码语言:javascript复制/* eslint-disable */
function generateModbusQuery(registerCount) {
const deviceId = 0x01; // 设备ID
const functionCode = 0x03; // 功能码(读取保持寄存器)
const startAddress = 0x0000; // 起始地址
const buffer = [deviceId, functionCode, startAddress >> 8, startAddress & 0xFF, registerCount >> 8, registerCount & 0xFF];
const crc = crc16(buffer);
buffer.push(crc & 0xFF); // 先添加CRC的低位
buffer.push(crc >> 8); // 再添加CRC的高位
return buffer.map(byte => byte.toString(16).padStart(2, '0')).join(' ').toUpperCase();
}
// 简单的CRC16计算函数,用于生成查询指令的CRC校验码
function crc16(buffer) {
let crc = 0xFFFF;
for (let pos = 0; pos < buffer.length; pos ) {
crc ^= buffer[pos];
for (let i = 8; i !== 0; i--) {
if ((crc & 0x0001) !== 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
// 解释指令
function parseModbusResponse(responseString) {
// 将字符串转换为字节数组
const response = responseString.split(' ').map(hex => parseInt(hex, 16));
// 假设响应数据从第4个字节开始(跳过设备ID,功能码,字节计数)
// 以及最后两个字节是CRC,不包括在内
const dataStartIndex = 3;
const dataEndIndex = response.length - 2;
for (let i = dataStartIndex; i < dataEndIndex; i = 2) {
const registerValue = (response[i] << 8) response[i 1];
const binaryString = registerValue.toString(2).padStart(16, '0');
console.log(`寄存器 ${Math.floor((i - dataStartIndex) / 2)}: ${binaryString}`);
for (let j = 0; j < binaryString.length; j ) {
console.log(`灯 ${Math.floor((i - dataStartIndex) / 2) * 16 j}: ${binaryString[j] === '1' ? '开' : '关'}`);
}
}
}
const req = generateModbusQuery(20)
// console.log(req)
parseModbusResponse("01 03 28 00 01 25 80 00 01 00 00 00 00 00 01 00 00 00 FF 00 01 00 30 00 FF F0 F0 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 1A E9");
代码语言:javascript复制// 生成点亮灯的指令
function generateModbusCommand(lightsToTurnOn) {
// 初始化所有寄存器为全灭(0)
let registers = Array(4).fill(0);
// 遍历灯的数组,设置相应的寄存器位
lightsToTurnOn.forEach(light => {
let registerIndex = Math.floor((light - 1) / 16);
let bitPosition = (light - 1) % 16;
registers[registerIndex] |= (1 << bitPosition);
});
// 将寄存器值转换为十六进制字符串
let hexData = registers.map(reg => reg.toString(16).padStart(4, '0')).join(' ');
// 构建Modbus指令
let deviceAddress = '01';
let functionCode = '10';
let startingAddress = '0000';
let registerCount = '0004';
let byteCount = '08';
let command = `${deviceAddress} ${functionCode} ${startingAddress} ${registerCount} ${byteCount} ${hexData}`;
return command;
}
// 示例:点亮第18、32、56号灯
let command = generateModbusCommand([18, 32, 56]);
console.log(command);
// 01 10 0000 0004 08 0000 8002 0000 0080
代码语言:javascript复制function binaryToHex(binaryStr) {
// 确保输入是16位
if (binaryStr.length !== 16) {
return 'Invalid input';
}
// 将二进制字符串转换为数字,然后转换为16进制字符串
let hexStr = parseInt(binaryStr, 2).toString(16).toUpperCase();
// 保证输出是4位16进制数
return hexStr.padStart(4, '0');
}
// 示例
let hex = binaryToHex('0000000011111111'); // 应该返回 '00FF'
console.log(hex);