| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- package com.mes.ui;
- import com.fazecast.jSerialComm.*;
- import java.math.BigInteger;
- public class ModbusRtu {
- public static SerialPort connect(){
- try{
- SerialPort serialPort = SerialPort.getCommPort("COM5"); // 替换为你的端口名
- serialPort.setComPortParameters(38400, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY); // 设置端口参数
- serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 1000, 0);
- if (serialPort.openPort()) {
- System.out.println("Port opened successfully.");
- return serialPort;
- } else {
- return null;
- }
- }catch (Exception e){
- e.printStackTrace();
- return null;
- }
- }
- public static void disconnect(SerialPort serialPort) {
- if (serialPort != null && serialPort.isOpen()) {
- serialPort.closePort();
- }
- }
- public static SerialPort reconnect(SerialPort serialPort) {
- disconnect(serialPort);
- return connect();
- }
- public static void openDevice(SerialPort serialPort) {
- System.out.println("isOpen:");
- if(serialPort ==null || !serialPort.isOpen()){
- serialPort = reconnect(serialPort);
- }
- try {
- String writeString = "010600000000"; // 关
- String crc = getCRC16_Modbus_Str(writeString);
- byte[] writeBuffer = hexStringToByteArray(writeString+crc);
- serialPort.writeBytes(writeBuffer, writeBuffer.length);
- // 接收数据
- byte[] readBuffer = new byte[512]; // 调整数组大小以适应预期的响应长度
- int numRead = serialPort.readBytes(readBuffer, readBuffer.length);
- System.out.println("Read " + numRead + " bytes.");
- // 将读取的字节转换为十六进制字符串
- StringBuilder data = new StringBuilder();
- for (int i = 0; i < numRead; i++) {
- data.append(String.format("%02X", readBuffer[i]));
- }
- String revStr = data.toString();
- // String ret = revStr.substring(6,8);
- System.out.println("Received data: " + revStr);
- // System.out.println("ret data: " + ret);
- } catch (Exception e) {
- e.printStackTrace();
- serialPort.closePort();
- } finally {
- }
- }
- public static void closeDevice(SerialPort serialPort) {
- if(serialPort ==null || !serialPort.isOpen()){
- serialPort = reconnect(serialPort);
- }
- try {
- String writeString = "010600000001"; // 开
- String crc = getCRC16_Modbus_Str(writeString);
- byte[] writeBuffer = hexStringToByteArray(writeString+crc);
- serialPort.writeBytes(writeBuffer, writeBuffer.length);
- // 接收数据
- byte[] readBuffer = new byte[512]; // 调整数组大小以适应预期的响应长度
- int numRead = serialPort.readBytes(readBuffer, readBuffer.length);
- System.out.println("Read " + numRead + " bytes.");
- // 将读取的字节转换为十六进制字符串
- StringBuilder data = new StringBuilder();
- for (int i = 0; i < numRead; i++) {
- data.append(String.format("%02X", readBuffer[i]));
- }
- String revStr = data.toString();
- // String ret = revStr.substring(6,8);
- System.out.println("Received data: " + revStr);
- // System.out.println("ret data: " + ret);
- } catch (Exception e) {
- e.printStackTrace();
- serialPort.closePort();
- } finally {
- }
- }
- public static Boolean readCoil(SerialPort serialPort,int pos) {
- if(serialPort ==null || !serialPort.isOpen()){
- serialPort = reconnect(serialPort);
- }
- try {
- String writeString = "010100000"+pos+"01"; // 线圈地址 0/1,目前只有2路
- String crc = getCRC16_Modbus_Str(writeString);
- byte[] writeBuffer = hexStringToByteArray(writeString+crc);
- serialPort.writeBytes(writeBuffer, writeBuffer.length);
- // 接收数据
- byte[] readBuffer = new byte[512]; // 调整数组大小以适应预期的响应长度
- int numRead = serialPort.readBytes(readBuffer, readBuffer.length);
- System.out.println("Read " + numRead + " bytes.");
- // 将读取的字节转换为十六进制字符串
- StringBuilder data = new StringBuilder();
- for (int i = 0; i < numRead; i++) {
- data.append(String.format("%02X", readBuffer[i]));
- }
- String revStr = data.toString();
- String ret = revStr.substring(6,8);
- System.out.println("Received data: " + revStr);
- System.out.println("ret data: " + ret);
- if(ret.equals("01")){
- MesClient.setPublicSerialStatus("采集:true",0);
- return true;
- }else{
- MesClient.setPublicSerialStatus("采集:false",0);
- return false;
- }
- } catch (Exception e) {
- e.printStackTrace();
- MesClient.setPublicSerialStatus("串口断线",-1);
- serialPort.closePort();
- return false;
- }
- }
- /**
- * CRC16(modbus)校验
- * 获取crc16校验码,参数data中不能有空格
- * @param data
- * @return
- */
- public static String getCRC16_Modbus_Str(String data) {
- data = data.replace(" ", "");
- int len = data.length();
- if (!(len % 2 == 0)) {
- return "0000";
- }
- int num = len / 2;
- byte[] para = new byte[num];
- for (int i = 0; i < num; i++) {
- int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
- para[i] = (byte) value;
- }
- return getCRC(para);
- }
- /**
- * 计算CRC16校验码
- * @param bytes
- * 字节数组
- * @return {@link String} 校验码
- * @since 1.0
- */
- public static String getCRC(byte[] bytes) {
- // CRC寄存器全为1
- int CRC = 0x0000ffff;
- // 多项式校验值
- int POLYNOMIAL = 0x0000a001;
- int i, j;
- for (i = 0; i < bytes.length; i++) {
- CRC ^= ((int) bytes[i] & 0x000000ff);
- for (j = 0; j < 8; j++) {
- if ((CRC & 0x00000001) != 0) {
- CRC >>= 1;
- CRC ^= POLYNOMIAL;
- } else {
- CRC >>= 1;
- }
- }
- }
- // 结果转换为16进制
- String result = Integer.toHexString(CRC).toUpperCase();
- if (result.length() != 4) {
- StringBuffer sb = new StringBuffer("0000");
- result = sb.replace(4 - result.length(), 4, result).toString();
- }
- //高位在前地位在后
- //return result.substring(2, 4) + " " + result.substring(0, 2);
- // 交换高低位,低位在前高位在后
- return result.substring(2, 4) + result.substring(0, 2);
- }
- public static byte[] hexStringToByteArray(String hexString) {
- // 去除字符串前后的空格
- hexString = hexString.trim();
- // 确保字符串的长度是偶数
- if (hexString.length() % 2 != 0) {
- throw new IllegalArgumentException("Invalid hex string");
- }
- // 将字符串转换为BigInteger对象
- BigInteger bigInt = new BigInteger(hexString, 16);
- // 获取BigInteger表示的字节数组
- byte[] byteArray = bigInt.toByteArray();
- // 处理符号位,如果数组的长度大于字符串的长度,则将符号位字节去除
- if (byteArray.length > hexString.length() / 2) {
- byte[] trimmedArray = new byte[hexString.length() / 2];
- System.arraycopy(byteArray, 1, trimmedArray, 0, trimmedArray.length);
- return trimmedArray;
- }
- return byteArray;
- }
- }
|