三菱PLC编程口通信上位机端报文和java示范代码
讀操作:
發送 02 30 XX XX XX XX YY YY 03 CS CS
XX是寄存器地址轉16進制字符串,定長4個ASCII字符,YY是讀取的字節數轉16進制字符串,定長2個ASCII字符,CS是對從30(含)到03(含)的每一個字節求和(字節本身的數字0~255,而非它所代表的文字含意'0'~'F')然后除以256的余數轉十六進制的字符串,定長2個ASCII字符。字符串是以高位在低字節方式排序的,也就是閱讀順序。高位為0時不能省略,要寫‘0’字符,對應的字節數字為30。
返回 02 DD DD 03 CS CS
DD是讀取的字節轉十六進制字符串格式,數量一定是2的倍數(2個字符代表一個字節)。如果讀的是M,X,Y,則返回開關量的數量會自動補充成8的倍數,因為一字節是8位,如果你要3個,它會給你8個,低3位是你要的,高5位是贈送的。相鄰兩個字符代表一個8位字節,按閱讀順序(高4位在前),然后字節的含義是低位為低地址。如果讀的是D,則返回寄存器數量不會自動補成整數,你可以只讀半個寄存器(一個寄存器16位,但你可以對最后一個寄存器只讀8位)。相鄰兩個字符代表一個8位字節,按閱讀順序(高4位在前),然后相鄰兩字節則是低8位在前。4位(ASCII字符串的一個字符代表4位)組成8位時是大端在前,8位組16位則變為小端在前。
寫操作:
發送 02 31 XX XX XX XX YY YY DD DD?03 CS CS
把功能碼換成0x31,也就是字符'1'。然后在讀報文上加了DD,它是你需要發送的字節轉16進制字符串,所以DD的個數一定是2的倍數。因為DD只需要是2的倍數,所以你可以只寫半個寄存器,但最好別這樣做,這可能會讓你的代碼出Bug,然后你找很久都找不出來。如果你只想改一個M怎么辦?沒辦法,你只能先讀出另外7個M,然后再原樣寫回去。當然,如果你確定另外7個M沒有用,也可以不去管它。
返回06
表示成功操作
讀和寫失敗的時候都返回15,可能是報文問題,也可能是你操作了一個不存在的M或D,或者不可寫的M或D。三菱PLC不會告訴你具體的原因,你需要自己去查手冊然后去猜。
M和D、X、Y被安排在連續的地址空間,每一個前綴需要不同的增量。增量見下面那個MITSUBISHI_CONST的接口文件,里面有定義各種增量。它是字節為單位的,也就是說一個地址可能代表8個M或半個D。
讀寫M的時候需要地址對齊,這是硬件決定的,邏輯上需要注意。讀寫D的時候我建議你最好自覺對齊,不然不知道會發生什么。
FX3U已經沒有強制ON和強制OFF了。這兩項功能在以前的梯形圖調試的時候比較有用,GX work2已經沒有這一功能了。FX3U也不支持該指令。
我們可以看到三菱通信協議是基于字符串的,字符串(也叫“字符流”)是一種特殊的字節流(也就是常說的二進制數據格式),它在字節流的基礎上對字節的值域進行分配,將0~255個數字分成可見字符、不可見字符、控制字符三類,對字節的數值范圍分類使報文更容易設計。比如報文頭02,它是一個不可見字符(在早期的計算機系統它是控制字符,但現在不是了),它不可能與業務邏輯相沖突,便于報文對齊。如果沒有報文頭,則只能使用超時機制,超時對齊不如報文頭對齊穩定。
由于可用字符的范圍縮小,有些干擾會直接使報文中出現沒有定義的字節,這樣不需要校驗和就可以確定報文錯誤。
字符串便于閱讀,但美中不足的是三菱的寄存器是低8位在前的,一個按書寫順序為H1234的十六進制數,在三菱報文中顯示為H3412。東方人喜歡在小處偷懶,在字節的尺度上就直接用地址順序,代碼比較少;而單片機的地址尺度只細到8位的字節,字節中的位沒有地址順序,就只能按閱讀順序編碼。所以造成了三菱通訊協議單個字節中的位是按閱讀順序,多字節中的每個字節按地址順序。
使用字符串也有缺點。字符串如果不壓縮,要表達相同的信息會需要2倍于字節流的字節長度(一個字節當半個字節來用),如果壓縮,則會給單片機的編程造成很大的麻煩。低端的單片機甚至沒有足夠的程序存儲器來存放壓縮算法。因為需要2倍的字節數量,要達到相同的信息傳輸速率,字符串需要的比特率為字節流的2倍。由此看來,字節流由于大幅降低了比特率,反而使線路本身坑干擾的能力提升。
三菱PLC有一種DB9串口接頭的編程線,雖然USB接頭其實也是轉串口下載,但DB9的接頭更容易讓人萌生手拉手總線通信的念頭。但這在三菱PLC編程口通信是不行的。比較一下Modbus協議和三菱協議,在交互規則上有一點不同,Modbus如果校驗不通過不會有回復,而三菱PLC編程口通信不管收到什么都會有回復。如果用485轉換器把三菱PLC連接到手拉手總線通信上,不管上位機發信息還是其它下位機回復,三菱PLC都會有串口數據輸出,這將導致大量的報文被干擾,線路無法使用。
?
下面是一些示范代碼
常量定義:
package pers.laserpen.util.protocol.mitsubishi;interface MITSUBISHI_CONST {public static final char CMD_READ = '0';public static final char CMD_WRITE = '1';@Deprecatedpublic static final char CMD_FORCE_ON = '7';@Deprecatedpublic static final char CMD_FORCE_OFF = '8';public static final byte STRUCT_ENQ = 5;public static final byte STRUCT_ACK = 6;public static final byte STRUCT_NAK = (byte) 0x15;public static final byte STRUCT_STX = 2;public static final byte STRUCT_ETX = 3;public static final int BASE_D = 0x1000;public static final int BASE_SPECIAL_D = 0xe00;public static final int BASE_Y = 0xa0;public static final int BASE_PY = 0x2a0;public static final int BASE_T = 0xc0;public static final int BASE_OT = 0x2c0;public static final int BASE_RT = 0x4c0;public static final int BASE_M = 0x100;public static final int BASE_PM = 0x300;public static final int BASE_S = 0x0;public static final int BASE_X = 0x80;public static final int BASE_C = 0x1c0;public static final int BASE_OC = 0x3c0;public static final int BASE_RC = 0x5c0;public static final int BASE_TV = 0x800;public static final int BASE_CV16 = 0xa00;public static final int BASE_CV32 = 0xc00; }工具方法:
package pers.laserpen.util.protocol.mitsubishi;import static pers.laserpen.util.protocol.mitsubishi.MITSUBISHI_CONST.*;import java.util.HashMap; import java.util.Map; import java.util.function.IntUnaryOperator;abstract class StaticMitsubishiUtils {private static final Map<String, Integer> BASE_INDEX = new HashMap<>();static {BASE_INDEX.put("D", BASE_D);BASE_INDEX.put("SD", BASE_SPECIAL_D);BASE_INDEX.put("Y", BASE_Y);BASE_INDEX.put("PY", BASE_PY);BASE_INDEX.put("T", BASE_T);BASE_INDEX.put("OT", BASE_OT);BASE_INDEX.put("RT", BASE_RT);BASE_INDEX.put("M", BASE_M);BASE_INDEX.put("PM", BASE_PM);BASE_INDEX.put("S", BASE_S);BASE_INDEX.put("X", BASE_X);BASE_INDEX.put("C", BASE_C);BASE_INDEX.put("OC", BASE_OC);BASE_INDEX.put("RC", BASE_RC);BASE_INDEX.put("TV", BASE_TV);BASE_INDEX.put("CV16", BASE_CV16);BASE_INDEX.put("CV32", BASE_CV32);}private static final Map<String, IntUnaryOperator> SIZE_CONVERTER = new HashMap<>();static { // IntUnaryOperator same = i -> i;IntUnaryOperator bit = i -> {if (i % 8 != 0) {System.err.println("地址未對齊,將自動轉換成" + (i & (-1 << 3)));}return i / 8;};IntUnaryOperator word = i -> i << 1;IntUnaryOperator dword = i -> i << 2;SIZE_CONVERTER.put("D", word);SIZE_CONVERTER.put("SD", word);SIZE_CONVERTER.put("Y", bit);SIZE_CONVERTER.put("PY", bit);SIZE_CONVERTER.put("T", word);SIZE_CONVERTER.put("OT", word);SIZE_CONVERTER.put("RT", word);SIZE_CONVERTER.put("M", bit);SIZE_CONVERTER.put("PM", bit);SIZE_CONVERTER.put("S", bit);SIZE_CONVERTER.put("X", bit);SIZE_CONVERTER.put("C", word);SIZE_CONVERTER.put("OC", word);SIZE_CONVERTER.put("RC", word);SIZE_CONVERTER.put("TV", word);SIZE_CONVERTER.put("CV16", word);SIZE_CONVERTER.put("CV32", dword);}private static final byte toAscii(int num) {num &= 0xf;if (num < 10) {return (byte) ('0' + num);}return (byte) ('A' - 10 + num);}/*** 三菱PLC通信協議的校驗* * @param bytes 數據緩沖* @param checkSumIndex 校驗的第一個字節放在緩沖區的位置*/static final void checkSum(byte[] bytes, int checkSumIndex) {int sum = 0;for (int i = 1; i < checkSumIndex; ++i) {sum += 0xff & bytes[i];}bytes[checkSumIndex + 1] = toAscii(sum);sum /= 16;bytes[checkSumIndex] = toAscii(sum);}/*** 三菱PLC寄存器地址* * @param type* @param index* @return*/static final int getIndexOfRegex(String type, int index) {type = type.toUpperCase();int base = BASE_INDEX.get(type);index = SIZE_CONVERTER.get(type).applyAsInt(index);return base + index;}}?通信協議報文類(僅報文,不含通信):
package pers.laserpen.util.protocol.mitsubishi;import static pers.laserpen.util.protocol.mitsubishi.MITSUBISHI_CONST.*; import static pers.laserpen.util.protocol.mitsubishi.StaticMitsubishiUtils.*; import static pers.laserpen.util.data.StaticDataUtils.*;import pers.laserpen.util.data.AbstractBinaryDataSupplier; import pers.laserpen.util.data.StaticDataUtils; import pers.laserpen.util.protocol.CommunicationProtocol;public class MitsubishiPLC extends AbstractBinaryDataSupplier implements CommunicationProtocol {/*** */private static final long serialVersionUID = 1L;private char m_cmd = CMD_READ;private int m_index = 0;private int m_byteLength = 0;private boolean m_check;private byte[] m_data;/*** * @param type "D", "M", "X", "Y"等* @param index 必須是字節對齊的* @param byteLength 字節數(一字節為8個開關量)*/public void setRead(String type, int index, int byteLength) {setCmd(CMD_READ);setIndex(type, index);setByteLength(type, byteLength);}/*** * @param type "D", "M", "X", "Y"等* @param index 必須是字節對齊的* @param bytes*/public void setWrite(String type, int index, byte[] bytes) {setCmd(CMD_WRITE);setIndex(type, index);setByteLength(bytes.length);setData(bytes);}/*** * @param type* @param index 必須是字節對齊的* @param nums short型的數字*/public void setWriteD(String type, int index, short[] nums) {byte[] bytes = new byte[nums.length * 2];for (int i = 0, j = 0; i < nums.length; ++i) {bytes[j++] = (byte) (nums[i] & 0xff);bytes[j++] = (byte) ((nums[i] >>> 8) & 0xff);}setWrite(type, index, bytes);}public byte[] getRead() {return m_data;}public short[] getReadD() {if (m_data == null) {return null;}short[] words = new short[m_data.length / 2];for (int i = 0, j = 0; i < words.length; ++i) {int tempL = m_data[j++] & 0xff;int tempH = m_data[j++] & 0xff;int temp = (tempH << 8) | tempL;words[i] = (short) temp;}return words;}private void setCmd(char cmd) {m_cmd = cmd;}private void setIndex(String type, int index) {setIndex(getIndexOfRegex(type, index));}private void setIndex(int index) {m_index = index & 0xffff;}private void setByteLength(String type, int regexLength) {if ("XYM".contains(type)) {regexLength = (regexLength + 7) / 8;} else if ("D".contains(type)) {regexLength = regexLength * 2;}setByteLength(regexLength);}private void setByteLength(int byteLength) {m_byteLength = byteLength & 0xff;}private void setData(byte[] data) {m_data = data;}@Overridepublic byte[] get() {byte[] bytes = null;switch (m_cmd) {case CMD_READ: {bytes = new byte[11];bytes[0] = STRUCT_STX;bytes[1] = (byte) m_cmd;{String hex = convertBytesToHexString(convertIntegerToBytes(1, 0, null, m_index), true, "", null);hex = hex.toUpperCase();for (int i = 0; i < 4; ++i) {bytes[i + 2] = (byte) hex.charAt(i);}}{String hex = convertBytesToHexString(convertIntegerToBytes(0, 0, null, m_byteLength), true, "", null);hex = hex.toUpperCase();for (int i = 0; i < 2; ++i) {bytes[i + 6] = (byte) hex.charAt(i);}}bytes[8] = STRUCT_ETX;checkSum(bytes, 9);break;}case CMD_WRITE: {bytes = new byte[11 + m_data.length * 2];bytes[0] = STRUCT_STX;bytes[1] = (byte) m_cmd;{String hex = convertBytesToHexString(convertIntegerToBytes(1, 0, null, m_index), true, "", null);hex = hex.toUpperCase();for (int i = 0; i < 4; ++i) {bytes[i + 2] = (byte) hex.charAt(i);}}{String hex = convertBytesToHexString(convertIntegerToBytes(0, 0, null, m_byteLength), true, "", null);hex = hex.toUpperCase();for (int i = 0; i < 2; ++i) {bytes[i + 6] = (byte) hex.charAt(i);}}{String hex = convertBytesToHexString(m_data, true, "", null);hex = hex.toUpperCase();for (int i = 0; i < m_data.length * 2; ++i) {bytes[i + 8] = (byte) hex.charAt(i);}}bytes[bytes.length - 3] = STRUCT_ETX;checkSum(bytes, bytes.length - 2);break;} // case CMD_FORCE_ON: { // break; // } // case CMD_FORCE_OFF: { // break; // }}return bytes;}@Overridepublic void accept(byte[] bytes) {if (bytes == null || bytes.length == 0) {m_check = false;return;}if (bytes[0] == STRUCT_NAK || bytes[0] == STRUCT_ACK || bytes[0] == STRUCT_ENQ) {m_check = true;return;}switch (m_cmd) {case CMD_READ: {if (bytes[0] != STRUCT_STX || bytes[bytes.length - 3] != STRUCT_ETX) {m_check = false;return;}StringBuilder hex = new StringBuilder();for (int i = 1; i < bytes.length - 3; ++i) {hex.append((char) bytes[i]);}m_data = StaticDataUtils.convertHexStringToBytes(hex.toString());m_byteLength = m_data.length;byte[] temp = new byte[bytes.length];System.arraycopy(bytes, 0, temp, 0, bytes.length);checkSum(temp, temp.length - 2);if (temp[temp.length - 1] != bytes[bytes.length - 1] || temp[temp.length - 2] != bytes[bytes.length - 2]) {m_check = false;return;}m_check = true;break;}case CMD_WRITE: {m_data = null;m_byteLength = 0;break;}}return;}@Overridepublic boolean isCorrect() {return m_check;}}串口通信類(通信體系太大,全放上來沒人看得懂,這一部分只作展示,不能使用):
package pers.laserpen.util.communication.serialPort;import static pers.laserpen.util.communication.serialPort.NativeSerialPortUtils.*;import java.io.IOException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.function.Supplier;import pers.laserpen.util.communication.AbstractActiveIO; import pers.laserpen.util.communication.BufferedReceivable; import pers.laserpen.util.communication.CommunicationType; import pers.laserpen.util.java.BufferClearable; import pers.laserpen.util.thread.StaticThreadUtils;public class SerialPortRS232Win32IO extends AbstractActiveIO<SerialPortMessage>implements BufferClearable, BufferedReceivable<SerialPortMessage> {private long m_handle = 0;private int m_comPort;private int m_recvNativeBuffer, m_sendNativeBuffer, m_recvTempBuffer;private long m_baudRate;ByteSize m_byteSize;Parity m_parity;StopBits m_stopBits;private long m_recvTimeout;private long m_running = Long.MIN_VALUE;private final BlockingQueue<SerialPortMessage> m_msgQue = new LinkedTransferQueue<>();/*** * @param comPort 端口號1~254* @param buffer 統一設置所有緩沖* @param baudRate 比特率* @param byteSize 字節長度* @param stopBits 停止位* @param parity 校驗* @param recvTimeout 內核運行周期(影響到緩沖隊列的更新周期和關閉串口消耗的時間,所以不要用太大的數字。*/public SerialPortRS232Win32IO(int comPort, int buffer, int baudRate, ByteSize byteSize, StopBits stopBits,Parity parity, long recvTimeout) {this(comPort, buffer, buffer, buffer, baudRate, byteSize, stopBits, parity, recvTimeout);}/*** * @param comPort 端口號1~254* @param recvNativeBuffer 接收緩沖* @param sendNativeBuffer 改善緩沖* @param recvTempBuffer 應用層接收緩沖* @param baudRate 比特率* @param byteSize 字節長度* @param stopBits 停止位* @param parity 校驗* @param recvTimeout 內核運行周期(影響到緩沖隊列的更新周期和關閉串口消耗的時間,所以不要用太大的數字。*/public SerialPortRS232Win32IO(int comPort, int recvNativeBuffer, int sendNativeBuffer, int recvTempBuffer,int baudRate, ByteSize byteSize, StopBits stopBits, Parity parity, long recvTimeout) {m_comPort = comPort;m_recvNativeBuffer = recvNativeBuffer;m_sendNativeBuffer = sendNativeBuffer;m_recvTempBuffer = recvTempBuffer;m_baudRate = baudRate;m_byteSize = byteSize;m_parity = parity;m_stopBits = stopBits;m_recvTimeout = recvTimeout;}private void receiveListener(long runId) {try {for (; m_running == runId; StaticThreadUtils.sleep(m_recvTimeout)) {SerialPortMessage msg = doRead();if (msg == null) {continue;}m_msgQue.offer(msg);}} catch (IOException e) {// e.printStackTrace();} finally {System.out.println("exit background listener of COM" + m_comPort);}}private SerialPortMessage doRead() throws IOException {byte[] buffer = new byte[m_recvTempBuffer];int recvLen = NativeSerialPortUtils.read(m_handle, buffer);if (recvLen == 0) {return null;} else if (recvLen < 0) {if (getLastErrorCode() != 0) {System.err.println("last error when doRead: " + getLastErrorCode());close();throw new IOException();}return null;}byte[] msgData = new byte[recvLen];System.arraycopy(buffer, 0, msgData, 0, recvLen);SerialPortMessage msg = new SerialPortMessage();msg.accept(msgData);msg.setPort(m_comPort);msg.setReplier(msgReplied -> {return send(msgReplied);});return msg;}@Overrideprotected void disconnect() throws Throwable {System.out.println("order receive listener of COM" + m_comPort + " to quit");m_running = Long.MIN_VALUE;if (m_handle >= 0) {if (!closeCom(m_handle)) {System.err.println("last error when disconnect: " + getLastErrorCode());}m_handle = 0;}System.out.println("COM" + m_comPort + " closed");}@Overrideprotected void connect() throws Throwable {if (m_handle >= 0) {if (closeCom(m_handle)) {System.err.println("last error when connect closeCom: " + getLastErrorCode());}m_handle = 0;}m_handle = openCom(m_comPort);if (m_handle < 0) {System.err.println("last error when connect openCom: " + getLastErrorCode());throw new IOException("open com" + m_comPort + "failed");}if (!setBuffer(m_handle, m_recvNativeBuffer, m_sendNativeBuffer)) {System.err.println("last error when connect setBuffer: " + getLastErrorCode());throw new IOException("open com" + m_comPort + "failed");}if (!setTimeout(m_handle, -1, 0, 0, 0, 0)) {System.err.println("last error when connect setTimeout: " + getLastErrorCode());throw new IOException("open com" + m_comPort + "failed");}if (!setState(m_handle, m_baudRate, m_byteSize, m_parity, m_stopBits)) {System.err.println("last error when connect setState: " + getLastErrorCode());throw new IOException("open com" + m_comPort + "failed");}m_running = System.currentTimeMillis();StaticThreadUtils.execute(() -> receiveListener(m_running));System.out.println("COM" + m_comPort + " is opened");}@Overrideprotected SerialPortMessage read() throws Throwable {return m_msgQue.poll(m_recvTimeout, TimeUnit.MILLISECONDS);}@Overrideprotected boolean write(Supplier<byte[]> msg) throws Throwable {int sendLen = NativeSerialPortUtils.write(m_handle, msg.get(), msg.get().length);if (sendLen <= 0) {System.err.println("last error when write: " + getLastErrorCode());throw new IOException("write com" + m_comPort + " failed");// return false;}return true;}@Overridepublic SerialPortMessage receive(long blockTimeout) {if (!open()) {return null;}return BufferedReceivable.super.receive(blockTimeout);}@Overridepublic SerialPortMessage receive(long timeout, int lineLimit, Function<byte[], Boolean> breakCondition) {if (!open()) {return null;}return BufferedReceivable.super.receive(timeout, lineLimit, breakCondition);}@Overridepublic CommunicationType getCommunicationType() {return CommunicationType.SERIAL_PORT;}@Overridepublic BlockingQueue<SerialPortMessage> getBlockingQueue() {return m_msgQue;}@Overridepublic void clearBuffer() {m_msgQue.clear();}}串口Native接口:
package pers.laserpen.util.communication.serialPort;import pers.laserpen.util.string.ENCODING;public abstract class NativeSerialPortUtils {public static final int NOPARITY = 0;public static final int ODDPARITY = 1;public static final int EVENPARITY = 2;public static final int MARKPARITY = 3;public static final int SPACEPARITY = 4;public static final int ONESTOPBIT = 0;public static final int ONE5STOPBITS = 1;public static final int TWOSTOPBITS = 2;public static final int CBR_110 = 110;public static final int CBR_300 = 300;public static final int CBR_600 = 600;public static final int CBR_1200 = 1200;public static final int CBR_2400 = 2400;public static final int CBR_4800 = 4800;public static final int CBR_9600 = 9600;public static final int CBR_14400 = 14400;public static final int CBR_19200 = 19200;public static final int CBR_38400 = 38400;public static final int CBR_56000 = 56000;public static final int CBR_57600 = 57600;public static final int CBR_115200 = 115200;public static final int CBR_128000 = 128000;public static final int CBR_256000 = 256000;public static final long getLastErrorCode() {return getLastError();}public static final long openCom(int com) {String portStr = "\\\\.\\COM" + com + "\0";// C/C++無法識別byte[]的長度,需要添加一個0字符。return createFile(portStr.getBytes(ENCODING.US_ASCII()));}public static final boolean closeCom(long handle) {return closeHandle(handle);}public static boolean setBuffer(long handle, int inBuffer, int outBuffer) {return setupComm(handle, inBuffer, outBuffer);}public static boolean setSimpleTimeout(long handle) {return setCommTimeouts(handle, -1, 0, 0, 0, 0);}public static boolean setTimeout(long handle, long readIntervalTimeout, long readTotalTimeoutConstant,long readTotalTimeoutMultiplier, long writeTotalTimeoutConstant, long writeTotalTimeoutMultiplier) {return setCommTimeouts(handle, readIntervalTimeout, readTotalTimeoutConstant, readTotalTimeoutMultiplier,writeTotalTimeoutConstant, writeTotalTimeoutMultiplier);}public static final boolean setState(long handle, long baudRate, ByteSize byteSize, Parity parity,StopBits stopBits) {return setCommState(handle, baudRate, byteSize.getFlag(), parity.getFlag(), stopBits.getFlag());}public static final boolean ready(long handle) {return purgeComm(handle);}public static final int read(long handle, byte[] buffer) {return readFile(handle, buffer);}public static final int write(long handle, byte[] buffer, int length) {return writeFile(handle, buffer, length);}private native static long getLastError();private native static long createFile(byte[] portName);private native static boolean closeHandle(long handle);private native static boolean setupComm(long handle, long inBuffer, long outBuffer);private native static boolean setCommTimeouts(long handle, long readIntervalTimeout, long readTotalTimeoutConstant,long readTotalTimeoutMultiplier, long writeTotalTimeoutConstant, long writeTotalTimeoutMultiplier);private native static boolean setCommState(long handle, long baudRate, long byteSize, long parity, long stopBits);private native static boolean purgeComm(long handle);private native static int readFile(long handle, byte[] buffer);private native static int writeFile(long handle, byte[] buffer, int length); }串口Native實現——頭文件:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include "JNIInclude/jni.h" /* Header for class pers_laserpen_util_communication_serialPort_NativeSerialPortUtils */#ifndef _Included_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils #define _Included_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils #ifdef __cplusplus extern "C" { #endif /** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: getLastError* Signature: ()J*/ JNIEXPORT jlong JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_getLastError(JNIEnv *, jclass);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: createFile* Signature: ([B)J*/ JNIEXPORT jlong JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_createFile (JNIEnv *, jclass, jbyteArray);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: closeHandle* Signature: (J)V*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_closeHandle (JNIEnv *, jclass, jlong);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: setupComm* Signature: (JJJ)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_setupComm (JNIEnv *, jclass, jlong, jlong, jlong);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: setCommTimeouts* Signature: (JJJJJJ)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_setCommTimeouts (JNIEnv *, jclass, jlong, jlong, jlong, jlong, jlong, jlong);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: setCommState* Signature: (JJJJJ)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_setCommState (JNIEnv *, jclass, jlong, jlong, jlong, jlong, jlong);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: purgeComm* Signature: (J)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_purgeComm (JNIEnv *, jclass, jlong);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: readFile* Signature: (J[B)I*/ JNIEXPORT jint JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_readFile(JNIEnv *, jclass, jlong, jbyteArray);/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: writeFile* Signature: (J[BI)I*/ JNIEXPORT jint JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_writeFile (JNIEnv *, jclass, jlong, jbyteArray, jint);#ifdef __cplusplus } #endif #endif串口Native實現——源文件:
#include <malloc.h> #include <windows.h> #include "pers_laserpen_util_communication_serialPort_NativeSerialPortUtils.h"#ifdef __cplusplus extern "C" { #endif /** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: getLastError* Signature: ()J*/ JNIEXPORT jlong JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_getLastError (JNIEnv *, jclass) {return (unsigned long long)GetLastError(); }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: createFile* Signature: ([B)J*/ JNIEXPORT jlong JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_createFile (JNIEnv *jEnv, jclass jCls, jbyteArray jPortName) {int len = jEnv->GetArrayLength(jPortName);char *buf = (char*)malloc(len);jEnv->GetByteArrayRegion(jPortName, 0, len, (jbyte*)buf);//異步通信不支持頻繁開關操作,不能滿足Java版LaserpenUtil的快速自動重啟機制的要求,因此只能使用同步通信。HANDLE handle = CreateFile(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0&(FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED), NULL);free(buf);return (jlong)handle; }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: closeHandle* Signature: (J)V*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_closeHandle (JNIEnv *jEnv, jclass jCls, jlong handle) {return CloseHandle((HANDLE)handle); }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: setupComm* Signature: (JJJ)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_setupComm (JNIEnv *jEnv, jclass jCls, jlong handle, jlong inBuffer, jlong outBuffer) {return SetupComm((HANDLE)handle, inBuffer, outBuffer); }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: setCommTimeouts* Signature: (JJJJJJ)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_setCommTimeouts (JNIEnv *jEnv, jclass jCls, jlong handle, jlong ReadIntervalTimeout, jlong ReadTotalTimeoutConstant, jlong ReadTotalTimeoutMultiplier, jlong WriteTotalTimeoutConstant, jlong WriteTotalTimeoutMultiplier) {COMMTIMEOUTS timeouts;timeouts.ReadIntervalTimeout=ReadIntervalTimeout;timeouts.ReadTotalTimeoutConstant=ReadTotalTimeoutConstant;timeouts.ReadTotalTimeoutMultiplier=ReadTotalTimeoutMultiplier;timeouts.WriteTotalTimeoutConstant=WriteTotalTimeoutConstant;timeouts.WriteTotalTimeoutMultiplier=WriteTotalTimeoutMultiplier;return SetCommTimeouts((HANDLE)handle, &timeouts); }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: setCommState* Signature: (JJJJJ)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_setCommState (JNIEnv *jEnv, jclass jCls, jlong handle, jlong BaudRate, jlong ByteSize, jlong Parity, jlong StopBits) {DCB dcb;GetCommState((HANDLE)handle, &dcb);dcb.BaudRate=BaudRate;dcb.ByteSize=ByteSize;dcb.Parity=Parity;dcb.fBinary=TRUE;dcb.fParity=TRUE;dcb.StopBits=StopBits;return SetCommState((HANDLE)handle, &dcb); }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: purgeComm* Signature: (J)Z*/ JNIEXPORT jboolean JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_purgeComm (JNIEnv *jEnv, jclass jCls, jlong handle) {return PurgeComm((HANDLE)handle, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR); }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: readFile* Signature: (J[B)I*/ JNIEXPORT jint JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_readFile (JNIEnv *jEnv, jclass jCls, jlong handle, jbyteArray jBuffer) {int bufLen = jEnv->GetArrayLength(jBuffer);char *buf = (char*)malloc(bufLen);//jEnv->GetByteArrayRegion(jBuffer, 0, bufLen, (jbyte*)buf);DWORD recvLen;DWORD dwErrorFlags;COMSTAT ComStat;OVERLAPPED ov;ClearCommError((HANDLE)handle,&dwErrorFlags,&ComStat);memset(&ov, 0, sizeof(ov));if(!ReadFile((HANDLE)handle, buf, bufLen, &recvLen, &ov)) {if(GetLastError()==ERROR_IO_PENDING) {GetOverlappedResult((HANDLE)handle, &ov, &recvLen, TRUE);jEnv->SetByteArrayRegion(jBuffer, 0, recvLen, (jbyte*)buf);} else {recvLen = -1;}} else {jEnv->SetByteArrayRegion(jBuffer, 0, recvLen, (jbyte*)buf);}free(buf);return recvLen; }/** Class: pers_laserpen_util_communication_serialPort_NativeSerialPortUtils* Method: writeFile* Signature: (J[BI)I*/ JNIEXPORT jint JNICALL Java_pers_laserpen_util_communication_serialPort_NativeSerialPortUtils_writeFile (JNIEnv *jEnv, jclass jCls, jlong handle, jbyteArray jBuffer, jint length) {int bufLen = jEnv->GetArrayLength(jBuffer);char *buf = (char*)malloc(bufLen);jEnv->GetByteArrayRegion(jBuffer, 0, bufLen, (jbyte*)buf);DWORD sendLen;DWORD dwErrorFlags;COMSTAT ComStat;OVERLAPPED ov;ClearCommError((HANDLE)handle,&dwErrorFlags,&ComStat);memset(&ov, 0, sizeof(ov));if(!WriteFile((HANDLE)handle, buf, length, &sendLen, &ov)) {if(GetLastError()==ERROR_IO_PENDING) {GetOverlappedResult((HANDLE)handle, &ov, &sendLen, TRUE);} else {sendLen = -1;}}//jEnv->SetByteArrayRegion(jBuffer, 0, recvLen, (jbyte*)buf);free(buf);return sendLen; }#ifdef __cplusplus } #endif?
總結
以上是生活随笔為你收集整理的三菱PLC编程口通信上位机端报文和java示范代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS2015 C#程序打包成.exe之i
- 下一篇: 网页播放器代码集中营(2)