依据 《利用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();
}
}