智能小车制作过程全纪录: 三、软件平台--- Java 平台串口通信

2019-07-13 07:23发布

嵌入式Linux上大部分都是有C/C++来做开发的,主要的原因还是为了效率,但本人最近几年用Java比较多所以决定用Java比较多所以决定还是用Java来开发,再者个人认为现在硬件的发展,对于实时性没有苛刻要求的环境Java足可以胜任了,所以言归正传,下面开始实际行动:

1、Java虚拟机的安装,OpenJava,Oracle Java都可以,这里用Oracle Java为例

a. Ubuntu本身是Apt-get是没有Oracle java的源的,所以首先的先添加源: sudo sh -c ‘echo “deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main” >> /etc/apt/sources.list
sudo sh -c ‘echo “deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main” >> /etc/apt/sources.list
sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys EEA14886
b 用apt-get update安装即可,Ubuntu core安装Oracle Java时间比较久,要耐心等待
.sudo apt-get update
sudo apt-get install oracle-java8-installer

2、Java串口通信

Java串口通信用到了Rxtxcomm这个包,
下载地址:最新版本rxtx 2.2pre2 http://rxtx.qbang.org/wiki/index.php/Download
安装说明
http://rxtx.qbang.org/wiki/index.php/Installation_on_Linux
官方给出了详细的安装说明,但是按照这个安装说明,在调用这个包的时候提示jar包和动态链接库.so 文件不一致的问题,这是这个版本的一个bug,解决办法如下:
首先用apt-get 安装,已操作过的可以忽略此步骤
apt-get install librxtx-java
执行完此步骤后,会在/usr/lib/jni/目录下发现动态链接库文件librxtxSerial.so,这时候用cp命令将此文件拷贝到Java Home下
cp /usr/lib/jni/librxtxSerial.so /usr/lib/jvm/java-8-oracle/jre/lib/arm
接下来下载源码,按照官方按照教程,在源码目录执行如下命令:
sh ./configure
make 执行完后会发现源码目录下多出一个RXTXcomm.jar,在Java工程中直接引用即可,也可以到百度 {MOD}下载https://pan.baidu.com/s/1jHD0aj0 执行完成后,在NanoPC T3调用官方示例中的listport还是找不到串口,后来研究代码发现Linux中的设备是用文件来表示的,所有的设备都是放在/dev目录下的,而NanoPC T3的串口是用ttySAC1,ttySAC3,ttySAC4这样的方式命名的,而rxtxcomm的串口查找没有匹配这种命名方式,可以看/src/gnu/io/RXTXCommDriver.java 577~581行的代码
这里写图片描述
只需要增加NanoPC T3的命名格式,重新编译一下就好了,改完后的代码如下: if(osName.equals("Linux")) { String[] Temp = { "ttyS", // linux Serial Ports "ttySA", // for the IPAQs "ttySAC",///for friendarm "ttyUSB", // for USB frobs "rfcomm", // bluetooth serial device "ttyircomm", // linux IrCommdevices (IrDA serial emu) }; CandidatePortPrefixes=Temp; } 现在可以调用官方sample中的connect打开串口了,打开串口3和4的方式如下:
connect(“/dev/ttySAC3”);
connect(“/dev/ttySAC4”);
官方connect函数代码如下: public void connect ( String portName ) throws Exception { CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); if ( portIdentifier.isCurrentlyOwned() ) { System.out.println("Error: Port is currently in use"); } else { CommPort commPort = portIdentifier.open(this.getClass().getName(),2000); if ( commPort instanceof SerialPort ) { SerialPort serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE); InputStream in = serialPort.getInputStream(); InputStreamReader reader = new InputStreamReader(in); OutputStream out = serialPort.getOutputStream(); BufferedReader r = new BufferedReader(reader); //(new Thread(new ReaderSerial(r))).start(); //(new Thread(new WriterSerial(out))).start(); rs=new ReaderSerial(r); // pool.execute(rs); rs.start(); ws=new WriterSerial(out); // pool.execute(ws); // // ws.start(); } else { System.out.println("Error: Only serial ports are handled by this example."); } } }

3、 最后针对小车驱动对串口通信重新包装了一下

SerialComm.java 串口操作的封装类
ReaderSerial.java 串口读的封装类
WriterSerial.java 串口写的类
DriverCMD.java 小车底盘控制命令类,配合Arduino 代码的串口命令 SerialComm.java import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import gnu.io.CommPort; import gnu.io.CommPortIdentifier; import gnu.io.SerialPort; public class SerialComm { //private String msg=""; //private String lastmsg=""; private ReaderSerial rs=null; private WriterSerial ws=null; //ExecutorService pool = Executors.newCachedThreadPool(); public void setMsg(String msg) { if (ws!=null){ //System.out.println("******step 3"); ws.setMsg(msg); ws.writeSerial(); } } public SerialComm() { super(); } public void connect ( String portName ) throws Exception { CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName); if ( portIdentifier.isCurrentlyOwned() ) { System.out.println("Error: Port is currently in use"); } else { CommPort commPort = portIdentifier.open(this.getClass().getName(),2000); if ( commPort instanceof SerialPort ) { SerialPort serialPort = (SerialPort) commPort; serialPort.setSerialPortParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE); InputStream in = serialPort.getInputStream(); InputStreamReader reader = new InputStreamReader(in); OutputStream out = serialPort.getOutputStream(); BufferedReader r = new BufferedReader(reader); //(new Thread(new ReaderSerial(r))).start(); //(new Thread(new WriterSerial(out))).start(); rs=new ReaderSerial(r); // pool.execute(rs); rs.start(); ws=new WriterSerial(out); // pool.execute(ws); // // ws.start(); } else { System.out.println("Error: Only serial ports are handled by this example."); } } } public static void listPorts() { @SuppressWarnings("unchecked") java.util.Enumeration portEnum = CommPortIdentifier.getPortIdentifiers(); while ( portEnum.hasMoreElements() ) { CommPortIdentifier portIdentifier = portEnum.nextElement(); System.out.println(portIdentifier.getName() + " - " + getPortTypeName(portIdentifier.getPortType()) ); } } 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 ""; } } ReaderSerial.java import java.io.BufferedReader; import java.io.IOException; public class ReaderSerial extends Thread{ BufferedReader in; public ReaderSerial ( BufferedReader in ) { this.in = in; } public void run () { try { String line; while ((line = in.readLine()) != null){ System.out.println(line); } } catch ( IOException e ) { e.printStackTrace(); } } } WriterSerial.java public class WriterSerial/* extends Thread*/{ private OutputStream out; private String msg=""; //private String lastmsg=""; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; System.out.println("******step 4 this.msg= "+this.msg); } public WriterSerial ( OutputStream out) { this.out = out; } public void writeSerial(){ if (msg != null && msg.length() != 0) { System.out.println("******before write, the msg is " + msg); try { out.write(this.msg.getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } DriverCMD.java public class DriverCMD { private SerialComm driverCMDComm; private String stopcar="5"; private String forward="1"; private String backward="2"; private String right="3"; private String left="4"; private String automate="6"; private String manual="7"; public void openSAC(String portName){ driverCMDComm=new SerialComm(); try { driverCMDComm.connect(portName); System.out.println("******the SAC "+portName+" has been opened!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void stop(){ driverCMDComm.setMsg(stopcar); } public void forward(){ //System.out.println("******step 2"); driverCMDComm.setMsg(forward); } public void backward(){ driverCMDComm.setMsg(backward); } public void right(){ driverCMDComm.setMsg(right); } public void left(){ driverCMDComm.setMsg(left); } public void manual(){ driverCMDComm.setMsg(manual); } public void automate(){ driverCMDComm.setMsg(automate); } public void mycmd(String cmdstr){ System.out.println("******"+cmdstr); try{ if(cmdstr.equals("FORWARD")){ forward(); Thread.sleep(2000); stop(); } if(cmdstr.equals("BACKWARD")){ backward(); Thread.sleep(2000); stop(); } if(cmdstr.equals("RIGHT")){ right(); Thread.sleep(1000); stop(); } if(cmdstr.equals("LEFT")){ left(); Thread.sleep(1000); stop(); } if(cmdstr.equals("EXIT")){ System.exit(0); } if(cmdstr.equals("STOP")){ stop(); } if(cmdstr.equals("MANUAL")){ manual(); } if(cmdstr.equals("AUTOMATE")){ automate(); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.exit(0); } } public void test(){ try { System.out.println("******step 1"); forward(); Thread.sleep(3000); backward(); Thread.sleep(3000); right(); Thread.sleep(3000); left(); Thread.sleep(3000); stop(); Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.exit(0); } } } 在main函数中可以按照如下方法调用: public class Test { public static void main(String[] args) { // TODO Auto-generated method stub SerialComm.listPorts(); DriverCMD driver =new DriverCMD(); driver.openSAC("/dev/ttySAC3"); driver.test(); //...... } }