modbus rtu 灯光控制板查询指令生产及查询结果的解读

2024-01-17 08:37:26 浏览数 (3)

查询指令的生成,直接查询多少个寄存器。可以优化成,查询多少个灯。

查询结果,翻译成可读性信息。

代码语言: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);

1 人点赞