Android USB轉串口通信開發實例詳解


Android USB轉串口通信開發實例詳解

 

好久沒有寫文章了,年前公司新開了一個項目,是和usb轉串口通信相關的,需求是用安卓平板通過usb轉接后與好幾個外設進行通信,一直忙到最近,才慢慢閑下來,趁着這個周末不忙,記錄下usb轉串口通信開發的基本流程。

我們開發使用的是usb主機模式,即:安卓平板作為主機,usb外設作為從機進行數據通信。整個開發流程可以總結為以下幾點:

1.發現設備

?
1
2
UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
Map<String, UsbDevice> usbList = usbManager.getDeviceList();

通過UsbManager這個系統提供的類,我們可以枚舉出當前連接的所有usb設備,我們主要需要的是UsbDevice對象,關於UsbDevice這個類,官方是這樣注釋的:

?
1
2
This class represents a USB device attached to the android device with the android device
  acting as the USB host.

是的,這個類就代表了Android所連接的usb設備。

2.打開設備

接下來,我們需要打開剛剛搜索到的usb設備,我們可以將平板與usb外設之間的連接想象成一個通道,只有把通道的門打開后,兩邊才能進行通信。

一般來說,在沒有定制的android設備上首次訪問usb設備的時候,默認我們是沒有訪問權限的,因此我們首先要判斷對當前要打開的usbDevice是否有訪問權限:

?
1
2
3
4
5
6
7
8
9
if (!usbManager.hasPermission(usbDevice)) {
     usbPermissionReceiver = new UsbPermissionReceiver();
     //申請權限
     Intent intent = new Intent(ACTION_DEVICE_PERMISSION);
     PendingIntent mPermissionIntent = PendingIntent.getBroadcast(context, 0 , intent, 0 );
     IntentFilter permissionFilter = new IntentFilter(ACTION_DEVICE_PERMISSION);
     context.registerReceiver(usbPermissionReceiver, permissionFilter);
     usbManager.requestPermission(usbDevice, mPermissionIntent);
     }

這里我們聲明一個廣播UsbPermissionReceiver,當接受到授權成功的廣播后做一些其他處理:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private class UsbPermissionReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
      String action = intent.getAction();
      if (ACTION_DEVICE_PERMISSION.equals(action)) {
        synchronized ( this ) {
          UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
          if (device.getDeviceName().equals(usbDevice.getDeviceName()) {
            if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false )) {
             //授權成功,在這里進行打開設備操作
            } else {
             //授權失敗
            }
          }
        }
      }
    }
  }

接下來,我們要找到具有數據傳輸功能的接口UsbInterface,從它里邊兒找到數據輸入和輸出端口UsbEndpoint,一般情況下,一個usbDevice有多個UsbInterface,我們需要的一般是第一個,所以:

?
1
usbInterface=usbDevice.getInterface( 0 );

同樣的,一個usbInterface有多個UsbEndpoint,有控制端口和數據端口等,因此我們需要根據類型和數據流向來找到我們需要的數據輸入和輸出兩個端口:

?
1
2
3
4
5
6
7
8
9
10
for ( int index = 0 ; index < usbInterface.getEndpointCount(); index++) {
         UsbEndpoint point = usbInterface.getEndpoint(index);
         if (point.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
           if (point.getDirection() == UsbConstants.USB_DIR_IN) {
             usbEndpointIn = point;
           } else if (point.getDirection() == UsbConstants.USB_DIR_OUT) {
             usbEndpointOut = point;
           }
         }
       }

最后,才是真正的打開usb設備,我們需要和usb外設建立一個UsbDeviceConnection,它的注釋很簡介的說明了它的用途:

?
1
This class is used for sending and receiving data and control messages to a USB device.

它的獲取也很簡單,就一句代碼:

?
1
usbDeviceConnection = usbManager.openDevice(usbDevice);

到這里,理論上平板和usb外設之間的連接已經建立了,也可以首發數據了,但是,我們大部分情況下還需要對usb串口進行一些配置,比如波特率,停止位,數據控制等,不然兩邊配置不同,收到的數據會亂碼。具體怎么配置,就看你使用的串口芯片是什么了,目前流行的有pl2303,ch340等,由於篇幅問題,需要具體配置串口代碼的朋友私信我我發給你。

3.數據傳輸

到這里,我們已經可以與usb外設進行數據傳輸了,首先來看怎么向usb設備發送數據。

 1.向usb外設發送數據

在第二步中,我們已經獲取了數據的輸出端口usbEndpointIn,我們向外設發送數據就是通過這個端口來實現的。來看怎么用:

?
1
int ret = usbDeviceConnection.bulkTransfer(usbEndpointOut, data, data.length, DEFAULT_TIMEOUT);

bulkTransfer這個函數用於在給定的端口進行數據傳輸,第一個參數就是此次傳輸的端口,這里我們用的輸出端口,第二個參數是要發送的數據,類型為字節數組,第三個參數代表要發送的數據長度,最后一個參數是超時,返回值代表發送成功的字節數,如果返回-1,那就是發送失敗了。

2.接受usb外設發送來的數據

同理,我們已經找到了數據輸入端口usbEndpointIn,因為數據的輸入是不定時的,因此我們可以另開一個線程,來專門接受數據,接受數據的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
int inMax = inEndpoint.getMaxPacketSize();
ByteBuffer byteBuffer = ByteBuffer.allocate(inMax);
UsbRequest usbRequest = new UsbRequest();
usbRequest.initialize(connection, inEndpoint);
usbRequest.queue(byteBuffer, inMax);
if (connection.requestWait() == usbRequest){
   byte [] retData = byteBuffer.array();
   for (Byte byte1 : retData){
     System.err.println(byte1);
   }
}

以上,就是usb轉串口通信的基本流程,有些地方寫的不是很全面,比如接收usb外設數據的方法應該還有別的,不足之處歡迎指正。

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

原文鏈接:http://blog.csdn.net/weixin_38251977/article/details/69944095

如對本文有疑問,請提交到交流社區,廣大熱心網友會為你解答!! 點擊進入社區


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM