依据 《利用Java实现串口全双工通讯》蒋清野 更新。
更新1:修正其源代码返回的字符数比发送的字符数滞后的BUG
更新2:修正javax.comm的BUG。此BUG表现为 java BlackBox 总是返回 No serial ports found!
注:更新处标注 update by LZA
环境:Win7 + JDK1.7 + Java Communications API 2.0 (comm.jar)
ReadSerial.java
//package serial; import java.io.*; /** * * This class reads message from the specific serial port and save the message * to the serial buffer. * */ public class ReadSerial extends Thread { private SerialBuffer ComBuffer; private InputStream ComPort; /** * * Constructor * * @param SB * The buffer to save the incoming messages. * @param Port * The InputStream from the specific serial port. * */ public ReadSerial(SerialBuffer SB, InputStream Port) { ComBuffer = SB; ComPort = Port; } public void run() { int c; try { while (true) { c = ComPort.read(); ComBuffer.PutChar(c); } } catch (IOException e) { } } }
SerialBean.java
//package serial; import java.io.*; import java.util.*; import javax.comm.*; /** * * This bean provides some basic functions to implement full dulplex information * exchange through the srial port. * */ public class SerialBean { static String PortName; CommPortIdentifier portId; SerialPort serialPort; static OutputStream out; static InputStream in; SerialBuffer SB; ReadSerial RT; /** * * Constructor * * @param PortID * the ID of the serial to be used. 1 for COM1, 2 for COM2, etc. * */ public SerialBean(int PortID) { PortName = "COM" + PortID; } /** * * This function initialize the serial port for communication. It startss a * thread which consistently monitors the serial port. Any signal capturred * from the serial port is stored into a buffer area. * */ public int Initialize() { int InitSuccess = 1; int InitFail = -1; try { portId = CommPortIdentifier.getPortIdentifier(PortName); try { serialPort = (SerialPort) portId.open("Serial_Communication", 2000); } catch (PortInUseException e) { return InitFail; } // Use InputStream in to read from the serial port, and OutputStream // out to write to the serial port. try { in = serialPort.getInputStream(); out = serialPort.getOutputStream(); } catch (IOException e) { return InitFail; } // Initialize the communication parameters to 9600, 8, 1, none. try { serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException e) { return InitFail; } } catch (NoSuchPortException e) { return InitFail; } // when successfully open the serial port, create a new serial buffer, // then create a thread that consistently accepts incoming signals from // the serial port. Incoming signals are stored in the serial buffer. SB = new SerialBuffer(); RT = new ReadSerial(SB, in); RT.start(); // return success information return InitSuccess; } /** * * This function returns a string with a certain length from the incomin * messages. * * @param Length * The length of the string to be returned. * */ public String ReadPort(int Length) { String Msg; Msg = SB.GetMsg(Length); return Msg; } /** * * This function sends a message through the serial port. * * @param Msg * The string to be sent. * */ public void WritePort(String Msg) { int c; try { for (int i = 0; i < Msg.length(); i++) out.write(Msg.charAt(i)); } catch (IOException e) { } } /** * * This function closes the serial port in use. * */ public void ClosePort() { RT.stop(); serialPort.close(); } }
SerialBuffer.java
//package serial; /** * * This class implements the buffer area to store incoming data from the serial * port. * */ public class SerialBuffer { private String Content = ""; private String CurrentMsg, TempContent; private boolean available = false; private int LengthNeeded = 1; /** * * This function returns a string with a certain length from the incomin * messages. * * @param Length * The length of the string to be returned. * */ public synchronized String GetMsg(int Length) { LengthNeeded = Length; notifyAll(); if (LengthNeeded > Content.length()) { available = false; while (available == false) { try { wait(); } catch (InterruptedException e) { } } } CurrentMsg = Content.substring(0, LengthNeeded); TempContent = Content.substring(LengthNeeded); Content = TempContent; LengthNeeded = 1; notifyAll(); return CurrentMsg; } /** * * This function stores a character captured from the serial port to the * buffer area. * * @param t * The char value of the character to be stored. * */ public synchronized void PutChar(int c) { Character d = new Character((char) c); Content = Content.concat(d.toString()); if (LengthNeeded <= Content.length()) // update by LZA { available = true; } notifyAll(); } }
SerialExample.java
import java.io.*; import java.util.*; import javax.comm.*; import com.sun.comm.*; class SerialExample { public static void main(String[] args) { // update by LZA Win32Driver w32Driver = new Win32Driver(); // 这两行修正javax.comm的BUG w32Driver.initialize(); // 这才正常初始化,才会正常找出所有port // TO DO: Add your JAVA codes here SerialBean SB = new SerialBean(1); String Msg; SB.Initialize(); for (int i = 5; i <= 10; i++) { Msg = SB.ReadPort(i); SB.WritePort("Reply: " + Msg); } SB.ClosePort(); } }