嵌入式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();
//......
}