您的位置:首页 > 移动开发 > Android开发

Android之USB转串口通信

2016-02-26 14:02 435 查看
实验目的:

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-57
	
	Stm32_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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: