国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

詳解Android USB轉(zhuǎn)串口通信開發(fā)基本流程

2019-12-12 03:08:27
字體:
供稿:網(wǎng)友

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

我們開發(fā)使用的是usb主機(jī)模式,即:安卓平板作為主機(jī),usb外設(shè)作為從機(jī)進(jìn)行數(shù)據(jù)通信。整個開發(fā)流程可以總結(jié)為以下幾點(diǎn):

1.發(fā)現(xiàn)設(shè)備

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

通過UsbManager這個系統(tǒng)提供的類,我們可以枚舉出當(dāng)前連接的所有usb設(shè)備,我們主要需要的是UsbDevice對象,關(guān)于UsbDevice這個類,官方是這樣注釋的:

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

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

2.打開設(shè)備

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

一般來說,在沒有定制的android設(shè)備上首次訪問usb設(shè)備的時候,默認(rèn)我們是沒有訪問權(quán)限的,因此我們首先要判斷對當(dāng)前要打開的usbDevice是否有訪問權(quán)限:

if (!usbManager.hasPermission(usbDevice)) {    usbPermissionReceiver = new UsbPermissionReceiver();    //申請權(quán)限    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,當(dāng)接受到授權(quán)成功的廣播后做一些其他處理: 

 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)) {             //授權(quán)成功,在這里進(jìn)行打開設(shè)備操作            } else {             //授權(quán)失敗            }          }        }      }    }  }

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

usbInterface=usbDevice.getInterface(0);

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

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設(shè)備,我們需要和usb外設(shè)建立一個UsbDeviceConnection,它的注釋很簡介的說明了它的用途:

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

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

usbDeviceConnection = usbManager.openDevice(usbDevice);

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

3.數(shù)據(jù)傳輸

到這里,我們已經(jīng)可以與usb外設(shè)進(jìn)行數(shù)據(jù)傳輸了,首先來看怎么向usb設(shè)備發(fā)送數(shù)據(jù)。

 1.向usb外設(shè)發(fā)送數(shù)據(jù)

在第二步中,我們已經(jīng)獲取了數(shù)據(jù)的輸出端口usbEndpointIn,我們向外設(shè)發(fā)送數(shù)據(jù)就是通過這個端口來實(shí)現(xiàn)的。來看怎么用:

復(fù)制代碼 代碼如下:

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

bulkTransfer這個函數(shù)用于在給定的端口進(jìn)行數(shù)據(jù)傳輸,第一個參數(shù)就是此次傳輸?shù)亩丝冢@里我們用的輸出端口,第二個參數(shù)是要發(fā)送的數(shù)據(jù),類型為字節(jié)數(shù)組,第三個參數(shù)代表要發(fā)送的數(shù)據(jù)長度,最后一個參數(shù)是超時,返回值代表發(fā)送成功的字節(jié)數(shù),如果返回-1,那就是發(fā)送失敗了。

2.接受usb外設(shè)發(fā)送來的數(shù)據(jù)

同理,我們已經(jīng)找到了數(shù)據(jù)輸入端口usbEndpointIn,因?yàn)閿?shù)據(jù)的輸入是不定時的,因此我們可以另開一個線程,來專門接受數(shù)據(jù),接受數(shù)據(jù)的代碼如下:

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轉(zhuǎn)串口通信的基本流程,有些地方寫的不是很全面,比如接收usb外設(shè)數(shù)據(jù)的方法應(yīng)該還有別的,不足之處歡迎指正。也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 西平县| 商都县| 基隆市| 双牌县| 新疆| 铜陵市| 宁都县| 九寨沟县| 南康市| 夏邑县| 屯昌县| 佛冈县| 罗山县| 扎赉特旗| 阿荣旗| 正安县| 永川市| 新建县| 中阳县| 安仁县| 石棉县| 泾川县| 凌海市| 禹州市| 宁国市| 德保县| 金溪县| 横山县| 玉龙| 沿河| 隆德县| 沐川县| 古田县| 芜湖县| 桐庐县| 成都市| 海阳市| 瓦房店市| 班戈县| 卓尼县| 沽源县|