以前做过一个针对串口扫描枪解析的项目,当时是用的java.comm包。回忆一下当时是怎么做的。
第一步:下载comm包,它包含有三个文件win32com.dll、comm.jar、javax.comm.properties
第二步:分别将他们拷到对应的文件夹
xcopy "system\win32com.dll" "%JAVA_HOME%\jre6\bin\" /E
xcopy "system\comm.jar" "%JAVA_HOME%\jre6\lib\" /E
xcopy "system\javax.comm.properties" "%JAVA_HOME%\jre6\lib\" /E
private CommPortIdentifier portId;
private SerialPort serialPort;
private InputStream is;
private ReaderThread t;
private static final String PortName = "COM1"; //串口号
private static final int DATABITS = 8; //数据位
private static final int STOPBITS = 1; //停止位
private static final int RATE = 9600; //波特率
try{
this.portId = CommPortIdentifier.getPortIdentifier(getPortName());
this.serialPort = ((SerialPort)this.portId.open("Bar_Scan", 20000));
this.is = this.serialPort.getInputStream();
this.serialPort.addEventListener(this.t);
this.serialPort.notifyOnDataAvailable(true);
this.serialPort.setSerialPortParams(getRATE(), getDATABITS(),
getSTOPBITS(), 0);
this.t.init(this.serialPort, this.is);
}catch(){}
public class ReaderThread extends Thread
implements SerialPortEventListener{
private SerialPort serialPort;
private InputStream is;
public void init(SerialPort serialPort, InputStream is) {
this.serialPort = serialPort;
this.is = is;
}
public void serialEvent(SerialPortEvent event) {
switch (event.getEventType()) {
case SerialPortEvent.DATA_AVAILABLE:
while (true) try {
...;
int b = this.is.read();
...
}
catch (IOException e){
log4J.error(e);
}
}
}
}
Copy RXTXcomm.jar ---> \jre\lib\ext
Copy rxtxSerial.dll ---> \jre\bin
Copy rxtxParallel.dll ---> \jre\bin
//创建串口连接
SerialConnector connector = new SerialConnector();
//绑定处理handler
connector.setHandler(new MyHandler());
//设置过滤器
connector.getFilterChain().addLast("logger",new LoggingFilter());
现在创建一个地址连接到一个串行端口:
//配置串口连接
SerialAddress address = new SerialAddress
("COM1", 9600, DataBits.DATABITS_8,StopBits.BITS_1 , Parity.NONE, FlowControl.NONE);
第一个参数是串行端口标识符,对于Windows系统来说,串行端口被称作“COM1”、“COM2”等,对于Linux和Unix系统来说,则是"/dev/ttyS0"、"/dev/ttyS1"和"/dev/ttyUsb0"等。
ConnectFuture future = connector.connect(address);
future.await();
IoSession session = future.getSession();
session.write("good mina");
SerialPort serialPort = initializePort("Apache MINA", portId, portAddress);
ConnectFuture future = new DefaultConnectFuture();
SerialSessionImpl session = new SerialSessionImpl(this, getListeners(), portAddress, serialPort);
initSession(session, future, sessionInitializer);
session.start();
return future;
class SerialSessionImpl extends AbstractIoSession implements SerialSession, SerialPortEventListener
我们注意他的start方法
void start() throws IOException, TooManyListenersException {
inputStream = port.getInputStream();
outputStream = port.getOutputStream();
ReadWorker w = new ReadWorker();
w.start();
port.addEventListener(this);
((SerialConnector) getService()).getIdleStatusChecker0().addSession(this);
try {
getService().getFilterChainBuilder().buildFilterChain(getFilterChain());
serviceListeners.fireSessionCreated(this);
} catch (Throwable e) {
getFilterChain().fireExceptionCaught(e);
processor.remove(this);
}
}
其中有个ReadWorker线程,他首先等待Object readReadyMonitor的资源,如果readReadyMonitor被notify,那线程就开始读数据
try {
readReadyMonitor.wait();
} catch (InterruptedException e) {
log.error("InterruptedException", e);
}
if (isClosing() || !isConnected()) {
break;
}
int dataSize;
try {
dataSize = inputStream.available();
byte[] data = new byte[dataSize];
int readBytes = inputStream.read(data);
if (readBytes > 0) {
IoBuffer buf = IoBuffer.wrap(data, 0, readBytes);
buf.put(data, 0, readBytes);
buf.flip();
getFilterChain().fireMessageReceived(buf);
}
} catch (IOException e) {
getFilterChain().fireExceptionCaught(e);
}
而readReadyMonitor被notify的事件就发生在串口有数据读入,因SerialSessionImpl实现了SerialPortEventListener,所以他就可以监听事件
public void serialEvent(SerialPortEvent evt) {
if (evt.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
synchronized (readReadyMonitor) {
readReadyMonitor.notifyAll();
}
}
}