最近公司的项目需要和硬件打交道,而我负责硬件对接这块的主要工作,这几天把java中的串口编程熟悉了下,其中大多是涉及到环境的配置,接下来我把自己做的过程中遇到的问题整理一下,供大家产考!
大至的应用场景是这样的,终端设备(简称DTU)通过USB连接到主机上,主机上通过Java 的串口程序把数据发送到DTU,dtu配置好转发服务器的ip和端口号,这样主机的数据就可以直接发送至服务器了,可能有人会问为什么不直接发送至服务器,因为我们的应用场景中主机是不可以联网的。
SimpleWrite.java
package comm32;
import java.io.*;
import java.util.*;
import javax.comm.*;
public class SimpleWrite {
static Enumeration portList;
static CommPortIdentifier portId;
static String messageString = "Hello, world00000000000000000000000000000!\n";
static SerialPort serialPort;
static OutputStream outputStream;
public static void main(String[] args) {
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
System.out.println(portId.getName());
if (portId.getName().equals("COM4")) {
try {
serialPort = (SerialPort)
portId.open("SimpleWriteApp", 2000);
} catch (PortInUseException e) {}
try {
outputStream = serialPort.getOutputStream();
} catch (IOException e) {}
try {
serialPort.setSerialPortParams(115200,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {}
try {
outputStream.write(messageString.getBytes());
System.out.println("ok");
} catch (IOException e) {}
}
}
}
}
}
其中需要注意的是com4,以及setSerialPortParams方法中第一个参数115200指的是波特率,运行程序,Hello, world00000000000000000000000000000!就已经通过端口发送了!
首先下载:RXTX的包,(仅64位有效)Rxtx开源包下载地址:1、把rxtxParallel.dll、rxtxSerial.dll拷贝到:C:\WINDOWS\system32下。
2、如果是在开发的时候(JDK),需要把RXTXcomm.jar、rxtxParallel.dll、rxtxSerial.dll拷贝到..\jre...\lib\ext下;如:D:\Program Files\Java\jre1.6.0_02\lib\ext
3、而且需要把项目1.右键->2.Preperties(首选项)->3.Java Build Path->4.Libraries->5.展开RXTXcomm.jar->6.Native library location:(None)->
7.浏览External Folder(选择至该项目的lib文件夹,如:E:/Item/MyItem/WebRoot/WEB-INF/lib).
package comme64;
import gnu.io.*;
import java.io.*;
import java.util.*;
public class SerialReader extends Observable implements Runnable,SerialPortEventListener
{
static CommPortIdentifier portId;
int delayRead = 100;
int numBytes; //
private static byte[] readBuffer = new byte[1024]; //
static Enumeration portList;
InputStream inputStream;
OutputStream outputStream;
static SerialPort serialPort;
HashMap serialParams;
Thread readThread;
boolean isOpen = false;
public static final String PARAMS_DELAY = "delay read"; //
public static final String PARAMS_TIMEOUT = "timeout"; // 超时时间
public static final String PARAMS_PORT = "port name"; // 端口名称
public static final String PARAMS_DATABITS = "data bits"; //
public static final String PARAMS_STOPBITS = "stop bits"; //
public static final String PARAMS_PARITY = "parity"; // 奇偶校验
public static final String PARAMS_RATE = "rate"; //
public boolean isOpen(){
return isOpen;
}
/**
* 初始化端口操作的参数.
* @throws SerialPortException
*
* @see
*/
public SerialReader()
{
isOpen = false;
}
public void open(HashMap params)
{
serialParams = params;
if(isOpen){
close();
}
try
{
// 参数初始
int timeout = Integer.parseInt( serialParams.get( PARAMS_TIMEOUT )
.toString() );
int rate = Integer.parseInt( serialParams.get( PARAMS_RATE )
.toString() );
int dataBits = Integer.parseInt( serialParams.get( PARAMS_DATABITS )
.toString() );
int stopBits = Integer.parseInt( serialParams.get( PARAMS_STOPBITS )
.toString() );
int parity = Integer.parseInt( serialParams.get( PARAMS_PARITY )
.toString() );
delayRead = Integer.parseInt( serialParams.get( PARAMS_DELAY )
.toString() );
String port = serialParams.get( PARAMS_PORT ).toString();
// 打开端口
portId = CommPortIdentifier.getPortIdentifier( port );
serialPort = ( SerialPort ) portId.open( "SerialReader", timeout );
inputStream = serialPort.getInputStream();
serialPort.addEventListener( this );
serialPort.notifyOnDataAvailable( true );
serialPort.setSerialPortParams( rate, dataBits, stopBits, parity );
isOpen = true;
}
catch ( PortInUseException e )
{
// 端口"+serialParams.get( PARAMS_PORT ).toString()+"已经被占�?;
}
catch ( TooManyListenersException e )
{
//"端口"+serialParams.get( PARAMS_PORT ).toString()+"监听者过�?;
}
catch ( UnsupportedCommOperationException e )
{
//"端口操作命令不支�?;
}
catch ( NoSuchPortException e )
{
//"端口"+serialParams.get( PARAMS_PORT ).toString()+"不存�?;
}
catch ( IOException e )
{
//"打开端口"+serialParams.get( PARAMS_PORT ).toString()+"失败";
}
serialParams.clear();
Thread readThread = new Thread( this );
readThread.start();
}
public void run()
{
try
{
Thread.sleep(50);
}
catch ( InterruptedException e )
{
}
}
public void start(){
try {
outputStream = serialPort.getOutputStream();
}
catch (IOException e) {}
try{
readThread = new Thread(this);
readThread.start();
}
catch (Exception e) { }
} //start() end
public void run(String message) {
try {
Thread.sleep(4);
}
catch (InterruptedException e) { }
try {
if(message!=null&&message.length()!=0)
{
System.out.println("run message:"+message);
outputStream.write(message.getBytes());
}
} catch (IOException e) {}
}
public void close()
{
if (isOpen)
{
try
{
serialPort.notifyOnDataAvailable(false);
serialPort.removeEventListener();
inputStream.close();
serialPort.close();
isOpen = false;
} catch (IOException ex)
{
//"关闭串口失败";
}
}
}
public void serialEvent( SerialPortEvent event )
{
try
{
Thread.sleep( delayRead );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
switch ( event.getEventType() )
{
case SerialPortEvent.BI: // 10
case SerialPortEvent.OE: // 7
case SerialPortEvent.FE: // 9
case SerialPortEvent.PE: // 8
case SerialPortEvent.CD: // 6
case SerialPortEvent.CTS: // 3
case SerialPortEvent.DSR: // 4
case SerialPortEvent.RI: // 5
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2
break;
case SerialPortEvent.DATA_AVAILABLE: // 1
try
{
// 多次读取,将所有数据读�?
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);
}
//打印接收到的字节数据的ASCII�?
for(int i=0;i // System.out.println("msg[" + numBytes + "]: [" +readBuffer[i] + "]:"+(char)readBuffer[i]);
}
// numBytes = inputStream.read( readBuffer );
changeMessage( readBuffer, numBytes );
}
catch ( IOException e )
{
e.printStackTrace();
}
break;
}
}
// 通过observer pattern将收到的数据发�?给observer
// 将buffer中的空字节删除后再发送更新消�?通知观察�?
public void changeMessage( byte[] message, int length )
{
setChanged();
byte[] temp = new byte[length];
System.arraycopy( message, 0, temp, 0, length );
notifyObservers( temp );
}
static void listPorts()
{
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
while ( portEnum.hasMoreElements() )
{
CommPortIdentifier portIdentifier = ( CommPortIdentifier ) portEnum
.nextElement();
}
}
public void openSerialPort(String message)
{
HashMap params = new HashMap();
String port="COM1";
String rate = "9600";
String dataBit = ""+SerialPort.DATABITS_8;
String stopBit = ""+SerialPort.STOPBITS_1;
String parity = ""+SerialPort.PARITY_NONE;
int parityInt = SerialPort.PARITY_NONE;
params.put( SerialReader.PARAMS_PORT, port ); // 端口名称
params.put( SerialReader.PARAMS_RATE, rate ); // 波特�?
params.put( SerialReader.PARAMS_DATABITS,dataBit ); // 数据�?
params.put( SerialReader.PARAMS_STOPBITS, stopBit ); // 停止�?
params.put( SerialReader.PARAMS_PARITY, parityInt ); // 无奇偶校�?
params.put( SerialReader.PARAMS_TIMEOUT, 100 ); // 设备超时时间 1�?
params.put( SerialReader.PARAMS_DELAY, 100 ); // 端口数据准备时间 1�?
try {
open(params);//打开串口
//LoginFrame cf=new LoginFrame();
//addObserver(cf);
//也可以像上面�?��通过LoginFrame来绑定串口的通讯输出.
if(message!=null&&message.length()!=0)
{
String str="";
for(int i=0;i<10;i++)
{
str+=message;
}
start();
run(str);
}
} catch (Exception e) {
}
}
static String getPortTypeName( int portType )
{
switch ( portType )
{
case CommPortIdentifier.PORT_I2C:
return "I2C";
case CommPortIdentifier.PORT_PARALLEL:
return "Parallel";
case CommPortIdentifier.PORT_RAW:
return "Raw";
case CommPortIdentifier.PORT_RS485:
return "RS485";
case CommPortIdentifier.PORT_SERIAL:
return "Serial";
default:
return "unknown type";
}
}
public HashSet getAvailableSerialPorts()//本来static
{
HashSet h = new HashSet();
Enumeration thePorts = CommPortIdentifier.getPortIdentifiers();
while ( thePorts.hasMoreElements() )
{
CommPortIdentifier com = ( CommPortIdentifier ) thePorts
.nextElement();
switch ( com.getPortType() )
{
case CommPortIdentifier.PORT_SERIAL:
try
{
CommPort thePort = com.open( "CommUtil", 50 );
thePort.close();
h.add( com );
}
catch ( PortInUseException e )
{
System.out.println( "Port, " + com.getName()
+ ", is in use." );
}
catch ( Exception e )
{
System.out.println( "Failed to open port "
+ com.getName() + e );
}
}
}
return h;
}
}
package comme64; /*
*数据位 8
* 校验位 0
* 停止位 1
* 波特率 115200
* 端口com3
*/
import gnu.io.SerialPort;
import java.util.*;
public class Test implements Observer{
public static void main(String []args)
{
Test test = new Test();
test.send("串口数据发送至DTU转发至服务器!");
while(true)
{
test.send("串口数据发送至DTU转发至服务器!");
}
}
SerialReader sr=new SerialReader();
// public Test()
// {
// openSerialPort("COM3"); //打开串口。
// }
public void update(Observable o, Object arg){
String mt=new String((byte[])arg);
System.out.println("---"+mt); //串口数据
}
/**
* 往串口发送数据,实现双向通讯.
* @param string message
*/
public void send(String message)
{
Test test = new Test();
test.openSerialPort(message);
}
/**
* 打开串口
* @param String message
*/
public void openSerialPort(String message)
{
HashMap params = new HashMap();
String port="COM3";
String rate = "115200";
String dataBit = ""+SerialPort.DATABITS_8;
String stopBit = ""+SerialPort.STOPBITS_1;
String parity = ""+SerialPort.PARITY_NONE;
int parityInt = SerialPort.PARITY_NONE;
params.put( SerialReader.PARAMS_PORT, port ); // 端口名称
params.put( SerialReader.PARAMS_RATE, rate ); // 波特率
params.put( SerialReader.PARAMS_DATABITS,dataBit ); // 数据位
params.put( SerialReader.PARAMS_STOPBITS, stopBit ); // 停止位
params.put( SerialReader.PARAMS_PARITY, parityInt ); // 无奇偶校验
params.put( SerialReader.PARAMS_TIMEOUT,100 ); // 设备超时时间 1秒
params.put( SerialReader.PARAMS_DELAY, 100 ); // 端口数据准备时间 1秒
try {
sr.open(params);
sr.addObserver(this);
if(message!=null&&message.length()!=0)
{
sr.start();
sr.run(message);
}
} catch (Exception e) {
}
}
public String Bytes2HexString(byte[] b) {
String ret = "";
for (int i = 0; i < b.length; i++) {
String hex = Integer.toHexString(b[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
ret += hex.toUpperCase();
}
return ret;
}
public String hexString2binaryString(String hexString) {
if (hexString == null || hexString.length() % 2 != 0)
return null;
String bString = "", tmp;
for (int i = 0; i < hexString.length(); i++) {
tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexString.substring(i, i + 1), 16));
bString += tmp.substring(tmp.length() - 4);
}
return bString;
}
}
通过Test.java的测试,可以成功把数据发送出去,这里还是要注意端口的以及波特率的正确。