樹莓派3使用JAVA實現串口通訊

在這裏插入圖片描述

1、配置樹莓派:

(1)sudo raspi-config
(2)選擇 Interfacing Options,然後選擇Serial,關閉串口shell終端,使能串口。
(3)修改配置文件

sudo nano /boot/config.txt

追加如下內容

dtoverlay=pi3-miniuart-bt
enable_uart=1

2、配置Java串口環境

(1)獲取系統版本信息

uname -r

(2)將獲取到的系統版本信息寫入配置文件/usr/include/linux/version.h

#define UTS_RELEASE "4.14.34-v7+" //引號內容根據實際情概況修改

(3)下載相關程序包【網頁鏈接:http://rxtx.qbang.org/wiki/index.php/Download

wget http://rxtx.qbang.org/pub/rxtx/rxtx-2.2pre2.zip

unzip rxtx-2.2pre2.zip

cd rxtx-2.2pre2

(4)JDK1.6及以上的運行環境下,需要對configure文件進行修改。

 在configure文件中找到所有的 1.2*|1.3*|1.4*|1.5* , 將現有的JDK版本加入進去即可.如:改成 1.2*|1.3*|1.4*|1.5*|1.6*|1.7*|1.8*

sh ./configure

make

make install

(5)安裝成功後,會顯示如下信息

Libraries have been installed in:
/cloud/jdk/jre/lib/arm
...................
/usr/bin/install -c RXTXcomm.jar /cloud/jdk/jre/lib/ext/

3、編寫java代碼

示例代碼如下

/**
 * 串口通訊
 */
public class SerialPortManager
{
    private static final SerialPortManager SERIAL_PORT_MANAGER = new SerialPortManager();
    private SerialPort serialPort;
    private InputStream inputStream;
    private OutputStream outputStream;

    public static SerialPortManager getInstance()
    {
        return SERIAL_PORT_MANAGER;
    }

    public void init()
    {
        if (openPort())//打開串口
        {
            addListener();//添加監聽器
            return;
        }
        Device.isConnect = false;
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        //刷新參數
        new ParameterManager(false).run();
    }

    /**
     * 從串口讀取數據
     */
    private void readPortData(DataLinkParserUtil parserUtil)
    {
        if (!Device.isConnect)
        {
            return;
        }
        try
        {
            if (serialPort == null)
            {
                System.out.println("Serial-串口對象爲空,監聽失敗!");
                init();
                return;
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            init();
            return;
        }
        byte[] readBuffer = new byte[4096];
        try
        {
            parserUtil.unpackData(inputStream.read(readBuffer), readBuffer);
        }
        catch (IOException ignored)
        {
            System.out.println("inputStream.read(readBuffer):ERROR!");
            init();
        }
    }

    /**
     * 給串口添加監聽器
     */
    private void addListener()
    {
        try
        {
            inputStream = serialPort.getInputStream();
            outputStream = serialPort.getOutputStream();
            Device.isConnect = true;
            final DataLinkParserUtil parserUtil = new DataLinkParserUtil();
            serialPort.addEventListener(new SerialPortListener(() -> readPortData(parserUtil)));
            // 設置當有數據到達時喚醒監聽接收線程
            serialPort.notifyOnDataAvailable(true);
            // 設置當通信中斷時喚醒中斷線程
            serialPort.notifyOnBreakInterrupt(true);
            new Thread(this::sendPortData).start();//發送串口數據
            new Thread(this::getSn).start();//發送獲取飛控編號請求
        }
        catch (TooManyListenersException | IOException e)
        {
            e.printStackTrace();
            Device.isConnect = false;
            init();
        }
    }

    /**
     * 發送串口數據
     */
    private void sendPortData()
    {
        while (Device.isConnect && outputStream != null)
        {
            if (Device.sendCommandQueue.isEmpty())
            {
                continue;
            }
            Packet packet = null;
            try
            {
                packet = Device.sendCommandQueue.take();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            if (packet == null)
            {
                continue;
            }
            try
            {
                outputStream.write(packet.encodePacket());
                outputStream.flush();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    /**
     * 打開串口
     */
    private boolean openPort()
    {
        closePort();
        try
        {
            if (Parameter.isLinux)
            { //RXTX只支持ttyS開頭的設備,而我們要跟串口通訊用的是 ttyAMA0,所以在此之前還要做一下映射
                Util.exeShellCommand("sudo ln -s /dev/ttyAMA0 /dev/ttyS4502");
            }
            System.out.println("打開串口:PORT=" + Parameter.PORT + ",RATE=" + Parameter.RATE);
            serialPort = openPort(Parameter.PORT, Parameter.RATE);
            if (serialPort != null)
            {
                System.out.println("Serial-串口已打開!");
                return true;
            }
        }
        catch (PortInUseException e)
        {
            System.out.println("Serial-串口已被佔用!");
            e.printStackTrace();
            return false;
        }
        return false;
    }

    /**
     * 打開串口
     *
     * @param portName 端口名稱
     * @param rate     波特率
     * @return 串口對象
     * @throws PortInUseException 串口已被佔用
     */
    private SerialPort openPort(String portName, int rate) throws PortInUseException
    {
        try
        {
            // 通過端口名識別端口
            CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
            // 打開端口,並給端口名字和一個timeout(打開操作的超時時間)
            CommPort commPort = portIdentifier.open(portName, 2000);
            // 判斷是不是串口
            if (!(commPort instanceof SerialPort))
            {
                System.out.println("Serial-" + portName + "不是串口");
                return null;
            }
            SerialPort serialPort = (SerialPort) commPort;
            try
            {
                // 設置一下串口的波特率等參數
                // 數據位:8
                // 停止位:1
                // 校驗位:None
                serialPort.setSerialPortParams(rate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
                return serialPort;
            }
            catch (UnsupportedCommOperationException e)
            {
                e.printStackTrace();
                return null;
            }
        }
        catch (NoSuchPortException e1)
        {
            e1.printStackTrace();
            System.out.println("Serial-沒有這個端口");
            return null;
        }
    }

    /**
     * 關閉串口
     */
    public void closePort()
    {
        System.out.println("Serial-關閉串口中...");
        Device.isConnect = false;
        if (serialPort != null)
        {
            serialPort.removeEventListener();
            serialPort.close();
            serialPort = null;
        }
        if (inputStream != null)
        {
            try
            {
                inputStream.close();
                inputStream = null;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        if (outputStream != null)
        {
            try
            {
                outputStream.close();
                outputStream = null;
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("Serial-串口已關閉");
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章