package cn.bayax.modbus;
import java.io.IOException;
import java.util.BitSet;
import android_serialport_api.SerialPort;
import cn.bayax.modbus.exception.ModbusError;
import cn.bayax.modbus.exception.ModbusErrorType;
import cn.bayax.utilities.ByteArrayReader;
import cn.bayax.utilities.ByteArrayWriter;
import cn.bayax.utilities.CRC16;
import cn.bayax.utilities.ThreadUtil;
import cn.bayax.utilities.TimeoutUtil;
/*
Modbus RTU master
*/
public class ModbusMaster {
private int timeout = 1000;
private SerialPort port;
public ModbusMaster(SerialPort port) {
this.port = port;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
synchronized public int[] execute(int slave, int function_code, int starting_address, int quantity_of_x, int output_value) throws IOException, ModbusError {
if (slave < 0 || slave > 255) {
throw new ModbusError(ModbusErrorType.ModbusInvalidArgumentError, "Invalid slave " + slave);
}
if (starting_address < 0 || starting_address > 0xffff) {
throw new ModbusError(ModbusErrorType.ModbusInvalidArgumentError, "Invalid starting_address " + starting_address);
}
if (quantity_of_x < 1 || quantity_of_x > 0xff) {
throw new ModbusError(ModbusErrorType.ModbusInvalidArgumentError, "Invalid quantity_of_x " + quantity_of_x);
}
boolean is_read_function = false;
int expected_length = 0;
// 构造request
ByteArrayWriter request = new ByteArrayWriter();
request.writeInt8(slave);
if (function_code == ModbusFunction.READ_COILS || function_code == ModbusFunction.READ_DISCRETE_INPUTS) {
is_read_function = true;
request.writeInt8(function_code);
request.writeInt16(starting_address);
request.writeInt16(quantity_of_x);
expected_length = (int) Math.ceil(0.1d * quantity_of_x / 8.0) + 5;
} else if (function_code == ModbusFunction.READ_INPUT_REGISTERS || function_code == ModbusFunction.READ_HOLDING_REGISTERS) {
is_read_function = true;
request.writeInt8(function_code);
request.writeInt16(starting_address);
request.writeInt16(quantity_of_x);
expected_length = 2 * quantity_of_x + 5;
} else if (function_code == ModbusFunction.WRITE_SINGLE_COIL || function_code == ModbusFunction.WRITE_SINGLE_REGISTER) {
if (function_code == ModbusFunction.WRITE_SINGLE_COIL)
if (output_value != 0) output_value = 0xff00;
request.writeInt8(function_code);
request.writeInt16(starting_address);
request.writeInt16(output_value);
expected_length = 8;
} else {
throw new ModbusError(ModbusErrorType.ModbusFunctionNotSupportedError, "Not support function " + function_code);
}
byte[] bytes = request.toByteArray();
int crc = CRC16.compute(bytes);
request.writeInt16Reversal(crc);
// 发送到设备
bytes = request.toByteArray();
port.getOutputStream().write(bytes);
// 从设备接收反馈
byte[] responseBytes;
try (ByteArrayWriter response = new ByteArrayWriter()) {
ThreadUtil.sleep(150);
final int finalExpected_length = expected_length;
final boolean[] complete = new boolean[1];
boolean done = TimeoutUtil.execute(new Runnable() {
@Override
public void run() {
try {
byte[] bytes = new byte[64];
while (!complete[0]) {
if (port.getInputStream().available() > 0) {
int len = port.getInputStream().read(bytes, 0, bytes.length);
if (len > 0) {
response.write(bytes, 0, len);
if (response.size() >= finalExpected_length) {
break;
}
}
}
ThreadUtil.sleep(1);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}, timeout);
complete[0] = true;
response.flush();
if (!done) {
throw new ModbusError(ModbusErrorType.ModbusTimeoutError, String.format("Timeout of %d ms.", timeout));
}
responseBytes = response.toByteArray();
}
if (responseBytes == null || responseBytes.length != expected_length) {
throw new ModbusError(ModbusErrorType.ModbusInvalidResponseError, "Response length is invalid " + responseBytes.length);
}
ByteArrayReader reader = new ByteArrayReader(responseBytes);
int responseSlave = reader.readInt8();
if (responseSlave != slave) {
throw new ModbusError(ModbusErrorType.ModbusInvalidResponseError,
String.format("Response slave %d is different from request slave %d", responseSlave, slave));
}
int return_code = reader.readInt8();
if (return_code > 0x80) {
int error_code = reader.readInt8();
throw new ModbusError(error_code);
}
int data_length = 0;
if (is_read_function) {
// get the values returned by the reading function
data_length = reader.readInt8();
int actualLength = responseBytes.length - 5;
if (data_length != actualLength) {
throw new ModbusError(ModbusErrorType.ModbusInvalidResponseError,
String.format("Byte count is %d while actual number of bytes is %d. ", data_length, actualLength));
}
}
// 读取反馈数据
int[] result = new int[quantity_of_x];
if (function_code == ModbusFunction.READ_COILS || function_code == ModbusFunction.READ_DISCRETE_INPUTS) {
bytes = new byte[data_length];
for (int i = 0; i < data_length; i++) {
bytes[i] = (byte) reader.readInt8();
}
BitSet bits = BitSet.valueOf(bytes);
for (int i = 0; i < quantity_of_x; i++) {
result[i] = bits.get(i) ? 1 : 0;
}
} else if (function_code == ModbusFunction.READ_INPUT_REGISTERS || function_code == ModbusFunction.READ_HOLDING_REGISTERS) {
for (int i = 0; i < quantity_of_x; i++) {
result[i] = reader.readInt16();
}
} else if (function_code == ModbusFunction.WRITE_SINGLE_COIL || function_code == ModbusFunction.WRITE_SINGLE_REGISTER) {
result[0] = reader.readInt16();
//result[1] = reader.readInt16();
}
return result;
}
public int[] readCoils(int slave, int startAddress, int numberOfPoints) throws IOException, ModbusError {
return execute(slave, ModbusFunction.READ_COILS, startAddress, numberOfPoints, 0);
}
public int[] readHoldingRegisters(int slave, int startAddress, int numberOfPoints) throws IOException, ModbusError {
return execute(slave, ModbusFunction.READ_HOLDING_REGISTERS, startAddress, numberOfPoints, 0);
}
public int[] readInputRegisters(int slave, int startAddress, int numberOfPoints) throws IOException, ModbusError {
return execute(slave, ModbusFunction.READ_INPUT_REGISTERS, startAddress, numberOfPoints, 0);
}
public int[] readInputs(int slave, int startAddress, int numberOfPoints) throws IOException, ModbusError {
return execute(slave, Modb
没有合适的资源?快使用搜索试试~ 我知道了~
Android通过ModbusRtu串口控制PLC程序源码
共17个文件
java:12个
mk:2个
c:1个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
5星 · 超过95%的资源 16 下载量 158 浏览量
2022-01-15
17:33:47
上传
评论 1
收藏 80KB ZIP 举报
温馨提示
【工控老马出品,必属精品,亲测校正,质量保证】 资源名:Android通过ModbusRtu串口控制PLC程序源码 资源类型:程序源代码 源码说明: 在单板机承载的Android系统中,通过串口以Modbus RTU协议操控PLC的类库。改编自python类库modbus_tk。 适合人群:新手及有一定经验的开发人员
资源推荐
资源详情
资源评论
收起资源包目录
Android通过ModbusRtu串口控制PLC程序源码.zip (17个子文件)
Android通过ModbusRtu串口控制PLC程序源码
ResourceHome.png 63KB
jni
Application.mk 62B
Android.mk 741B
serialport
SerialPort.h 757B
SerialPort.c 5KB
java
android_serialport_api
SerialPort.java 3KB
SerialPortFinder.java 3KB
cn
bayax
utilities
TimeoutUtil.java 1KB
ByteArrayWriter.java 864B
CRC16.java 9KB
ByteArrayReader.java 732B
ByteUtil.java 3KB
ThreadUtil.java 8KB
modbus
ModbusFunction.java 382B
exception
ModbusError.java 585B
ModbusErrorType.java 399B
ModbusMaster.java 9KB
共 17 条
- 1
工控老马
- 粉丝: 589
- 资源: 2625
下载权益
C知道特权
VIP文章
课程特权
开通VIP
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 基于pygame实现的烟花代码
- mcu-printf关于51单片机使用printf函数进行串口调试的方法
- MySQL和数据表操作
- 微信小程序面试题.pdf
- 基于matlab实现电力系统仿真计算软件包,包括潮流计算,最优潮流计算等.rar
- 基于matlab实现电力系统各种故障波形仿真,单相接地故障,两相间短路,两相接地短路,三相短路等.rar
- 基于matlab实现电动汽车动力性,爬坡性,续驶里程等性能仿真.rar
- Python动态烟花代码.pdf
- 基于matlab实现串口发送接收数据 可配置端口,波特率等 发送可选择ASCII方式或HEX方式
- matlab基于BP神经网络手写字母识别(单一).zip代码9
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
前往页