关于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);