關於java實現的串口通訊,使用的是開源項目RXTX,以前sun公司也有JCL項目,不過已經好久沒有更新了,RXTX項目地址:點擊打開,可是兩個項目的API用法是同樣的,只是導入的包不同而已。簡單的入門能夠參照官方的wiki。php
對應你的開發環境(Linux、window、Mac)下載對應的文件(下載地址),這裏說下具體的安裝方法,官方給的有點囉嗦,在Eclipse下使用,下載后里面的文件:html
RXTXcomm.jar包放到你項目的lib文件夾下,Java Builder Path---->Add to builder path,而後對應系統環境選擇文件:java
將兩個文件直接拷貝到項目的根目錄下:oracle
問題1app
注意,我安裝的時候出現了「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'.」ui
google好久沒有解決辦法,因此按照給出的提示信息,sudo apt-get install execstack,安裝了execstack後,在librxtxSerial所在的文件夾,打開終端,按照提少的要求execstack -c librxtxSerial.so便可解決。this
問題2google
找不到設備,這是權限問題,你應該在終端下用sudo命令啓動Eclipsespa
關於使用:.net
建議你參考這兩篇博客:使用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);