1. 程式人生 > >Android 之 串列埠通訊

Android 之 串列埠通訊

閱讀前提:串列埠通訊是微控制器採用RS232與Android板進行通訊,首先要了解RS232傳送資料的工作原理:RS232傳送資料的時候是通過一個位元組接著一個位元組,將資料傳送出去,所以當接收資料時候也應當一個位元組一個位元組接受

在AndroidManifest.xml中加入許可權

/*允許程式對SD卡進行寫入*/
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
/*允許程式對SD卡進行讀取*/
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
/>

1.登陸GitHub下載android-serialport-api


專案目錄

①首先,在main的資料夾中新建一個叫android_serialport_api的資料夾,並且把android_serialport_api中的中的SerialPort中的檔案複製到資料夾

②新建一個jni和jniLibs的資料夾,把android_serialport_api對應的檔案複製過來

2.建立SerialPortUtil單例模式

這裡簡單介紹:

單例模式:單例模式就是保證你全域性有且只有這個類的一個例項,這個例項可以在全域性使用,並且這個例項會為全域性提供訪問的節點

全域性的概念:全域性在這裡可以理解為整一個Application,這個類在整個Application中永遠只會被例項化一次(即new),當JVM檢測到這個例項不再使用就會被垃圾回收機制回收了,那麼當代碼執行到需要這個例項的時候,發現這個例項不存在就會把這個類再例項化一次,這樣就保證了記憶體中只有一個類的例項而不是多個例項

為什麼類只例項化一個:這裡涉及到一個記憶體的使用的問題,如果一個類被例項化了多次,在記憶體中就會佔有多個同一個類的多個例項,這樣就浪費記憶體,減慢程式碼執行效率。只使用一個例項可以節省記憶體,提高程式碼的執行效率。

在我這裡使用的是一個叫懶漢模式的單例模式

public
class SerialPortUtil { //這個就是需要被例項化的類 private static SerialPortUtil INSTANCE = null; //這裡必須需要一個私有的構造器 private SerialPortUtil(){ } //這裡為全域性提供訪問的節點 public static SerialPortUtil getInstance(){ //涉及延時載入,當需要這個類的時候才會被例項化 if (INSTANCE == null){ INSTANCE = new SerialPortUtil(); } return INSTANCE; } }

當對串列埠進行資料的通訊時候,進行四個步驟:①開啟串列埠、②傳送資料、③接受資料、④關閉串列埠

    //開啟串列埠
    private void openSerialPort(){

        try {
            /*設定開啟的串列埠*/
            final String portPath = "/dev/ttyS0";
            /*設定波特率*/
            final int baudRate = 115200;

            serialPort = new SerialPort(new File(portPath),baudRate,0);
            outputStream = serialPort.getOutputStream();
            inputStream = serialPort.getInputStream();

            /*開啟執行緒讀取資料*/
            new ReadThread().start();

        }catch (IOException e){

            e.printStackTrace();
        }

    }

    //關閉串列埠
    private void closeSerialPort(){

        try{

            inputStream.close();
            outputStream.close();
            serialPort.close();

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    //傳送資料
    private void sendDataToSerialPort(byte[] data){

        try{

            int dataLength = data.length;
            Log.d("DATASIZE",String.valueOf(dataLength));

            if(dataLength > 0){

                outputStream.write(data);
                outputStream.write('\n');
                outputStream.flush();
            }

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    //接收資料的執行緒
    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while(!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[64];
                    if (inputStream == null) return;
                    size = inputStream.read(buffer);
                    if (size > 0) {
                            SCMDataReceiveListener.dataRecevie(buffer, size);//監聽資料的傳輸
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

接收資料通過介面進行接收資料

    //設定監聽介面
    public void setSCMDataReceiveListener(SCMDataReceiveListener SCMDataReceiveListener) {

        this.SCMDataReceiveListener = SCMDataReceiveListener;
    }

3.SerialPortUtil原始碼

public class SerialPortUtil {

    private static SerialPortUtil INSTANCE = null;
    private SerialPort serialPort;
    private OutputStream outputStream;
    private InputStream inputStream;
    private SCMDataReceiveListener SCMDataReceiveListener;

    private SerialPortUtil(){

    }

    public static SerialPortUtil getInstance(){
        if (INSTANCE == null){
            INSTANCE = new SerialPortUtil();
        }
        return INSTANCE;
    }

    public void setSCMDataReceiveListener(SCMDataReceiveListener SCMDataReceiveListener) {
        this.SCMDataReceiveListener = SCMDataReceiveListener;
    }

    private void openSerialPort(){

        try {

            final String portPath = "/dev/ttyS0";
            final int baudRate = 115200;

            serialPort = new SerialPort(new File(portPath),baudRate,0);
            outputStream = serialPort.getOutputStream();
            inputStream = serialPort.getInputStream();

            new ReadThread().start();

        }catch (IOException e){

            e.printStackTrace();
        }

    }

    public void closeSerialPort(){

        try{

            inputStream.close();
            outputStream.close();
            serialPort.close();

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    private void sendDataToSerialPort(byte[] data){

        try{

            int dataLength = data.length;
            Log.d("DATASIZE",String.valueOf(dataLength));

            if(dataLength > 0){

                outputStream.write(data);
                outputStream.write('\n');
                outputStream.flush();
            }

        }catch (IOException e){

            e.printStackTrace();
        }
    }

    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while(!isInterrupted()) {
                int size;
                try {
                    byte[] buffer = new byte[1];
                    if (inputStream == null) return;
                    size = inputStream.read(buffer);
                    if (size > 0) {
                        /*監聽資料接收*/
                        SCMDataReceiveListener.dataRecevie(buffer, size);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

}

4.設定串列埠監聽回撥介面

public interface SCMDataReceiveListener {
    void dataRecevie(byte[] data,int size);
}