实验目的:
STM32通过USB转串口向Android Device持续发送数据,并让其显示在Android Device的Editview界面上
manifest.xml
xml/usb_device_filter.xml:
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:[email protected]
*
* 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= 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
关注微信公众号获取更多资讯