編輯:關於Android編程
Android 串口通信編程:嵌入式編程和可穿戴設備及智能設備都會用到串口,這裡就帶大家分析下,
一,android串口通信
串口通信采用一個第三方開源項目,實現串口數據收發。
1. 使用了http://code.google.com/p/android-serialport-api/的項目的serialport api和jni;
2. 支持4串口同時收發,有定時自動發送功能,收發模式可選Txt或Hex模式;
3. n,8,1,沒得選;
4. 為減輕界面卡頓的情況,接收區的刷新采用單獨的線程進行定時刷新;
5. 發送區的數據以及一些設置項,在程序關閉時會自動保存,打開時自動載入;
6. jni使用最新的NDKr8b重新編譯了一下
簡單編寫步驟:
1.新建一個項目,自己起個名字
2.直接復制serialport api和jni文件夾到新建的工程,如果不想自己編譯jni,就連libs文件夾也一起復制
3.去android官方網站下載NDK,解壓,在CMD中轉到jni目錄,並執行 絕對路徑\ndk-build
4.自己再封裝一個工具類或直接使用SerialPort類都行,舉個直接使用的例:
直接剽竊原項目的SerialPortActivity.java,並稍微改一下,重點改這裡
mSerialPort = mApplication.getSerialPort();
這裡可以改成
new SerialPort(new File("/dev/s3c2410_serial0"), 9600, 0);//COM0,波特率9600
5. SerialPortFinder的使用就沒什麼好講的了,實例化後用.getAllDevicesPath()就能獲取到所有設備了。
其它如數據轉換等請參考源碼
源碼可以參考谷歌android-serialport-api例子
http://code.google.com/p/android-serialport-api/source/checkout
svn checkout http://android-serialport-api.googlecode.com/svn/trunk
二,串口通信協議解析
1.通信基本格式
字段 描述 長度(字節)
起始符 0F,十六進制碼 1
信息類型 一個字節,十六進制碼(0F,F0,FF等保留碼不用)1
信息長度 是信息內容的長度,ASCII碼表示(0~9,A~F,最大長度為256)(例如長為11個,十六進制是0B,則兩個字節就寫0x30 0x42)。
注:因為最大長度256不能滿足有些指令的要求,所以對長度做了擴展,下面是擴展說明:
如果第一個字節的最高位為1,則表示擴展長度。在擴展長度狀態下,其他15個字節通過16進制大端模式來保存長度。比如:0x80 0x12表示長度為0x001 2,0x81 0x12表示長度為0x0112。2
信息內容 一組十六進制碼 N
校驗 一個字節,十六進制碼,是自信息類型起至對象號止所有碼的異或。1
結束符 F0,一個字節,十六進制碼 (為了保證可靠性,車機下發的結束符為F0 FF)1
2.協議解析
/** * 讀取終端設備數據 * @author Administrator */ private class ReadThread extends Thread { @Override public void run() { super.run(); // 定義一個包的最大長度 int maxLength = 2048; byte[] buffer = new byte[maxLength]; // 每次收到實際長度 int available = 0; // 當前已經收到包的總長度 int currentLength = 0; // 協議頭長度4個字節(開始符1,類型1,長度2) int headerLength = 4; while (!isInterrupted()) { try { available = mInputStream.available(); if (available > 0) { // 防止超出數組最大長度導致溢出 if (available > maxLength - currentLength) { available = maxLength - currentLength; } mInputStream.read(buffer, currentLength, available); currentLength += available; } } catch (Exception e) { e.printStackTrace(); } int cursor = 0; // 如果當前收到包大於頭的長度,則解析當前包 while (currentLength >= headerLength) { // 取到頭部第一個字節 if (buffer[cursor] != 0x0F) { --currentLength; ++cursor; continue; } int contentLenght = parseLen(buffer, cursor, headerLength); // 如果內容包的長度大於最大內容長度或者小於等於0,則說明這個包有問題,丟棄 if (contentLenght <= 0 || contentLenght > maxLength - 5) { currentLength = 0; break; } // 如果當前獲取到長度小於整個包的長度,則跳出循環等待繼續接收數據 int factPackLen = contentLenght + 5; if (currentLength < contentLenght + 5) { break; } // 一個完整包即產生 // proceOnePacket(buffer,i,factPackLen); onDataReceived(buffer, cursor, factPackLen); currentLength -= factPackLen; cursor += factPackLen; } // 殘留字節移到緩沖區首 if (currentLength > 0 && cursor > 0) { System.arraycopy(buffer, cursor, buffer, 0, currentLength); } } } } /** * 獲取協議內容長度 * @param header * @return */ public int parseLen(byte buffer[], int index, int headerLength) { // if (buffer.length - index < headerLength) { return 0; } byte a = buffer[index + 2]; byte b = buffer[index + 3]; int rlt = 0; if (((a >> 7) & 0x1) == 0x1) { rlt = (((a & 0x7f) << 8) | b); } else { char[] tmp = new char[2]; tmp[0] = (char) a; tmp[1] = (char) b; String s = new String(tmp, 0, 2); rlt = Integer.parseInt(s, 16); } return rlt; } protected void onDataReceived(final byte[] buffer, final int index, final int packlen) { System.out.println("收到信息"); byte[] buf = new byte[packlen]; System.arraycopy(buffer, index, buf, 0, packlen); ProtocolAnalyze.getInstance(myHandler).analyze(buf); }
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
一、什麼是鎖在Java的util.concurrent.locks包下有關於鎖的接口和類如下:先看一段代碼:package com.codeing.snail.test;
WindowsAndroid我們可以這樣來稱呼我們此次Win8中運行安卓系統的方法。這款軟件是北京某公司剛剛研發出來的
java虛擬機運行一般都有一個內存界限,超過這個界限,就會報outofmemory。這個時候一般都是存在內存洩漏。解決內存洩漏問題,竊以為分為兩個步驟:分析應用程序是否真
Android 解決監聽home鍵的幾種方法前言:以下兩種方法可以完美解決監聽back鍵,home鍵,多任務鍵(最近任務鍵)。一、使用注冊廣播監聽home鍵、多任務鍵演示