Modbus был разработан компанией MODICON в 1979 году и представляет собой стандарт протокола промышленной полевой шины. В 1996 году Шнайдер запустил протокол Modbus, основанный на Ethernet TCP/IP: ModbusTCP. Протокол Modbus — это протокол передачи сообщений прикладного уровня, включающий три типа сообщений: ASCII, RTU и TCP. Стандартные интерфейсы физического уровня протокола Modbus включают интерфейсы RS232, RS422, RS485 и Ethernet, которые обмениваются данными в режиме «ведущий/подчиненный».
Личное ощущение:
modbusпротокол Это тоже верноадресная переменная
Выполнять операции чтения или записи,Что может измениться, так этоадресная переменнаяизадрес
итип данных
。
Этот код функции (определяет, что делать для 4 различных регистров объекта Modbus: читать, записывать или выполнять несколько операций вместе)
Связь между Modbus и RS485: Modbus — это протокол, а интерфейсы физического уровня включают интерфейсы RS232, RS422, RS485 и Ethernet.
Я хочу написать Мастер (главную станцию), поэтому мне нужен Слейв (ведомая станция)
Убедитесь, что для четырех часто используемых функций «Код», «Программное обеспечение для моделирования» отображаются F=01, F=02, F=03 и F=04.
Соответствующий код необходимо написать в 4 методах
Понимание параметров кода
saveid: См. информацию «На шине Modbus может быть несколько подчиненных станций», Программное обеспечение для тестирование может моделировать ведомую станцию, которая имеет ID=1, естественно ее можно модифицировать на ID=2Код функции:4индивидуальный Код функция, соответствующая написанию 4-х методов, Программное обеспечение для F=1 при рассмотрении или F=2, 3, 4адрес: когда вы впервые смотрите на код, адреса всех четырех методов начинаются с 0. Повторяются ли они? Ответ: 4 Код. функциивыражать4индивидуальный区域或者设备,addrвыражать各自区域изадрессерийный номер。
Выберите режим TCP, порт фиксированный 502.
F8:
Slave Definition
Вы можете свободно установить начальный адрес адреса (по умолчанию 0) и установить номер (по умолчанию 10).
Код функции
действовать:Создайте четыре новых разных Кода. окно функции, затем запустите код и измените Программное обеспечение для Стоимость рассмотрения.
Код функции01
Код функции02
Код функции03,выбиратьFloatтип
подписано: подписано без знака: без знака шестнадцатеричный: шестнадцатеричный двоичный: двоичный
big-endian: big endian, сохраняет старший байт по начальному адресу (старшая адресация) Little-endian: Little-endian, сохраняет младший байт по начальному адресу (младшая адресация).
обмен: обмен
Дважды щелкните первый адрес для ввода данных, и вам будет предложено ввести тип данных. 32-битные данные занимают 2 адреса, поэтому следующий адрес:
Код функции04
<!-- Если вы хотите ссылаться на modbus4j, вам необходимо ввести следующий репозиторий id:ias-snapshots id:ias-releases два ,Загрузка с использованием репозитория по умолчанию,Не используйте облачный склад Alibaba.-->
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>ias-snapshots</id>
<name>Infinite Automation Snapshot Repository</name>
<url>https://maven.mangoautomation.net/repository/ias-snapshot/</url>
</repository>
<repository>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>ias-releases</id>
<name>Infinite Automation Release Repository</name>
<url>https://maven.mangoautomation.net/repository/ias-release/</url>
</repository>
</repositories>
<!-- modbus4j -->
<dependency>
<groupId>com.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.0.3</version>
</dependency>
Класс подключения ModbusTcpMaster
@Service(value = "ModbusTcpMaster")
public class ModbusTcpMaster {
private final ModbusFactory modbusFactory = new ModbusFactory();
/**
* Получить раба
* @return
* @throws ModbusInitException
*/
public ModbusMaster getSlave(String ip,int port) {
ModbusMaster master = null;
try {
IpParameters params = new IpParameters();
params.setHost(ip);
params.setPort(port);
//Этот атрибут определяет, является ли кадр протокола структурой RTU, инкапсулированной через TCP с использованием Modbus При использовании TCP/IP установите значение false. с использованием Modbus rtu over Для TCP/IP установите значение true
params.setEncapsulated(false);
// modbusFactory.createRtuMaster(wapper); //RTU протокол
// modbusFactory.createUdpMaster(params);//UDP протокол
// modbusFactory.createAsciiMaster(wrapper);//ASCII протокол
master = modbusFactory.createTcpMaster(params, false);
//Максимальное время ожидания
master.setTimeout(2000);
//Максимальное количество подключений
master.setRetries(5);
master.init();
} catch (ModbusInitException e) {
e.printStackTrace();
}
return master;
}
}
Класс Modbus4jReadUtil
public class Modbus4jReadUtil {
/**
* Читать[01 Coil Status 0x] тип выключательданные *
* @param slaveId slaveId
* @param offset Расположение
* @return Чтение значения
* @throws ModbusTransportException аномальный
* @throws ErrorResponseException аномальный
*/
public static Boolean readCoilStatus(ModbusMaster master,int slaveId, int offset,String dev_code){
// 01 Coil Status
BaseLocator<Boolean> loc = BaseLocator.coilStatus(slaveId, offset);
try {
return master.getValue(loc);
}catch (Exception e){
if (e.getMessage().equals("java.net.SocketTimeoutException: connect timed out")) System.err.println(dev_code+":"+e.getMessage());
else e.printStackTrace();
return null;
}
}
/**
* Читать[02 Input Status 1x] тип выключательданные *
* @param slaveId
* @param offset
* @return
* @throws ModbusTransportException
* @throws ErrorResponseException
*/
public static Boolean readInputStatus(ModbusMaster master,int slaveId, int offset,String dev_code) {
// 02 Input Status
BaseLocator<Boolean> loc = BaseLocator.inputStatus(slaveId, offset);
try{
return master.getValue(loc);
}catch (Exception e){
if (e.getMessage().equals("java.net.SocketTimeoutException: connect timed out")) System.err.println(dev_code+":"+e.getMessage());
else e.printStackTrace();
return null;
}
}
/**
* Читать[03 Holding Тип регистрации 2x]Аналоговое количестводанные *
* @param slaveId slave Id
* @param offset Расположение
* @param dataType тип данных,Из com.serotonin.modbus4j.code.DataType. * @return
* @throws ModbusTransportException аномальный
* @throws ErrorResponseException аномальный
*/
public static Number readHoldingRegister(ModbusMaster master,int slaveId, int offset, int dataType,String dev_code) {
// 03 Holding Тип регистрацииданные读取
BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
try {
return master.getValue(loc);
}catch (Exception e){
if (e.getMessage().equals("java.net.SocketTimeoutException: connect timed out")) System.err.println(dev_code+":"+e.getMessage());
else e.printStackTrace();
return null;
}
}
/**
* Читать[04 Input Registers 3x] тип Аналоговое количестводанные *
* @param slaveId slaveId
* @param offset Расположение
* @param dataType тип данных,Из com.serotonin.modbus4j.code.DataType. * @return Возврат результатов
* @throws ModbusTransportException аномальный
* @throws ErrorResponseException аномальный
*/
public static Number readInputRegisters(ModbusMaster master,int slaveId, int offset, int dataType,String dev_code) {
// 04 Input Регистры типа данных для чтения
BaseLocator<Number> loc = BaseLocator.inputRegister(slaveId, offset, dataType);
try{
return master.getValue(loc);
}catch (Exception e){
if (e.getMessage().equals("java.net.SocketTimeoutException: connect timed out")) System.err.println(dev_code+":"+e.getMessage());
else e.printStackTrace();
return null;
}
}
/**
* Как использовать пакетное чтение
*
* @throws ModbusTransportException
* @throws ErrorResponseException
*/
public static void batchRead(ModbusMaster master) throws ModbusTransportException, ErrorResponseException {
BatchRead<Integer> batch = new BatchRead<Integer>();
batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.TWO_BYTE_INT_SIGNED));
batch.addLocator(1, BaseLocator.inputStatus(1, 0));
batch.setContiguousRequests(true);
BatchResults<Integer> results = master.send(batch);
System.out.println("batchRead:" + results.getValue(0));
System.out.println("batchRead:" + results.getValue(1));
}
}
тест
@Autowired
@Qualifier(value = "ModbusTcpMaster")
ModbusTcpMaster masterTcp;
@Test
public void test() {
//Открываем соединение ModbusTcpMaster
ModbusMaster master = masterTcp.getSlave("127.0.0.1", 502);
try {
// 01тест
Boolean v011 = Modbus4jReadUtil.readCoilStatus(master,1, 0,"test_code");
Boolean v012 = Modbus4jReadUtil.readCoilStatus(master,1, 1,"test_code");
Boolean v013 = Modbus4jReadUtil.readCoilStatus(master,1, 6,"test_code");
System.out.println("v011:" + v011);
System.out.println("v012:" + v012);
System.out.println("v013:" + v013);
// 02тест
Boolean v021 = Modbus4jReadUtil.readInputStatus(master,1, 0,"test_code");
Boolean v022 = Modbus4jReadUtil.readInputStatus(master,1, 1,"test_code");
Boolean v023 = Modbus4jReadUtil.readInputStatus(master,1, 2,"test_code");
System.out.println("v021:" + v021);
System.out.println("v022:" + v022);
System.out.println("v023:" + v023);
// 03тест
Number v031 = Modbus4jReadUtil.readHoldingRegister(master,1, 1, DataType.FOUR_BYTE_FLOAT,"test_code");// Обратите внимание, плавайте
Number v032 = Modbus4jReadUtil.readHoldingRegister(master,1, 3, DataType.FOUR_BYTE_FLOAT,"test_code");// То же, что и выше
System.out.println("v031:" + v031);
System.out.println("v032:" + v032);
// 04тест
Number v041 = Modbus4jReadUtil.readInputRegisters(master,1, 0, DataType.FOUR_BYTE_FLOAT,"test_code");//
Number v042 = Modbus4jReadUtil.readInputRegisters(master,1, 2, DataType.FOUR_BYTE_FLOAT,"test_code");//
System.out.println("v041:" + v041);
System.out.println("v042:" + v042);
// пакетное чтение
Modbus4jReadUtil.batchRead(master);
} catch (Exception e) {
e.printStackTrace();
}
}
подчиненная конфигурация
действовать:Создайте четыре новых разных Кода. окно функции, затем запустите код и измените Программное обеспечение для Стоимость рассмотрения.
Выход:
v011:true
v012:false
v013:true
v021:true
v022:false
v023:true
v031:7.5
v032:10.5
v041:1.5
v042:3.0
7.5
true
Классы Modbus4jWriteUtils
public class Modbus4jWriteUtils{
/**
* Запишите данные о значении одного (катушки) переключателя.
* Код функция: 05, точка выхода переключателя Q устанавливается или сбрасывается, запись данных в регистр типа DO реальной машины, логический тип (0x), который можно читать и записывать.
* @param slaveId идентификатор подчиненного устройства
* @param writeOffset Расположение-预访问изадрес-адресобъем:0-255
* @param writeValue Значение — 1, если установлено, 0, если сброшено.
* @return Успешно ли написание
*/
public static boolean writeCoil(ModbusMaster master,int slaveId, int writeOffset, boolean writeValue){
boolean flag = false;
try {
// Создать запрос
WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
// Отправьте запрос и получите объект ответа
WriteCoilResponse response = (WriteCoilResponse) master.send(request);
flag = !response.isException();
}catch (ModbusTransportException e){
e.printStackTrace();
}
return flag;
}
/**
* Запись нескольких значений переключения данных (катушек)
* Код функциидля:0F,Запись нескольких значений переключения данных (катушек)
* @param slaveId slaveId
* @param startOffset начинать Расположение
* @param bdata писатьизданные * @return Успешно ли написание
*/
public static boolean writeCoils(ModbusMaster master,int slaveId, int startOffset, boolean[] bdata) {
boolean flag = false;
try {
// Создать запрос
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata);
// Отправьте запрос и получите объект ответа
WriteCoilsResponse response = (WriteCoilsResponse) master.send(request);
flag = !response.isException();
}catch (ModbusTransportException e){
e.printStackTrace();
}
return flag;
}
/***
* Регистр временного хранения записывает одиночный
* Код функция: 06, запись данных в память V, данные на реальную машину, тип данные — это Int, числовой тип, который можно читать и записывать (4x).
* @param slaveId slaveId
* @param writeOffset начинать Расположение
* @param writeValue писатьизданные */
public static boolean writeRegister(ModbusMaster master,int slaveId, int writeOffset, short writeValue){
boolean flag = false;
try {
// Создать объект запроса
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
// Отправьте запрос и получите объект ответа
WriteRegisterResponse response = (WriteRegisterResponse) master.send(request);
flag = !response.isException();
}catch (ModbusTransportException e){
e.printStackTrace();
}
return flag;
}
/**
* Запись нескольких аналоговых величин в данные регистра временного хранения.
* Код функциидля:16,Воляданныеписать至多индивидуальныйVпамять,писатьданные на реальную машину, тип data is short[], числовой тип, который можно читать и записывать (4x).
* @param slaveId идентификатор подчиненного устройства Modbus
* @param startOffset Начальное значение смещения регулировки
* @param sdata писатьизданные * @return возвращаться Успешно ли написание
*/
public static boolean writeRegisters(ModbusMaster master,int slaveId, int startOffset, short[] sdata) {
boolean flag = false;
try {
// Создать объект запроса
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata);
// Отправьте запрос и получите объект ответа
WriteRegistersResponse response = (WriteRegistersResponse) master.send(request);
flag = !response.isException();
}catch (ModbusTransportException e){
e.printStackTrace();
}
return flag;
}
/**
* Запись данных в соответствии с типом (например: запись аналогового типа Float, аналогового типа Double, целочисленного типа Short, Integer, Long)
*
* @param value записать значение
* @param dataType com.serotonin.modbus4j.code.DataType
*/
public static void writeHoldingRegister(ModbusMaster master,int slaveId, int offset, Number value, int dataType) {
try {
// тип
BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
master.setValue(locator, value);
}catch (Exception e){
e.printStackTrace();
}
}
}
тест
@Autowired
@Qualifier(value = "ModbusTcpMaster")
ModbusTcpMaster masterTcp;
@Test
public void test() {
//Открываем соединение ModbusTcpMaster
ModbusMaster master = masterTcp.getSlave("127.0.0.1", 502);
try {
//Запись аналоговой величины
writeHoldingRegister(master,1,0, 10.1f, DataType.FOUR_BYTE_FLOAT);
} catch (Exception e) {
e.printStackTrace();
}
}