Android之USB转串口通信

来源:互联网 发布:everest硬件检测软件 编辑:程序博客网 时间:2024/04/28 07:55

实验目的:

STM32通过USB转串口向Android Device持续发送数据,并让其显示在Android DeviceEditview界面上


manifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.dai.usb_test">    <uses-feature android:name="android.hardware.usb.host"></uses-feature>    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity            android:name=".UsbTestActivity"            android:label="@string/app_name"            android:theme="@style/AppTheme.NoActionBar">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>            <intent-filter>                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />            </intent-filter>            <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"                android:resource="@xml/usb_device_filter" />        </activity>    </application></manifest><strong></strong>


xml/usb_device_filter.xml:

<?xml version="1.0" encoding="utf-8"?><resources>    <usb-device  vendor-id="6790" product-id="29987"  /></resources>

注:vendor-id和product-id都为十进制数值;



USB_Admin:

package com.example.dai.usb_test;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.hardware.usb.UsbDevice;import android.hardware.usb.UsbDeviceConnection;import android.hardware.usb.UsbEndpoint;import android.hardware.usb.UsbInterface;import android.hardware.usb.UsbManager;import android.util.Log;import android.widget.Toast;/** * Created by DAI on 2016/1/23. * Author:Will Smith * Email:15997135562@163.com * * Tip: *before developing USB on Android,you should configure manifests * accoriding to Android Developer */public class USB_Admin {    private UsbManager usbManager;    private UsbDevice usbDevice;    private UsbInterface usbInterface;    private UsbEndpoint usbEndpointIn;    private UsbEndpoint usbEndpointOut;    private UsbDeviceConnection usbDeviceConnection;    private static int TIMEOUT = 5000;    /*自己编写的USB管理类的构造函数*/    public USB_Admin(Context context){        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);        Log.v("USBManager:","" + usbManager);    }    /*****************************USB相关的操作**********************************/    /*获得USB的usbManager*/    public UsbManager get_UsbManager(){        return usbManager;    }    /*获得USB设备*/    public UsbDevice get_UsbDevice(Intent intent){   //这个USBDevice还有问题,暂时还得不到;        /*使用意图过滤器的方法*/        if (intent != null) {            Log.d("intent: ", "" + intent.toString());            if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {    //说明没有进入到这个if语句中                usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);        //待查找;                Log.v("USBDevice ","" + usbDevice);                if (usbDevice != null) {                    Log.d("USB device attached: ", "" + usbDevice.getDeviceName());                }            }        }        /*使用枚举的方法做一下*/        return usbDevice;    }    /*获得访问USB设备的权限*/    /*若没有在清单文件中配置USB的意图过滤器,那么就需要手动通过这一步去获取权限*/    /*    public void getPermission(){    }    */    /*获取USB设备的UsbInterface*/    /*和系统提供的函数名有冲突*/    public UsbInterface get_Interface(Context context){        usbInterface = usbDevice.getInterface(0);        Log.v("USBInterface:", "" + usbInterface);        if(usbInterface == null){            Toast.makeText(context,"can't get usbInterface",Toast.LENGTH_SHORT);            return null;        }        return usbInterface;    }    /*    作用:获取USB设备UsbEndpoint    参数:    0:表示获取输入端点    1:表示获取输出端点    */    /*和系统提供的函数名有冲突*/    public UsbEndpoint get_Endpoint(int i,Context context){        //获取输入端点        if(i == 0){            if((usbEndpointIn = usbInterface.getEndpoint(0)) != null){                Log.v("USBEndpointIn:","" + usbEndpointIn);                return usbEndpointIn;            }            Toast.makeText(context,"can't get usbEndpointIn",Toast.LENGTH_SHORT);        }else if(i == 1){     //获取输出端点            if((usbEndpointOut = usbInterface.getEndpoint(1)) != null){                Log.v("USBEndpointOut:","" + usbEndpointOut);                return usbEndpointOut;            }            Toast.makeText(context,"can't get usbEndpointOut",Toast.LENGTH_SHORT);        }        Toast.makeText(context,"can't get any usbEndpoint",Toast.LENGTH_SHORT);        return null;    }    /*获得USB设备的UsbDeviceConnection*/    public UsbDeviceConnection get_usbDeviceConnection(Context context){        if(usbManager.hasPermission(usbDevice)){            usbDeviceConnection = usbManager.openDevice(usbDevice);            Log.v("USBDeviceConnection:","" + usbDeviceConnection);            return usbDeviceConnection;        }        Toast.makeText(context,"can't get usbDeviceConnection",Toast.LENGTH_SHORT);        return null;    }    /*接收数据*/    public  int receive_Message(byte[] receiveBytes){        int ret = -1;        if(usbEndpointIn != null){            ret = usbDeviceConnection.bulkTransfer(usbEndpointIn, receiveBytes, receiveBytes.length, TIMEOUT);        }else {            Log.v("receiveBytes: ", "failed");        }        return ret;    }    /*发送数据*/    public int send_Message(byte[] sendBytes){        int ret = -1;        if(usbEndpointOut != null){            ret = usbDeviceConnection.bulkTransfer(usbEndpointOut, sendBytes, sendBytes.length, TIMEOUT);        }else {            Log.v("Send: ","failed");        }        return ret;    }    /*断开已连接的USB设备*/    public void disconnect_USB(Context context){        BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {            public void onReceive(Context context, Intent intent) {                String action = intent.getAction();                if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {                    UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);                    if (device != null) {                        usbDeviceConnection.releaseInterface(get_Interface(context));                        usbDeviceConnection.close();                    }                }            }        };    }    /*获得设备的product-id和vendor-id*/    public int get_ProductId(){        return usbDevice.getProductId();    }    /*获得设备的vendor-id*/    public int get_VendorId(){        return usbDevice.getVendorId();    }    /*获得设备的getSerialNumber*/    /*    public String get_SerialNumber(){        return null;    }    */}



UsbTestActivity:

package com.example.dai.usb_test;import android.content.Intent;import android.hardware.usb.UsbDevice;import android.hardware.usb.UsbDeviceConnection;import android.hardware.usb.UsbEndpoint;import android.hardware.usb.UsbInterface;import android.hardware.usb.UsbManager;import android.os.Bundle;import android.os.Message;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.Snackbar;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.EditText;import java.io.UnsupportedEncodingException;/*Purpose:** test USB on Android by receiving data from stm32 board,* then display on X4418 board** */public class UsbTestActivity extends AppCompatActivity {    private USB_Admin usb_admin;    private UsbManager usbManager;    private UsbDevice usbDevice;    private UsbInterface usbInterface;    private UsbDeviceConnection usbDeviceConnection;    private UsbEndpoint usbEndpointIn;    private UsbEndpoint usbEndpointOut;    protected final Object mReadBufferLock = new Object();    protected final Object mWriteBufferLock = new Object();    byte[] receiveBytes = new  byte[32];    byte[] sendBytes = new  byte[32];    private StringBuffer stringBuffer = new StringBuffer();    EditText editText;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_usb_test);        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);        setSupportActionBar(toolbar);        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);        fab.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)                        .setAction("Action", null).show();            }        });        editText = (EditText)findViewById(R.id.editText);        usb_Init();        usb_receiveData();        usb_sendData();    }    public void usb_Init(){        Intent intent = getIntent();        usb_admin = new USB_Admin(this);        Log.v("usb_admin: ", "" + usb_admin);        usbManager = usb_admin.get_UsbManager();        Log.v("usbManager: ","" + usbManager);        usbDevice = usb_admin.get_UsbDevice(intent);        Log.v("usbDevice: ", "" + usbDevice);        Log.v("interfaceCount: ",""+usbDevice.getInterfaceCount());        usbInterface = usb_admin.get_Interface(this);        Log.v("usbInterface: ", "" + usbInterface);    //1个;        Log.v("usbEndpointCount: ", "" + usbInterface.getEndpointCount());        usbEndpointIn = usb_admin.get_Endpoint(0, this);        Log.v("usbEndpointIn: ", "" + usbEndpointIn);        Log.v("usbEndpointDirection: ", "" + usbEndpointIn.getDirection());        usbEndpointOut = usb_admin.get_Endpoint(1, this);        Log.v("usbEndpointOut: ", "" + usbEndpointOut);        Log.v("usbEndpointDirection: ", "" + usbEndpointOut.getDirection());        usbDeviceConnection = usb_admin.get_usbDeviceConnection(this);        Log.v("usbDeviceConnection: ", "" + usbDeviceConnection);        configUsb340(115200);    }    public void usb_receiveData(){        ReceiveThread receiveThread = new ReceiveThread();        Thread thread = new Thread(receiveThread);        thread.start();    }    public void usb_sendData(){        SendThread sendThread = new SendThread();        Thread send = new Thread(sendThread);        send.start();    }    class ReceiveThread implements Runnable{        @Override        public void run() {            synchronized(mReadBufferLock){                while (!Thread.currentThread().isInterrupted()){                    if(usbDeviceConnection.claimInterface(usbInterface, true)){                        if((usb_admin.receive_Message(receiveBytes)) >= 0){                        /*                        for(int i=0;i<receiveBytes.length;i++){                            Log.v("Data: ",""+receiveBytes[i]);   //为什么这里得到的数据大部分都为0呢?                        }                        */                            Log.v("length: ",""+usb_admin.receive_Message(receiveBytes));                            String string = null;                            Log.v("receiveBytes: ","" + receiveBytes.toString());                            Log.v("receiveBytes: ","is OK ");                            try {                                string = new String(receiveBytes,"UTF-8");                                stringBuffer.append(string);                                Log.v("3D DATA", string);                            } catch (UnsupportedEncodingException e) {                                e.printStackTrace();                            }                            Message message = handler.obtainMessage();                            message.obj = stringBuffer;                            message.what = 1;                            handler.sendMessage(message);                        }else {                            Log.v("Receive Data: ","failed");                        }                    }else {                        Log.v("claimInterface: ","failed");                    }                    try {                        Thread.sleep(3000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }    class SendThread implements Runnable{        @Override        public void run() {            synchronized(mWriteBufferLock){                while (!Thread.currentThread().isInterrupted()){                    if(usbDeviceConnection.claimInterface(usbInterface, true)){                        String string = " Android USB Test ";                        sendBytes = string.getBytes();                        if((usb_admin.send_Message(sendBytes)) >= 0){                            Log.v("sendBytes: ","is OK ");                        }else {                            Log.v("Send Data: ","failed");                        }                    }else {                        Log.v("claimInterface: ","failed");                    }                    try {                        Thread.sleep(3000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }    }    private android.os.Handler handler = new android.os.Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what){                case 1:                    editText.setText((StringBuffer)msg.obj);                    break;                default:                    break;            }        }    };    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.menu_usb_test, menu);        return true;    }    @Override    public boolean onOptionsItemSelected(MenuItem item) {        // Handle action bar item clicks here. The action bar will        // automatically handle clicks on the Home/Up button, so long        // as you specify a parent activity in AndroidManifest.xml.        int id = item.getItemId();        //noinspection SimplifiableIfStatement        if (id == R.id.action_settings) {            return true;        }        return super.onOptionsItemSelected(item);    }    private boolean configUsb340(int paramInt)    {        byte[] arrayOfByte = new byte[8];        usbDeviceConnection.controlTransfer(192, 95, 0, 0, arrayOfByte, 8, 1000);        usbDeviceConnection.controlTransfer(64, 161, 0, 0, null, 0, 1000);        long l1 = 1532620800 / paramInt;        for (int i = 3; ; i--)        {            if ((l1 <= 65520L) || (i <= 0))            {                long l2 = 65536L - l1;                int j = (short)(int)(0xFF00 & l2 | i);                int k = (short)(int)(0xFF & l2);                usbDeviceConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);                usbDeviceConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);                usbDeviceConnection.controlTransfer(192, 149, 9496, 0, arrayOfByte, 8, 1000);                usbDeviceConnection.controlTransfer(64, 154, 1304, 80, null, 0, 1000);                usbDeviceConnection.controlTransfer(64, 161, 20511, 55562, null, 0, 1000);                usbDeviceConnection.controlTransfer(64, 154, 4882, j, null, 0, 1000);                usbDeviceConnection.controlTransfer(64, 154, 3884, k, null, 0, 1000);                usbDeviceConnection.controlTransfer(64, 164, 0, 0, null, 0, 1000);                return true;            }            l1 >>= 3;        }    }}



从STM32发送数据那段的程序如下:

#include "sys.h"#include "delay.h"#include "uart.h"#include "led.h"int main(void){int i = 0;char res[10] = {'0','1','2','3','4','5','6','7','8','9'};   //ASCII:49-57Stm32_Clock_Init(336,8,2,7);//ʨ׃ʱד,168Mhz  delay_init(168);USART_Init();while(1){for(i=0;i<10;i++){USART1->DR = res[i];while(((USART1->SR)&(0x80)) != 0x80); }delay_ms(3000);}}



效果图如下:





注:针对不同的USB转串口芯片,USB部分的配置代码不一样;本程序只针对CH340芯片可用;

具体的USB转串口程序可参考Github上的开源项目https://github.com/ksksue/PhysicaloidLibrary 

或者 https://github.com/mik3y/usb-serial-for-android 


2 0
原创粉丝点击