java modbus协议

2021-05-04  本文已影响0人  浪人残风

概念

Modbus是一种串行通信协议,Modbus协议目前存在用于串口、以太网以及其他支持互联网协议的网络的版本。
大多数Modbus设备通信通过串口EIA-485物理层进行。

通讯格式

地址域 功能码 数据 CRC校验(低字节在前)
1字节 1字节 N字节 2字节

在单片机硬件通讯串口行业,很多厂家都把485串口参数设置为:
波特率9600,无奇偶校验,1停止位

功能码说明

实际用途中常用的功能码有:

功能码0x03:读单个或多个保持寄存器
设备地址(1字节) 功能码(1字节) 寄存器起始地址(2字节) 寄存器数量(2字节) CRC校验(2字节)
XX 03 XX XX XX XX XX XX

响应:

设备地址(1字节) 功能码(1字节) 数据长度(2字节) 数据(N字节) CRC校验(2字节)
XX 03 XX XX N字节 XX XX

示例
查询设备类型

设备地址(1字节) 功能码(1字节) 数据长度(2字节) 数据(N字节) CRC校验(2字节)
01 03 00 01 00 01 D5 CA

查询设备类型响应

设备地址(1字节) 功能码(1字节) 数据长度(2字节) 数据(N字节) CRC校验(2字节)
01 03 02 00 21 78 5C
功能码0x06:写单个寄存器
设备地址(1字节) 功能码(1字节) 寄存器地址(2字节) 数据(N字节) CRC校验(2字节)
XX 06 XX XX N字节 XX XX

响应:

设备地址(1字节) 功能码(1字节) 寄存器地址(2字节) 数据(N字节) CRC校验(2字节)
XX 06 XX XX N字节 XX XX

示例
写数据

设备地址(1字节) 功能码(1字节) 寄存器地址(2字节) 数据(N字节) CRC校验(2字节)
01 06 00 14 00 00 C9 CE

Java版modbus协议代码:

package com.wrs.project.modbus;


import java.util.ArrayList;
import java.util.List;

public class ModbusUtils {

    /**
     * 读指令
     * @param deviceAddress 设备地址
     * @param registerAddress 寄存器起始地址
     * @param registerCount 寄存器个数
     * @return
     */
    public static byte[] getReadModbus(int deviceAddress, int registerAddress, int registerCount) {
        int registerLow = registerAddress & 0xFF;
        int registerHigh = registerAddress >>> 8;
        int countLow = registerCount & 0xFF;
        int countHigh = registerCount >>> 8;
        int[] data = new int[]{registerHigh, registerLow, countHigh, countLow};
        byte[] sendData = getModbusData(deviceAddress, 0x03, data);
        return sendData;
    }

    /**
     * 写指令
     * @param deviceAddress 设备地址
     * @param registerAddress 寄存器起始地址
     * @param writeData 寄存器个数
     * @return
     */
    public static byte[] getWriteModbus(int deviceAddress, int registerAddress, int[] writeData) {
        int registerLow = registerAddress & 0xFF;
        int registerHigh = registerAddress >>> 8;
        int[] data = new int[writeData.length + 2];
        data[0] = registerHigh;
        data[1] = registerLow;
        for (int i = 0; i < writeData.length; i ++) {
            data[i + 2] = writeData[i];
        }
        byte[] sendData = getModbusData(deviceAddress, 0x06, data);
        return sendData;
    }

    public static List<Byte> isValidModbusResponseData(List<Byte> list) {
        if (null != list && list.size() >= 4) {
            int size = list.size();
            int leng = ByteUtils.byteToInt(list.get(2));
            int totalSize = leng + 5;
            if (size < totalSize) {
                return null;
            }
            List tempList = list.subList(0, totalSize - 2);
            byte[] tempData = ArrayUtils.listTobyte(tempList);
            int crc = CRCUtils.getCRC(tempData);
            int low = crc & 0xFF;
            int high = crc >>> 8;
            byte lowData = list.get(totalSize - 2);
            byte hightData = list.get(totalSize - 1);
            if (low == ByteUtils.byteToInt(lowData) && high == ByteUtils.byteToInt(hightData)) {
                return list.subList(0, totalSize);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

    public static byte[] getModbusData(int address, int function, int[] data) {
        int leng = 2;
        if (null != data) {
            leng += data.length;
        }
        byte[] tempData = new byte[leng];
        tempData[0] = ByteUtils.intToByte(address);
        tempData[1] = ByteUtils.intToByte(function);
        if (null != data) {
            for (int i = 0; i < data.length; i++) {
                tempData[i + 2] = ByteUtils.intToByte(data[i]);
            }
        }
        int crc = CRCUtils.getCRC(tempData);
        int low = crc & 0xFF;
        int high = crc >>> 8;
        List list = new ArrayList();
        list.addAll(ArrayUtils.byteToList(tempData));
        list.add(ByteUtils.intToByte(low));
        list.add(ByteUtils.intToByte(high));
        return ArrayUtils.listTobyte(list);
    }
}

项目源码下载

上一篇 下一篇

猜你喜欢

热点阅读