zoukankan      html  css  js  c++  java
  • 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);
  • 相关阅读:
    Binder机制1---Binder原理介绍
    ShareSDK for iOS 2.9.0已经公布
    TCP/IP数据包结构具体解释
    苹果ipa软件包破解笔记
    自己定义对象的监听方式
    强大的PropertyGrid
    matlab中plot使用方法
    fopen 參数具体解释
    leetcode:linked_list_cycle_II
    AssemblyInfo.cs文件的作用
  • 原文地址:https://www.cnblogs.com/sowhat4999/p/4575696.html
Copyright © 2011-2022 走看看