读书人

java 串口通讯 简单封装

发布时间: 2012-10-27 10:42:26 作者: rapoo

java 串口通信 简单封装

-------------------------------接口-------------------------------

package anole.server.common;

import java.util.List;

public interface CommService {

??? /**
???? * 设置端口名称
???? * @param portName 需要操作的端口名称
???? */
??? public void setPortName(String portName);

??? /**
???? * 设置读取超时时长
???? * @param timeOut 读取超时时长
???? */
??? public void setTimeOut(long timeOut);

??? /**
???? * 设置传输速率
???? * @param rate 传输速率
???? */
??? public void setRate(int rate);

??? /**
???? * 设置数据位
???? * @param dataBit 数据位
???? */
??? public void setDataBit(int dataBit);

??? /**
???? * 设置停止位
???? * @param stopBit 停止位
???? */
??? public void setStopBit(int stopBit);

??? /**
???? * 设置奇偶校验
???? * @param parity 奇偶校验
???? */
??? public void setParity(int parity);

??? /**
???? * 获取本机串口列表
???? * @return 本机串口名列表
???? */
??? public List<String> listPortName();

??? /**
???? * 发送命令到通信端口
???? * @param comCode 发送的字符 此字符为16进制字符串,从00到FF
???? * @param splitFlag 分割符
???? * @return?? 0 发送成功 1 命令非十六进制 2 IO操作异常
???? */
??? public int send(String comCode, String splitFlag);

??? /**
???? * 发送命令到通信端口
???? * @param comCode 发送的字符 此字符为16进制字符串,从00到FF
???? * @return? 0 发送成功 1 命令非十六进制 2 IO操作异常
???? */
??? public int send(String comCode);

??? /**
???? * 发送命令到通信端口
???? * @param comCode 发送的数组的数值为0到255
???? * @return?? 0 发送成功 1 命令非十六进制 2 IO操作异常
???? */
??? public int send(char[] comCode);

??? /**
???? * 发送命令到通信端口
???? * @param b 发送的数据
???? * @return? 0 发送成功? 2 IO操作异常
???? */
??? public int send(byte[] b);

??? /**
???? * 读取通信端口数据
???? * @param endFlag 当有结果返回是 数据结束符
???? * @param timeout 等待数据超时时间 以毫秒计算
???? * @return 通信端口返回数据
???? */
??? public byte[] recevie(String endFlag, long timeout);

??? /**
???? * 读取通信端口数据
???? * @param dataLength 当有数据返回,返回数据长度
???? * @param timeout 等待数据超时时间 以毫秒计算
???? * @return 通信端口返回数据
???? */
??? public byte[] recevie(int dataLength, long timeout);

??? /**
???? * 读取通信端口数据
???? * @return 通信端口返回数据
???? */
??? public byte[] recevie();

??? /**
???? * 关闭端口
???? * @return 0:正常开启? 1:开启失败;2;端口设置错误;3;未找到端口;4;端口被占用 5 IO开启异常
???? */
??? public int open();

??? /**
???? * 关闭端口
???? * @return 0:正常关闭? 1:关闭失败
???? */
??? public int close();
}
------------------------自定义异常-------------------------------

package anole.server.common.util;

public class NoByteException extends Throwable {
??? private static final long serialVersionUID = 1L;

??? NoByteException(String string) {
??????? super();
??? }

}

---------------------------数据转换-------------------------------------------

?

package anole.server.common.util;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;

public class CodeConvert {

??? /**
???? * 十六进制字符与数字转换表。
???? */
??? public static final String HEX_STRING = "0123456789abcdef";

??? /**
???? * 将十六进制字符转换成数字。
???? * @param c 将转换的字符。
???? * @return 转换成的数字。
???? * @throws NotByteException
???? */
??? private static int StringHexToInt(char c) throws NoByteException {
??????? char cc = Character.toLowerCase(c);
??????? int value = HEX_STRING.indexOf(cc);
??????? if (value == -1) {
??????????? throw new NoByteException("必须是十六进制字符");
??????? }
??????? return value;
??? }

??? /**
???? * 将字节数组转换成十六进制的字符表现形式。
???? * @param b 字节数组。
???? * @return 十六进制字符表现形式。
???? */
??? public static String ByteToString(byte[] b) {
??????? StringBuilder sb = new StringBuilder();
??????? for (int i = 0; i < b.length; i++) {
??????????? StringBuilder append = sb.append(HEX_STRING.charAt((b[i] >> 4) & 0xf)).append(HEX_STRING.charAt((b[i]) & 0xf));
??????? }
??????? return sb.toString().toUpperCase();
??? }

??? /**
???? * 将字节数组转换成十六进制的字符表现形式。
???? * @param b 字节数组。
???? * @param splitString 字符串分割符
???? * @return 十六进制字符表现形式。
???? */
??? public static String ByteToString(byte[] b, String splitString) {
??????? StringBuilder sb = new StringBuilder();
??????? int bLen = b.length;
??????? sb.append(HEX_STRING.charAt((b[0] >> 4) & 0xf)).append(HEX_STRING.charAt((b[0]) & 0xf));
??????? for (int i = 1; i < b.length; i++) {
??????????? sb.append(splitString);
??????????? sb.append(HEX_STRING.charAt((b[i] >> 4) & 0xf)).append(HEX_STRING.charAt((b[i]) & 0xf));
??????? }
??????? return sb.toString().toUpperCase();
??? }

??? /**
???? * 将十六进制字符串转换成字节数组。
???? * @param str 需要转换的字符串。
???? * @return 字节数组。
???? * @throws NoByteException 不是byte类型字符串
???? */
??? public static byte[] StringToByte(String str) throws NoByteException {
??????? char[] c = str.toCharArray();
??????? byte[] b = new byte[c.length / 2];
??????? int m = 0;
??????? for (int i = 0; i < c.length; i += 2) {
??????????? int j = StringHexToInt(c[i]) << 4;
??????????? int k = StringHexToInt(c[i + 1]);
??????????? b[m] = (byte) (j | k);
??????????? m++;
??????? }
??????? return b;
??? }

??? public static byte[] CharsToBytes(char[] chars) {
??????? Charset cs = Charset.forName("UTF-8");
??????? CharBuffer cb = CharBuffer.allocate(chars.length);
??????? cb.put(chars);
??????? cb.flip();
??????? ByteBuffer bb = cs.encode(cb);
??????? return bb.array();
??? }

??? public static char[] BytesToChars(byte[] bytes) {
??????? Charset cs = Charset.forName("UTF-8");
??????? ByteBuffer bb = ByteBuffer.allocate(bytes.length);
??????? bb.put(bytes);
??????? bb.flip();
??????? CharBuffer cb = cs.decode(bb);
??????? return cb.array();
??? }

??? /**
???? * 将十六进制字符串转换成字节数组。
???? * @param str 需要转换的字符串。
???? * @param splitString 字符串分割符
???? * @return 字节数组。
???? * @throws NoByteException 不是byte类型字符串
???? */
??? public static byte[] StringToByte(String str, String splitString) throws NoByteException {
??????? return StringToByte(str.replace(splitString, ""));
??? }
}
--------------------------------串口监听器----------------------------------------------------

/*
?* To change this template, choose Tools | Templates
?* and open the template in the editor.
?*/
package anole.server.common.serialService;

import anole.server.common.util.CodeConvert;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.TooManyListenersException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
?*
?* @author Administrator
?*/
public class SerialHandler implements SerialPortEventListener {

??? private SerialPort serialPort;
??? private long timeOut = 4000;
??? private String portName;
??? private OutputStream os;
??? private InputStream is;
??? private int rate = 9600;
??? private int dataBit = SerialPort.DATABITS_8;
??? private int stopBit = SerialPort.STOPBITS_1;
??? private int parity = SerialPort.PARITY_NONE;
??? private boolean isComplate = true;
??? private byte[] readBuffer;
??? private int bufferSize = 10240;

??? public synchronized void setReadBuffer(byte[] readBuffer) {
??????? isComplate = false;
??????? while (isComplate) {
??????????? try {
??????????????? this.wait();
??????????? } catch (InterruptedException e) {
??????????????? e.printStackTrace();
??????????? }
??????? }
??????? byte[] temp = readBuffer;
??????? if (this.readBuffer != null) {
??????????? if (temp != null) {
??????????????? int rLen = this.readBuffer.length;
??????????????? int tLen = temp.length;
??????????????? byte[] in = new byte[rLen + tLen];
??????????????? System.arraycopy(this.readBuffer, 0, in, 0, rLen);
??????????????? System.arraycopy(temp, 0, in, rLen, tLen);
??????????? }
??????? } else {
??????????? this.readBuffer = temp;
??????? }
??????? isComplate = true;
??????? this.notifyAll();
??? }

??? public synchronized byte[] getReadBuffer() {
??????? while (!isComplate) {
??????????? try {
??????????????? this.wait();
??????????? } catch (InterruptedException e) {
??????????????? e.printStackTrace();
??????????? }
??????? }
??????? byte[] temp = this.readBuffer;
??????? this.readBuffer = null;
??????? this.notifyAll();
??????? return temp;
??? }

??? public void setTimeOut(long timeOut) {
??????? this.timeOut = timeOut;
??? }

??? public void setBufferSize(int bufferSize) {
??????? this.bufferSize = bufferSize;
??? }

??? public int send(byte[] bs) {
??????? int flag = 0;
??????? try {
??????????? os.write(bs);
??????????? os.flush();
??????? } catch (IOException e) {
??????????? flag = 2;
??????? }
??????? return flag;
??? }

??? public byte[] recevie(int dataLength, long timeOut) {
??????? this.timeOut = timeOut;
??????? byte[] bs = null;
??????? byte[] temp = null;
??????? int cLen = 0;
??????? int tLen = 0;
??????? int lLen = 0;
??????? long curr = new Date().getTime();
??????? while ((bs == null || bs.length < dataLength) && new Date().getTime() - curr < this.timeOut) {
??????????? try {
??????????????? //获取缓冲区数据
??????????????? temp = null;//临时数据清空
??????????????? temp = getReadBuffer();
??????????????? tLen = 0;
??????????????? if (temp != null) {
??????????????????? System.out.println("临时数据:" + CodeConvert.ByteToString(temp));
??????????????????? tLen = temp.length;
??????????????? }
??????????????? //计算要返回数据长度
??????????????? if (bs != null) {
??????????????????? cLen = bs.length;
??????????????? }
??????????????? System.out.println("当前数据长度:" + cLen);
??????????????? //若 当前要返回数据长度 加上 临时数据长度 大于 要求的数据长度
??????????????? if ((cLen + tLen) > dataLength) {
??????????????????? System.out.println("长度超出" + (cLen + tLen));
??????????????????? //计算需要拷贝的数据长度
??????????????????? lLen = dataLength - cLen;
??????????????????? byte[] in = new byte[cLen + lLen];
??????????????????? System.arraycopy(bs, 0, in, 0, cLen);
??????????????????? System.arraycopy(temp, 0, in, cLen, lLen);
??????????????????? bs = in;
??????????????????? break;
??????????????? } //将临时数据追加到要返回的数据之后
??????????????? else if (temp != null && bs != null) {
??????????????????? //将临时数组添加到当前数组之后
??????????????????? System.out.println("附加数据");
??????????????????? byte[] in = new byte[cLen + tLen];
??????????????????? System.arraycopy(bs, 0, in, 0, cLen);
??????????????????? System.arraycopy(temp, 0, in, cLen, tLen);
??????????????????? bs = in;
??????????????? } else if (temp != null && bs == null) {
??????????????????? System.out.println("初始化数组");
??????????????????? bs = temp;
??????????????? }
??????????????? //若 数据长度不够 则 线程睡眠1000ms
??????????????? if (bs != null) {
??????????????????? cLen = bs.length;
??????????????? }
??????????????? if (cLen < dataLength) {
??????????????????? System.out.println("线程睡眠1000ms");
??????????????????? Thread.sleep(1000);
??????????????? }

??????????? } catch (InterruptedException ex) {
??????????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, ex);
??????????? }
??????? }
??????? int aLen = bs.length;
??????? bs = Arrays.copyOf(bs, aLen);
??????? System.out.println("当前返回数据:" + CodeConvert.ByteToString(bs));
??????? return bs;
??? }

??? public byte[] recevie(byte endFlag, long timeOut) {
??????? this.timeOut = timeOut;
??????? byte[] bs = null;
??????? byte[] temp = null;
??????? int cLen = 0;
??????? int tLen = 0;
??????? int lLen = 0;
??????? int iIndex = -1;
??????? long curr = new Date().getTime();
??????? while (iIndex < 0 && new Date().getTime() - curr < this.timeOut) {
??????????? try {
??????????????? //获取缓冲区数据
??????????????? temp = null;
??????????????? tLen = 0;
??????????????? temp = getReadBuffer();
??????????????? if (temp != null) {
??????????????????? System.out.println("临时数据:" + CodeConvert.ByteToString(temp));
??????????????????? tLen = temp.length;
??????????????? }

??????????????? //计算要返回数据长度
??????????????? if (bs != null) {
??????????????????? cLen = bs.length;
??????????????? }

??????????????? System.out.println("临时数据长度:" + tLen);

??????????????? for (int i = 0; i < tLen; i++) {
??????????????????? if (temp[i] == endFlag) {
??????????????????????? iIndex = i + 1;
??????????????????? }
??????????????? }
??????????????? System.out.println("位置:" + iIndex);

??????????????? lLen = tLen + cLen;

??????????????? //若 临时数据中未发现结束符
??????????????? if (iIndex < 0) {
??????????????????? //扩容 追加到要返回的数据之后
??????????????????? byte[] in = new byte[lLen];
??????????????????? if (temp != null && bs != null) {
??????????????????????? System.arraycopy(bs, 0, in, 0, cLen);
??????????????????????? System.arraycopy(temp, 0, in, cLen, tLen);
??????????????????????? bs = in;

??????????????????? } else if (temp != null && bs == null) {
??????????????????????? bs = temp;
??????????????????? }
??????????????????? Thread.sleep(1000);
??????????????? } else {
??????????????????? if (temp != null && bs != null) {//非第一个包中就包含了结束符号
??????????????????????? //扩容 追加到要返回的数据之后
??????????????????????? byte[] in = new byte[lLen];
??????????????????????? System.arraycopy(bs, 0, in, 0, cLen);
??????????????????????? System.arraycopy(temp, 0, in, cLen, iIndex);
??????????????????????? bs = in;
??????????????????????? break;
??????????????????? } else if (temp != null && bs == null) {//第一个包中就包含了结束符号
??????????????????????? bs = Arrays.copyOf(temp, iIndex);
??????????????????????? break;
??????????????????? }
??????????????? }
??????????? } catch (InterruptedException ex) {
??????????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, ex);
??????????? }
??????? }
??????? int aLen = new String(bs).trim().length();
??????? bs = Arrays.copyOf(bs, aLen);
??????? System.out.println("返回的数据:" + CodeConvert.ByteToString(bs));
??????? return bs;
??? }

??? public byte[] recevie() {
??????? return readBuffer;
??? }

??? ;

??? @Override
??? public void serialEvent(SerialPortEvent event) {
??????? switch (event.getEventType()) {
??????????? case SerialPortEvent.BI:
??????????? case SerialPortEvent.OE:
??????????? case SerialPortEvent.FE:
??????????? case SerialPortEvent.PE:
??????????? case SerialPortEvent.CD:
??????????? case SerialPortEvent.CTS:
??????????? case SerialPortEvent.DSR:
??????????? case SerialPortEvent.RI:
??????????? case SerialPortEvent.OUTPUT_BUFFER_EMPTY:
??????????????? break;
??????????? case SerialPortEvent.DATA_AVAILABLE:
??????????????? try {
??????????????????? int numBytes = 0;
??????????????????? byte[] bs = new byte[bufferSize];
??????????????????? while (is.available() > 0) {
??????????????????????? //将数据读入readBuffer中。?
??????????????????????? numBytes = is.read(bs);
??????????????????? }

??????????????????? setReadBuffer(Arrays.copyOf(bs, numBytes));
??????????????? } catch (IOException e) {
??????????????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, e);
??????????????? }
??????????????? break;
??????? }
??? }

??? public int open() {
??????? int flag = 0;
??????? CommPortIdentifier portId = null;
??????? try {
??????????? portId = CommPortIdentifier.getPortIdentifier(portName);
??????? } catch (NoSuchPortException e) {
??????????? flag = 3;//未找到端口
??????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, e);
??????? }
??????? try {
??????????? serialPort = (SerialPort) portId.open(SerialServiceImpl.class.getSimpleName(), 2000);
??????? } catch (PortInUseException e) {
??????????? flag = 4;//端口被占用
??????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, e);
??????? }
??????? try {
??????????? serialPort.setSerialPortParams(rate, dataBit, stopBit, parity);
??????????? System.out.println("开启端口:portName-" + portName + ":::rate-" + rate + ":::dataBit-" + dataBit + ":::stopBit-" + stopBit + ":::parity-" + parity);
??????????? //serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE);
??????? } catch (UnsupportedCommOperationException e) {
??????????? flag = 2;//端口设置错误
??????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, e);
??????? }
??????? try {
??????????? is = serialPort.getInputStream();
??????????? os = serialPort.getOutputStream();
??????? } catch (IOException e) {
??????????? flag = 5;//IO开启异常
??????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, e);
??????? }
??????? try {
??????????? serialPort.addEventListener(this); // 给当前串口天加一个监听器
??????? } catch (TooManyListenersException e) {
??????????? flag = 6;//监听器添加异常
??????????? Logger.getLogger(SerialHandler.class.getName()).log(Level.SEVERE, null, e);
??????? }
??????? serialPort.notifyOnDataAvailable(true); // 当有数据时通知?
??????? return flag;
??? }

??? public int close() {
??????? int flag = 0;
??????? try {
??????????? if (is != null) {
??????????????? is.close();
??????????? }
??????????? if (os != null) {
??????????????? os.close();
??????????? }
??????????? serialPort.close();
??????? } catch (IOException e) {
??????????? flag = 1;
??????? }
??????? return flag;
??? }

??? public List<String> getListPortName() {
??????? List<String> listPortName = new ArrayList<String>();
??????? CommPortIdentifier portId;
??????? @SuppressWarnings("unchecked")
??????? Enumeration<CommPortIdentifier> en = CommPortIdentifier.getPortIdentifiers();
??????? while (en.hasMoreElements()) {
??????????? portId = en.nextElement();
??????????? if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
??????????????? listPortName.add(portId.getName());
??????????? }
??????? }
??????? return listPortName;
??? }

??? public void setRate(int rate) {
??????? this.rate = rate;
??? }

??? public void setDataBit(int dataBit) {
??????? this.dataBit = dataBit;
??? }

??? public void setStopBit(int stopBit) {
??????? this.stopBit = stopBit;
??? }

??? public void setParity(int parity) {
??????? this.parity = parity;
??? }

??? public void setPortName(String portName) {
??????? this.portName = portName;
??? }
}
----------------------------接口的实现------------------------------------------------

package anole.server.common.serialService;

import anole.server.common.CommService;
import anole.server.common.util.CodeConvert;
import anole.server.common.util.NoByteException;
import java.util.List;

public class SerialServiceImpl implements CommService {

??? private SerialHandler serialHandler = new SerialHandler();
???
??? public SerialServiceImpl() {

??? }
??? public void setTimeOut(long timeOut){
??????? serialHandler.setTimeOut(timeOut);
??? }
??? public SerialServiceImpl(String portName) {
??????? serialHandler.setPortName(portName);
??? }

??? public SerialServiceImpl(String portName, int rate) {
??????? serialHandler.setRate(rate);
??????? serialHandler.setPortName(portName);
??? }

??? @Override
??? public void setPortName(String portName) {
??????? serialHandler.setPortName(portName);
??? }

??? @Override
??? public void setRate(int rate) {
??????? serialHandler.setRate(rate);
??? }

??? @Override
??? public void setDataBit(int dataBit) {

??????? serialHandler.setDataBit(dataBit);
??? }

??? @Override
??? public void setStopBit(int stopBit) {

??????? serialHandler.setStopBit(stopBit);
??? }

??? @Override
??? public void setParity(int parity) {

??????? serialHandler.setParity(parity);
??? }

??? @Override
??? public List<String> listPortName() {

??????? return serialHandler.getListPortName();
??? }

??? @Override
??? public int send(String comCode, String splitFlag) {
??????? int flag = 0;
??????? byte[] bs = null;
??????? try {
??????????? bs = CodeConvert.StringToByte(comCode, splitFlag);
??????? } catch (NoByteException ne) {
??????????? flag = 1;
??????? }
??????? flag = send(bs);
??????? return flag;
??? }

??? @Override
??? public int send(String comCode) {
??????? int flag = 0;
??????? byte[] bs = null;
??????? try {
??????????? bs = CodeConvert.StringToByte(comCode);
??????? } catch (NoByteException ne) {
??????????? flag = 1;
??????? }
??????? flag = send(bs);
??????? return flag;
??? }

??? @Override
??? public int send(char[] comCode) {
??????? int flag = 0;
??????? byte[] bs = null;
??????? bs = CodeConvert.CharsToBytes(comCode);
??????? flag = send(bs);
??????? return flag;
??? }

??? @Override
??? public int send(byte[] b) {
??????? int flag = 0;
??????? serialHandler.send(b);
??????? return flag;
??? }

??? @Override
??? public byte[] recevie(String endFlag, long timeout) {
??????? byte[] bs = null;
??????? byte ef=0;
??????? try {
??????????? ef = CodeConvert.StringToByte(endFlag)[0];
??????? } catch (NoByteException ne) {
??????????? int flag = 1;
??????? }

??????? serialHandler.recevie(ef, timeout);
??????? return bs;
??? }

??? @Override
??? public byte[] recevie(int dataLength, long timeout) {
??????? byte[] bs = null;
??????? serialHandler.recevie(dataLength, timeout);
??????? return bs;
??? }

??? @Override
??? public byte[] recevie() {
??????? byte[] bs = null;
??????? bs = serialHandler.recevie();
??????? return bs;
??? }

??? @Override
??? public int open() {
??????? int flag = 0;
??????? flag = serialHandler.open();
??????? return flag;
??? }

??? @Override
??? public int close() {
??????? int flag = 0;
??????? serialHandler.close();
??????? return flag;
??? }
}

------测试类-----------


package mm;
import anole.server.common.CommService;
import anole.server.common.serialService.SerialServiceImpl;
import java.util.Iterator;
import java.util.List;

public class Mm {

??? public static void main(String[] args) {
?????? CommService cs=new SerialServiceImpl();
?????? List<String> ll=cs.listPortName();
?????? Iterator<String> iter=ll.iterator();
?????? while(iter.hasNext()){
?????????? System.out.println(iter.next());
?????? }
?????? cs.setPortName("COM3");
?????? cs.open();
?????? cs.send("AD010D");
?????? cs.recevie(35, 12000);
?????? cs.close();
??? }
}

读书人网 >编程

热点推荐