java下的串口通信-RXTX

关于java实现的串口通信,使用的是开源项目RXTX,之前sun公司也有JCL项目,不过已经很久没有更新了,RXTX项目地址:点击打开,但是两个项目的API用法是一样的,只是导入的包不一样而已。简单的入门可以参照官方的wiki

对应你的开发环境(Linux、window、Mac)下载对应的文件(下载地址),这里说下具体的安装方法,官方给的有点啰嗦,在Eclipse下使用,下载后里面的文件:

RXTXcomm.jar包放到你项目的lib文件夹下,Java Builder Path---->Add to builder path,然后对应系统环境选择文件:

 

将两个文件直接拷贝到项目的根目录下:

 

问题1

注意,我安装的时候出现了“VM warning: You have loaded library /****/***/***/librxtxSerial.so which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.

google很久没有解决办法,所以按照给出的提示信息,sudo apt-get install execstack,安装了execstack后,在librxtxSerial所在的文件夹,打开终端,按照提少的要求execstack -c librxtxSerial.so即可解决。

问题2

找不到设备,这是权限问题,你应该在终端下用sudo命令启动Eclipse

关于使用:

建议你参考这两篇博客:使用comm在java程序中管理本地端口Java串口通讯,两篇讲的是一些基础知识依据API的基本用法,当然如果你依据很熟悉,那么你可以直接写写代码运行下,比如扫描当前的设备端口:

   public static void listPorts()
    {
        java.util.Enumeration<CommPortIdentifier> portEnum = CommPortIdentifier.getPortIdentifiers();
        while ( portEnum.hasMoreElements() ) 
        {
            CommPortIdentifier portIdentifier = portEnum.nextElement();
            System.out.println(portIdentifier.getName()  +  " - " +  getPortTypeName(portIdentifier.getPortType()) );
        }        
    }
    
   public 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";
        }
    }

串口通信,有两种方式,两篇博客说的很详细了,你也可以参考wiki的例子了解其通信流程,我仿照官方写的例子,部分有改动,SerialRXTX.java:

package nir.desktop.demo;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.HashSet;

public class SerialRXTX {
    /**
     * This code snippet shows how to retrieve the available comms ports on your
     * computer. A CommPort is available if it is not being used by another
     * application.
     */
    public static void listAvailablePorts() {
        HashSet<CommPortIdentifier> portSet = getAvailableSerialPorts();
        String[] serialPort = new String[portSet.size()];
        int i = 0;
        for (CommPortIdentifier comm : portSet) {
            serialPort[i] = comm.getName();
            System.out.println(serialPort[i]);
            i++;
        }
    }

    public 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";
        }
    }

    /**
     * @return A HashSet containing the CommPortIdentifier for all serial ports
     *         that are not currently being used.
     */
    public static HashSet<CommPortIdentifier> getAvailableSerialPorts() {
        HashSet<CommPortIdentifier> h = new HashSet<CommPortIdentifier>();
        @SuppressWarnings("rawtypes")
        Enumeration thePorts = CommPortIdentifier.getPortIdentifiers();// 可以找到系统的所有的串口,每个串口对应一个CommPortldentifier
        while (thePorts.hasMoreElements()) {
            CommPortIdentifier com = (CommPortIdentifier) thePorts
                    .nextElement();
            switch (com.getPortType()) {
            case CommPortIdentifier.PORT_SERIAL:// type of the port is serial
                try {
                    CommPort thePort = com.open("CommUtil", 50);// open the serialPort
                    thePort.close();
                    h.add(com);
                } catch (PortInUseException e) {
                    System.out.println("Port, " + com.getName()
                            + ", is in use.");
                } catch (Exception e) {
                    System.err.println("Failed to open port " + com.getName());
                    e.printStackTrace();
                }
            }
        }
        return h;
    }

    public static SerialPort connect(String portName) throws Exception {
        SerialPort serialPort = null;
        CommPortIdentifier portIdentifier = CommPortIdentifier
                .getPortIdentifier(portName);// initializes of port operation
        if (portIdentifier.isCurrentlyOwned()) {
            System.out.println("Error: Port is currently in use");
        } else {
            CommPort commPort = portIdentifier.open(portName, 2000);// the delay
                                                                    // time of
                                                                    // opening
                                                                    // port
            if (commPort instanceof SerialPort) {
                serialPort = (SerialPort) commPort;
                serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8,
                        SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);// serial
                                                                        // communication
                                                                        // parameters
                                                                        // setting
                InputStream inputStream = serialPort.getInputStream();
                // OutputStream outputStream = serialPort.getOutputStream();
                // (new Thread(new SerialWriter(outputStream))).start();
                serialPort.addEventListener(new SerialReader(inputStream));
                serialPort.notifyOnDataAvailable(true);
            }
        }
        return serialPort;

    }

    /**
     * not necessary to send command in new thread, but the serialPort only has
     * one instance
     * 
     * @param serialPort
     * @param string
     */
    public static void sendMessage(SerialPort serialPort, String string) {
        try {
            OutputStream outputStream = serialPort.getOutputStream();
            (new Thread(new SerialWriter(outputStream, string))).start();// send
                                                                            // command
                                                                            // in
                                                                            // the
                                                                            // new
                                                                            // thread
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * Handles the input coming from the serial port. A new line character is
     * treated as the end of a block in this example.
     */
    public static class SerialReader implements SerialPortEventListener {
        private InputStream in;

        public SerialReader(InputStream in) {
            this.in = in;
        }

        public void serialEvent(SerialPortEvent arg0) {
            byte[] buffer = new byte[1024];
            try {
                Thread.sleep(500);// the thread need to sleep for completed
                                    // receive the data
                if (in.available() > 0) {
                    in.read(buffer);
                }
                System.out.println(new String(buffer));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    /** */
    public static class SerialWriter implements Runnable {
        OutputStream out;
        String commandString;

        public SerialWriter(OutputStream out, String commandString) {
            this.out = out;
            this.commandString = commandString;
        }

        public void run() {
            while (true) {
                try {
                    Thread.sleep(3000);// an interval of 3 seconds to sending
                                        // data
                    out.write(commandString.getBytes());
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InterruptedException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) {
        listAvailablePorts();
        try {
            sendMessage(connect("/dev/ttyUSB0"), "P");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}

返回的数据:

在监听返回数据的时候,出现的问题是返回的数据不连续,比如:

P

H:05.36

解决的方法是在接受的地方让线程休眠一下,即可解决

Thread.sleep(500);

 

posted @ 2015-06-14 20:55  tomi_mint  阅读(8886)  评论(1编辑  收藏  举报