智能小车制作过程全纪录: 三、软件平台— Java 平台串口通信详解架构师

嵌入式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工程中直接引用即可,也可以到百度网盘下载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<CommPortIdentifier> 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(); 
    //...... 
} 

}

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/6915.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论