java基于RXTXcomm的串口程序

准备工作

  • 首先下载官方提供的jar包和.dll文件,dll文件有两个,一个是rxtxSerial,一个是rxtxParallel,分别表示串口和并口。
  • 因为我开发串口,所以把rxtxSerial.dll放到了jdk1.8.0_171/jre/bin和jre1.8.0_171/bin目录下,官方说两个都放,我没有去验证只放其中一个有没有差别。直接按照官方的直接放了。
  • 接下来将jar包放入工程目录下的lib文件夹,并引用。

PS:在程序开发之前,强烈建议用测试工具测试设备是否已经可用。

程序包括的部分

  • 初始化对象以及设置监听的init函数
  • 监听消息的函数 serialEvent()(该函数来自实现的接口SerialPortEventListener)
  • 消息发送函数 send()
  • 消息接收的函数 receive()
  • 关闭函数 close()
  • 因为消息是16进制字符串,所以还有16进制字符串转byte数组以及byte数组转字符串函数
    (这两个函数随便网上copy的,不是我自己写的,只修改了一句)

程序参数

  • PORT_NAME = “COM3”,这个参数的参数值看的是设备连接上后的设备管理器端口部分查看端口
  • BIT_RATE = 9600;
    DATA_BITS = SerialPort.DATABITS_8;
    STOP_BIT = SerialPort.STOPBITS_1;
    PARITY_BIT = SerialPort.PARITY_NONE;
    这四个参数分别表示设备的比特率,数据位,停止位,和校验位,在设备使用说明上提供了。
  • serialPort,这个参数用来设置串口的参数
  • InputStream in;OutputStream out;这两个参数分别用来读写数据

代码部分

初始化部分基本参照官网代码,只是稍作修改。
整个过程

  • 根据端口名称获取端口对象
  • 判断对象是否被占用
  • 判断端口类型,其中1代表串口,如果是串口就打开串口,设置设备参数,设置输入输出流,以及设置数据监听
public void init() {
        try {
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(PORT_NAME);
            if (portIdentifier.isCurrentlyOwned()){
                System.out.println("Error: Port is currently in use");
            }else if(portIdentifier.getPortType()==1){
                serialPort = (SerialPort) portIdentifier.open(PORT_NAME,1000);
                serialPort.setSerialPortParams(BIT_RATE,DATA_BITS,STOP_BIT,PARITY_BIT);

                in = serialPort.getInputStream();
                out = serialPort.getOutputStream();

                serialPort.addEventListener(this);
                serialPort.notifyOnDataAvailable(true);
            }else{
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

serialEvent函数,大概就是用来监听事件,他包括很多事件,但是我只判断一个,是否有是可用数据,如果存在可用数据就接收。

public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()){
            case SerialPortEvent.DATA_AVAILABLE:
                receive();
                break;
        }
    }

receive函数,用来接收收到的数据,这里比较好理解,通过上面初始化的输入流,将获取到的数据存入byte数组,并且将其转成字符串返回。

public String receive(){
        byte[] buffer = new byte[128];
        int data;
        String result = null;
        try{
            int len = 0;
            while ( ( data = in.read()) > -1 ){
                buffer[len++] = (byte) data;
            }
            byte[] copyValue = new byte[len];
            System.arraycopy(buffer,0,copyValue,0,len);
            result = ByteArrayToString(copyValue);
        }catch ( IOException e ){
            e.printStackTrace();
        }
        return result;
    }

send函数,send函数将要发送的16进制字符串消息转换成byte数组发送,并且让线程休眠1秒。

public void send(String message){
        try {
            byte[] bytes = hexStrToByteArray(message);
            out.write(bytes);
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

官网还有其他地方的收发数据都用到了线程,但是在写的过程中发现并没有使用线程的必要,所以我去掉了线程这个部分。如果发送的数据不是类似我的16进制字符串,完全可以去掉那两个转换代码,所以看情况适当修改。

整个代码

/**
 * @author:ms.y
 * @create 2019/1/24-8:48
 */
public class CommUtil implements SerialPortEventListener{

    private static final String PORT_NAME = "COM3";
    private static final int BIT_RATE = 9600;
    public static final int DATA_BITS = SerialPort.DATABITS_8;
    public static final int STOP_BIT = SerialPort.STOPBITS_1;
    public static final int PARITY_BIT = SerialPort.PARITY_NONE;

    private static SerialPort serialPort;
    private static InputStream in;
    private static OutputStream out;
    private static CommUtil commUtil;

    private CommUtil(){}

    public static CommUtil getInstance(){
        if(commUtil==null){
            commUtil = new CommUtil();
            commUtil.init();
        }
        return commUtil;
    }

public void init() {
        try {
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(PORT_NAME);
            if (portIdentifier.isCurrentlyOwned()){
                System.out.println("Error: Port is currently in use");
            }else if(portIdentifier.getPortType()==1){
                serialPort = (SerialPort) portIdentifier.open(PORT_NAME,1000);
                serialPort.setSerialPortParams(BIT_RATE,DATA_BITS,STOP_BIT,PARITY_BIT);

                in = serialPort.getInputStream();
                out = serialPort.getOutputStream();

                serialPort.addEventListener(this);
                serialPort.notifyOnDataAvailable(true);
            }else{
                System.out.println("Error: Only serial ports are handled by this example.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void send(String message){
        try {
            byte[] bytes = hexStrToByteArray(message);
            out.write(bytes);
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void serialEvent(SerialPortEvent event) {
        switch (event.getEventType()){
            case SerialPortEvent.DATA_AVAILABLE:
                receive();
                break;
        }
    }

    public String receive(){
        byte[] buffer = new byte[128];
        int data;
        String result = null;
        try{
            int len = 0;
            while ( ( data = in.read()) > -1 ){
                buffer[len++] = (byte) data;
            }
            byte[] copyValue = new byte[len];
            System.arraycopy(buffer,0,copyValue,0,len);
            result = ByteArrayToString(copyValue);
        }catch ( IOException e ){
            e.printStackTrace();
        }
        return result;
    }

    public void close(){
        try {
            in.close();
            out.close();
            serialPort.notifyOnDataAvailable(false);
            serialPort.removeEventListener();
            serialPort.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //16进制转byte数组
    public byte[] hexStrToByteArray(String str) {
        if (str == null) {
            return null;
        }
        if (str.length() == 0) {
            return new byte[0];
        }
        byte[] byteArray = new byte[str.length() / 2];
        for (int i = 0; i < byteArray.length; i++) {
            String subStr = str.substring(2 * i, 2 * i + 2);
            byteArray[i] = ((byte) Integer.parseInt(subStr, 16));
        }
        return byteArray;
    }

    public String ByteArrayToString(byte[] by) {
        String str = "";
        for (int i = 0; i < by.length; i++) {
            String hex = Integer.toHexString(by[i] & 0xFF);
            if (hex.length() == 1) {
                hex = "0" + hex;
            }
            str += hex.toUpperCase();
        }
        return str;
    }

    public static void main ( String[] args ){
        CommUtil commUtil = CommUtil.getInstance();
        commUtil.send("8101060108080302FF");
        commUtil.send("8101060108080301FF");
    }
}


附上官方参考文档地址:[串口通信示例](http://rxtx.qbang.org/wiki/index.php/Examples)

隔了几年再看这个代码,发现几个不太好的地方,本来想改的,但是没设备,就算了。
打算改的一个就是初始化那部分,单例对象一次创建,那么初始化感觉没必要写成非静态的,比较好的处理方法是静态块。
这一整个程序在当初的设计就是设计实验,所以定位就是单线程使用,所以不会出现问题,如果需要加上多线程,需要相应的做更改。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值