很久以前写的一个java串口通讯程序,用的是comm.jar。用java搞串口通讯就是用菜刀削水果-虽然也能做到,但是很麻烦。

贴下核心类:

package com.jzdf.odu.serial;



import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.ArrayList;

import java.util.TooManyListenersException;



import javax.comm.CommPortIdentifier;

import javax.comm.NoSuchPortException;

import javax.comm.PortInUseException;

import javax.comm.SerialPort;

import javax.comm.SerialPortEvent;

import javax.comm.SerialPortEventListener;

import javax.comm.UnsupportedCommOperationException;



import org.eclipse.swt.widgets.Display;



import com.jzdf.odu.constant.Constants;

import com.jzdf.odu.dto.Packet;

import com.jzdf.odu.util.AsciiToHex;

import com.jzdf.odu.view.MainShell;



/**

* 串口工具类,负责串口的打开,发送数据,接收数据,关闭等

*

* @author liu

*/

public class SerialOperate implements SerialPortEventListener {

public SerialPort serialPort;

private CommPortIdentifier portId;

private InputStream inputStream;

private OutputStream outputStream;

private static final SerialOperate serialOperate = new SerialOperate();



// private MainShell shell = MainShell.getMainShell();



/**

* 构造器:打开串口,并获得输入输出流, 与主界面类(MainView)构造依赖

*

* @param MainShell

* The main view of the program.

* @param portName

* The serial port name of the local computer. such as

* "COM1","COM2" etc.

* @throws PortInUseException

* @throws NoSuchPortException

*/

private SerialOperate() {

}



/**

* 单列模式

*

* @return the only instance of the class.

*/

public static SerialOperate getInstance() {

return serialOperate;

}



/**

* 打开串口和输入输出流

*

* @throws IOException

*

*/

public boolean openPort(String portName) throws NoSuchPortException,

PortInUseException, IOException {

portId = CommPortIdentifier.getPortIdentifier(portName);

serialPort = (SerialPort) portId.open("ODU", 50);

try {

inputStream = new BufferedInputStream(serialPort.getInputStream());

outputStream = new BufferedOutputStream(serialPort

.getOutputStream());

return true;

} catch (IOException e) {

inputStream.close();

return false;

}

}



/**

* 设置串口读写参数(分别为波特率:115200, 数据位:8,停止位:1,校验码:无)

*

*/

public boolean setParameter() {

try {

// serialPort.setSerialPortParams(Integer.valueOf(shell.comboBaud.getText()),Integer.valueOf(shell.comboDataBit.getText()),

// Integer.valueOf(shell.comboStopBit.getText()),

// Integer.valueOf(shell.comboCheck.getText()));

serialPort.setSerialPortParams(115200, SerialPort.DATABITS_8,

SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);

return true;

} catch (UnsupportedCommOperationException e) {

return false;

}

}



// public byte read() {

// int newData = 0;

// byte data = 0;

// try {

// if ((newData = inputStream.read()) != -1) {

// data = (byte) newData;

// }

// } catch (IOException e) {

// }

// return data;

// }



/**

* 以包为单位返回数据

*/

static int flag = 0;

public int no = 0;// 包的编号

public Packet readPacket() throws IOException {//TODO

final Packet pack = new Packet();

final ArrayList<String> content = new ArrayList<String>();

int newData;

while ((newData = inputStream.read()) != -1) {

byte data = (byte) newData;

if (data != 0x7E && flag != 0) {

content.add(String.valueOf(data));// 包的数据

flag++;

continue;

} else if (data == 0x7E && flag > 1) {// 包尾

content.add("126");

flag = 0;

pack.setId(no++);

System.out.println("No:" + no);

pack.setType(AsciiToHex.decToHex(content.get(1)));

Display.getDefault().syncExec(new Runnable() {

public void run() {

// 如果包类型为要过滤的类型,则清空包,重新计数

if (MainShell.getMainShell().getFilterList().contains(

pack.getType())) {

content.clear();

flag = 0;

no--;

} else {

String[] temp1 = new String[content.size()];

String[] temp2 = AsciiToHex.decToHex(content

.toArray(temp1));

content.clear();

for (String str : temp2) {

content.add(str);

}

pack.setData(content);

pack.setLength(content.size());

/* 显示接收到的数据包数及所用时间 */

if (MainShell.getMainShell().startTime != 0) {

MainShell.getMainShell().lblInfo

.setText("正在接收数据,已收到"

+ no

+ "个数据包!用时:"

+ (System.currentTimeMillis() - MainShell

.getMainShell().startTime)

+ "ms.");

} else {

MainShell.getMainShell().lblInfo

.setText("正在接收数据,已收到" + no + "个数据包!");

}

/* Write a packet to the txt file. */

FileOutputStream fos;

try {

fos = new FileOutputStream(new File(

Constants.dataFile + ".txt"), true);

fos.write(String.valueOf(no).getBytes());

fos.write(32);

fos.write(content.get(1).getBytes());

fos.write(32);

fos.write(content.toString().trim().getBytes());

fos.write(32);

fos.write(String.valueOf(content.size())

.getBytes());

String newLine = "\r\n";

fos.write(newLine.getBytes());

fos.close();// Must!!!

} catch (Exception e) {

}

content.clear();// Must!!!

/* End write */

flag = 0;

}

}

});

continue;

} else if (data == 0x7E && flag == 0) {// 包头

content.add("126");

flag++;

continue;

} else if (data == 0x7E && flag == 1) {// 7E 7E

content.clear();

content.add("126");

flag = 1;

continue;

}

}

return pack;

}



/**

* 以十进制整型发送数据

*

* @param dataToSend

*/

public void send(String dataToSend) {

try {

outputStream.write(Integer.parseInt(dataToSend, 16));

outputStream.flush();

} catch (IOException e) {

}

}



/**

* 发送"发送区"中的数据

*/

public void sendAll() {

ArrayList<String> data = (ArrayList<String>) MainShell.getMainShell()

.getSendPacket();

for (String byteHex : data) {

send(byteHex);

}

}



/**

* 关闭串口

*/

public void closePort() {

if (serialPort != null) {

serialPort.close();

}

}



/**

* 串口监听器,监听是否有数据及传输是否正常

*/

public void listening() {

try {

serialPort.addEventListener(this);

} catch (TooManyListenersException e) {

}

serialPort.notifyOnDataAvailable(true);

}



@Override

public void serialEvent(SerialPortEvent event) {

switch (event.getEventType()) {

case SerialPortEvent.BI:/* Break interrupt,通讯中断 */

case SerialPortEvent.OE:/* Overrun error,溢位错误 */

case SerialPortEvent.FE:/* Framing error,传帧错误 */

case SerialPortEvent.PE:/* Parity error,校验错误 */

case SerialPortEvent.CD:/* Carrier detect,载波检测 */

case SerialPortEvent.CTS:/* Clear to send,清除发送 */

case SerialPortEvent.DSR:/* Data set ready,数据设备就绪 */

case SerialPortEvent.RI:/* Ring indicator,响铃指示 */

case SerialPortEvent.OUTPUT_BUFFER_EMPTY:/* 输出缓冲区已清空 */

break;

case SerialPortEvent.DATA_AVAILABLE:/* 端口有数据时 */

try {

readPacket();// 按包读取数据,包按7E开头,7E结尾

} catch (IOException e1) {

}

break;

}

}

}