Android USB转串口编程

快速开发和使用Android串口 串口叫做串行接口,也称串行通信接口,也可以叫做COM口,按电气标准及协议来分包括RS-232-C、RS-422、RS485、USB等。串行接口是指数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信,从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。 阅读详情

 安卓手机的对外通信接口就只有USB跟音频口,我们可采用其进行与外设进行通信。今天,我们来讲讲安卓手机利用USB接口与外设进行通信。此时,有两种情况。

第一:USB(手机)<--->USB(外设),就是手机与外设直接通过USB线进行通讯。

第二:USB(手机)<--->UART(外设),即手机与外设通过USB转接成串口,再与外设通信。

外设,说白了就是单片机,单片机端直接通过USB接口跟其他设备通讯,这种情况还是比较少见的。(另外,单片机是否具备驱动USB的能力,这个也值得质疑。我不是做下位机的,这些问题不太了解,只是说理论上这种方式是可行的而已。)一般来说,我们的单片机是通过串口跟其他设备进行通信的。所以,本文就自第二种情况进行阐述。他们的关系如下图所示。


在此,转接芯片承担着一个USB--UART转接的作用,CH34X是指具体一系列型号的芯片,包括CH340和CH341,此次我选择的是CH340,之前曾用过PL2303HA芯片作为转接芯片,但是手机端并不能很好地识别到USB设备,所以后来选择了CH340。MCU设备端的编程,是单片机工程师的串口编程,这个我们不太管,本文中我们更关注的是Android端的USB Host编程。

说到安卓USBHost编程,其实就是安卓的USB HOST编程。这部分网上资料很多,在此我大概用阐述一下。

Android下的USB Host介绍和开发

          一、USB Host介绍
USB Host,中文意思是USB主模式,是相对于USB Accessory(USB副模式)来说的。如果Android工作在USB Host模式下,则连接到Android上的USB设备把Android类似的看作是一台PC机,PC机能干的事儿,Android也能干,例如将鼠标、键盘插入则可以使用键盘、鼠标来操作Android系统,如果插入U盘则,通过Android可以读写U盘上的数据。而USB Accessory模式表示将Android设备类似当作一个USB的键盘、鼠标、U盘插入到电脑主机上一样使用,这两种模式在Android API level-12以上才支持,即Android3.1及更高的版本支持这两种模式。

在我们这里,Android端当然是主模式。 

要实现安卓USB HOST编程,系统版本只是他的软件要求,除此之外,当然还需要硬件要求。那就是手机必须支持OTG功能。不知道什么是OTG的朋友,请自行百度。

二、USB HOST开发

 关于Android USB HOST编程,网上这方面的例子也是不少的,大致可以实现从发现设备到打开连接设备并进行数据双向传输的功能。但这些例子只是单纯的进行USB通信,对于我们本文中的例子,是不够的。我们这里,USB设备之外是一个UART串口设备。虽然所对于我们的安卓端来说,转接芯片已经帮我们屏蔽了串口,已转接成USB,貌似已不用关心串口。但是,实际上,串口的 一些参数配置我们还是需要的。举个例子:如果MCU端以9600bps的波特率发送数据过来,转接芯片又如何知道应该以怎样的波特率进行接收并转换成USB数据呢?倘若转接芯片不是以相应的波特率接收数据,手机端必定接收到的是错误的数据。即使转接芯片默认的波特率是9600,得到了正确的数据,但假如MCU换了波特率,是以115200来发送呢?所以,我们原则上来说,手机端还是要通过一定的方法,发送一定的命令给CH340转接芯片,配置相应的串口参数。下面,我将会从如何进行USB HOST编程基础开始讲起,对这些问题进行阐述。

 其实不管是进行什么样方式的通信,归纳起来,无非就是四个步骤走:发现设备----->打开(连接)设备----->数据通信----->关闭设备。

 1、添加权限(安卓动不动就要添加权限,这个还是些许无聊的。)

<uses-feature android:name="android.hardware.usb.host" />
    <uses-permission android:name="android.hardware.usb.host" />
    <uses-permission android:name="ANDROID.PERMISSION.HARDWARE_TEST" />
2、添加USB设备信息

在res目录下,新建一个xml文件夹,在里面新建一个xml文件,device_filter.xml,用来存放usb的设备信息。

<?xml version="1.0" encoding="utf-8"?>
<span style="white-space:pre">	</span><resources>
   <span style="white-space:pre">		</span> <usb-device product-id="29987" vendor-id="6790" />
<span style="white-space:pre">	</span></resources>
其中的ProductID跟VendorID是你要进行通信的USB设备的供应商ID(VID)和产品识别码(PID),具体数值多少可以在接下来的枚举设备方法里面得知。

  新建完文件,我们自然要引用他,即在manifest.xml文件中声明。在要启动的Activity里添加 <meta-data />标签。

<activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:launchMode="singleTask" >
            <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/device_filter" />
        </activity>
此外,我在此Activity中添加一个action为USB_DEVICE_ATTACHED的inten-filter,只是为了在不打开应用的时候监听USB设备的插入,当插入USB设备,则自动打开该应用。并且,为了防止我在已打开应用的的时候,插入USB设备他再次打开一个应用,所以我设置其启动模式为singleTask。

3、枚举(发现)并获取相应的USB设备(相关USB类:UsbManager ,UsbDevice)

     不管进行什么通信,我们首先该做的应是获取相应的设备。此处,应是利用UsbManager 类获取插入到此Andriod手机上的USB设备,用UsbDevice类表示。

public UsbDevice EnumerateDevice(){
		mUsbmanager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
		mPendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(mString), 0);
		HashMap<String, UsbDevice> deviceList = mUsbmanager.getDeviceList();
		if(deviceList.isEmpty()) {
			Toast.makeText(mContext, "No Device Or Device Not Match", Toast.LENGTH_LONG).show();
			return null;
		}
		Iterator<UsbDevice> localIterator = deviceList.values().iterator();
		while(localIterator.hasNext()) {
			UsbDevice localUsbDevice = localIterator.next();
			for(int i = 0; i < DeviceCount; ++i) {
//				 Log.d(TAG, "DeviceCount is " + DeviceCount);
				if(String.format("%04x:%04x", new Object[]{Integer.valueOf(localUsbDevice.getVendorId()), 
						Integer.valueOf(localUsbDevice.getProductId()) }).equals(DeviceNum.get(i))) {
					IntentFilter filter = new IntentFilter(mString);
					filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
					mContext.registerReceiver(mUsbReceiver, filter);
					BroadcastFlag = true;
					return localUsbDevice;
					
				} else {
					Log.d(TAG, "String.format not match");
				}
			}
		}
		
		return null;
	}
4、打开USB设备
此处较为复杂,其实打开设备只是一个概括性的动作,实际上他还分好几个动作,不然直接打开设备的话无法通信。

 打开设备方法:

public synchronized void OpenUsbDevice(UsbDevice mDevice){
		Object localObject;
		UsbInterface intf;
		if(mDevice == null)
			return;
		intf = getUsbInterface(mDevice);
		if((mDevice != null) && (intf != null)) {
			localObject = this.mUsbmanager.openDevice(mDevice);
			if(localObject != null) {
				if(((UsbDeviceConnection)localObject).claimInterface(intf, true)) {
					this.mUsbDevice = mDevice;
					this.mDeviceConnection = ((UsbDeviceConnection)localObject);
					this.mInterface = intf;
					if(!enumerateEndPoint(intf))
						return;
					Toast.makeText(mContext, "Device Has Attached to Android", Toast.LENGTH_LONG).show();
					if(READ_ENABLE == false){
						READ_ENABLE = true;
						readThread = new read_thread(mBulkInPoint, mDeviceConnection);
						readThread.start();
					}
					return;
				}
			}
		}
		
	}
4.1 获取USB设备接口

获取到UsbDevice之后,我们在该设备上要获取相应的UsbInterface。

private UsbInterface getUsbInterface(UsbDevice paramUsbDevice) {
		if(this.mDeviceConnection != null) {
			if(this.mInterface != null) {
				this.mDeviceConnection.releaseInterface(this.mInterface);
				this.mInterface = null;
			}
			this.mDeviceConnection.close();
			this.mUsbDevice = null;
			this.mInterface = null;
		}
		if(paramUsbDevice == null)
			return null;
		for (int i = 0; i < paramUsbDevice.getInterfaceCount(); i++) {
			UsbInterface intf = paramUsbDevice.getInterface(i);
			if (intf.getInterfaceClass() == 0xff
					&& intf.getInterfaceSubclass() == 0x01
					&& intf.getInterfaceProtocol() == 0x02) {
				return intf;
			}
		}
		return null;
	}
4.2  分配端点,IN | OUT| 

获取到USB设备接口之后,我们还不能进行USB通信,USB通信需要使用UsbEndpoint端点。

private boolean enumerateEndPoint(UsbInterface sInterface){
		if(sInterface == null)
			return false;
		for(int i = 0; i < sInterface.getEndpointCount(); ++i) {
			UsbEndpoint endPoint = sInterface.getEndpoint(i);
			if(endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK && endPoint.getMaxPacketSize() == 0x20) {
				if(endPoint.getDirection() == UsbConstants.USB_DIR_IN) {
					mBulkInPoint = endPoint;
				} else {
					mBulkOutPoint = endPoint;
				}
				this.mBulkPacketSize = endPoint.getMaxPacketSize();
			} else if(endPoint.getType() == UsbConstants.USB_ENDPOINT_XFER_CONTROL) {
					mCtrlPoint = endPoint;
			}
		}
		return true;
	}
其中In端点mBulkInPoint是输入端点,是要来读数据的,Out端点mBulkOutPoint是输出端点,是写数据用的。

4.3 打开并连接USB设备

此处跟前面获取端点是可以互换顺序的。但从理解角度来说,我还是倾向于把打开设备放在最后,因为一般都是把配置方面都做好了,才去连接设备的。

此处直接使用UsbManager的方法进行连接:mUsbmanager.openDevice(mDevice);

到了这里,一般的即可进行USB数据的读写了。

5、读写USB数据

读数据:使用 mConn.bulkTransfer()方法,mBulkInPoint端点。另外,串口是的缓存很小的,最大也就几K,可认为几乎没有,具体大小取决于串口设备端的MCU,所以我们必须开一个线程去不断循环读取数据,不然倘若读取速度小于设备端的发送速度,这样就会导致数据丢失。

private class read_thread  extends Thread {
		UsbEndpoint endpoint;
		UsbDeviceConnection mConn;
		read_thread(UsbEndpoint point, UsbDeviceConnection con){
			endpoint = point;
			mConn = con;
			this.setPriority(Thread.MAX_PRIORITY);
		}
		public void run()
		{		
			while(READ_ENABLE == true)
			{
				while(totalBytes > (maxnumbytes - 63))
				{
					try 
					{
						Thread.sleep(5);
					}
					catch (InterruptedException e) {e.printStackTrace();}
				}
				synchronized(ReadQueueLock)
				{
					if(endpoint != null)
					{	
						readcount = mConn.bulkTransfer(endpoint, usbdata, 64, ReadTimeOutMillis);
						if(readcount > 0)
						{
							for(int count = 0; count< readcount; count++)
							{					    			
								readBuffer[writeIndex] = usbdata[count];
								writeIndex++;
								writeIndex %= maxnumbytes;
							}
							if(writeIndex >= readIndex)
								totalBytes = writeIndex-readIndex;
							else
								totalBytes = (maxnumbytes-readIndex)+writeIndex;
						}
					}
				}
			}
		}
	}
当要取数据的时候,直接去取readBuffer数组的数据即可。

   写数据:也是使用 mConn.bulkTransfer()方法,但是却用的mBulkOutPoint端点。

  public int WriteData(byte[] buf, int length, int timeoutMillis)
	{
		int offset = 0;
		int HasWritten = 0;
		int odd_len = length;
		if(this.mBulkOutPoint == null)
			return -1;
		while(offset < length)
		{
			synchronized(this.WriteQueueLock) {
				int mLen = Math.min(odd_len, this.mBulkPacketSize);
				byte[] arrayOfByte = new byte[mLen];
				if(offset == 0) {
					System.arraycopy(buf, 0, arrayOfByte, 0, mLen);
				} else {
					System.arraycopy(buf, offset, arrayOfByte, 0, mLen);
				}
				HasWritten = this.mDeviceConnection.bulkTransfer(this.mBulkOutPoint, arrayOfByte, mLen, timeoutMillis);
				if(HasWritten < 0) {
					return -2;
				} else {
					offset += HasWritten;
					odd_len -= HasWritten;
//					Log.d(TAG, "offset " + offset + " odd_len " + odd_len);
				}
			}
		}
		return offset;
	}
到了这里,一般的读写已可以了。网上的文章一般也就说到这一步。但是如同开头所说,并没有解决串口设置的问题,此时很大可能会接收到错误的数据,这不是我们所希望的。此时,就需要我们的下一步了。

6、串口配置

在我们的这个CH340单转接芯片里,我们采用的是mDeviceConnection.controlTransfer()这个方法来进行配置。

 6.1 :初始化串口:

public boolean UartInit(){
		int ret;
		int size = 8;
		byte[] buffer = new byte[size];
		Uart_Control_Out(UartCmd.VENDOR_SERIAL_INIT, 0x0000, 0x0000);
		ret = Uart_Control_In(UartCmd.VENDOR_VERSION, 0x0000, 0x0000, buffer, 2);
		if(ret < 0)
			return false;
		Uart_Control_Out(UartCmd.VENDOR_WRITE, 0x1312, 0xD982);
		Uart_Control_Out(UartCmd.VENDOR_WRITE, 0x0f2c, 0x0004);
		ret = Uart_Control_In(UartCmd.VENDOR_READ, 0x2518, 0x0000, buffer, 2);
		if(ret < 0)
			return false;
		Uart_Control_Out(UartCmd.VENDOR_WRITE, 0x2727, 0x0000);
		Uart_Control_Out(UartCmd.VENDOR_MODEM_OUT, 0x00ff, 0x0000);
		return true;
	}
public int Uart_Control_Out(int request, int value, int index)
	{
		int retval = 0;
		retval = mDeviceConnection.controlTransfer(UsbType.USB_TYPE_VENDOR | UsbType.USB_RECIP_DEVICE | UsbType.USB_DIR_OUT,
				request, value, index, null, 0, DEFAULT_TIMEOUT);
		
		return retval;
	}
public int Uart_Control_In(int request, int value, int index, byte[] buffer, int length)
	{
		int retval = 0;
		retval = mDeviceConnection.controlTransfer(UsbType.USB_TYPE_VENDOR | UsbType.USB_RECIP_DEVICE | UsbType.USB_DIR_IN,
					request, value, index, buffer, length, DEFAULT_TIMEOUT);
		return retval;
	}

 6.2:配置串口参数(主要是波特率,数据位,停止位,奇偶校验位以及流控)

public boolean SetConfig(int baudRate, byte dataBit, byte stopBit, byte parity, byte flowControl){
		int value = 0;
		int index = 0;
		char valueHigh = 0, valueLow = 0, indexHigh = 0, indexLow = 0;
		switch(parity) {
		case 0:	/*NONE*/
			valueHigh = 0x00;
			break;
		case 1:	/*ODD*/
			valueHigh |= 0x08;
			break;
		case 2:	/*Even*/
			valueHigh |= 0x18;
			break;
		case 3:	/*Mark*/
			valueHigh |= 0x28;
			break;
		case 4:	/*Space*/
			valueHigh |= 0x38;
			break;
		default:	/*None*/
			valueHigh = 0x00;
			break;
		}
		
		if(stopBit == 2) {
			valueHigh |= 0x04;
		}
		
		switch(dataBit) {
		case 5:
			valueHigh |= 0x00;
			break;
		case 6:
			valueHigh |= 0x01;
			break;
		case 7:
			valueHigh |= 0x02;
			break;
		case 8:
			valueHigh |= 0x03;
			break;
		default:
			valueHigh |= 0x03;
			break;
		}
		
		valueHigh |= 0xc0;
		valueLow = 0x9c;
		
		value |= valueLow;
		value |= (int)(valueHigh << 8);
		
		switch(baudRate) {
		case 50:
			indexLow = 0;
			indexHigh = 0x16;
			break;
		case 75:
			indexLow = 0;
	        indexHigh = 0x64;
	        break;
		case 110:
            indexLow = 0;
            indexHigh = 0x96;
            break;
        case 135:
            indexLow = 0;
            indexHigh = 0xa9;
            break;
        case 150:
            indexLow = 0;
            indexHigh = 0xb2;
            break;    
		case 300:
			indexLow = 0;
			indexHigh = 0xd9;
			break;
		case 600:
			indexLow = 1;
			indexHigh = 0x64;
			break;
		case 1200:
			indexLow = 1;
			indexHigh = 0xb2;
			break;
		case 1800:
            indexLow = 1;
            indexHigh = 0xcc;
            break;
		case 2400:
			indexLow = 1;
	        indexHigh = 0xd9;
			break;
		case 4800:
			indexLow = 2;
	        indexHigh = 0x64;
			break;
		case 9600:
			indexLow = 2;
	        indexHigh = 0xb2;
			break;
		case 19200:
			indexLow = 2;
	        indexHigh = 0xd9;
			break;
		case 38400:
			indexLow = 3;
	        indexHigh = 0x64;
			break;
		case 57600:
			indexLow = 3;
	        indexHigh = 0x98;
			break;
		case 115200:
			indexLow = 3;
	        indexHigh = 0xcc;
			break;
		case 230400:
			indexLow = 3;
	        indexHigh = 0xe6;
			break;
		case 460800:
			indexLow = 3;
	        indexHigh = 0xf3;
			break;				    
		case 500000:
            indexLow = 3;                                    
            indexHigh = 0xf4;
            break;
        case 921600:
            indexLow = 7;
            indexHigh = 0xf3;
            break;
        case 1000000:
            indexLow = 3;
            indexHigh = 0xfa;
            break;
        case 2000000:
            indexLow = 3;
            indexHigh = 0xfd;
            break;
        case 3000000:
            indexLow = 3;
            indexHigh = 0xfe;
            break;
		default:	// default baudRate "9600"
			indexLow = 2;
	        indexHigh = 0xb2;
			break; 
		}
		
		index |= 0x88 |indexLow;
		index |= (int)(indexHigh << 8);
		
		Uart_Control_Out(UartCmd.VENDOR_SERIAL_INIT, value, index);
		if(flowControl == 1) {
			Uart_Tiocmset(UartModem.TIOCM_DTR | UartModem.TIOCM_RTS, 0x00);
		}
		return true;
	}
这样,串口已经初始化,以及配置好相关的波特率之类的,就可以进行正确的数据收发了,就可以实现我们的USB--UART串口通信了。

7、关闭设备

当然,最后不要忘记关闭设备,释放资源。

	public synchronized void CloseDevice() {
		try {
			Thread.sleep(10);
		} catch (Exception e) {
		}

		if (this.mDeviceConnection != null) {
			if (this.mInterface != null) {
				this.mDeviceConnection.releaseInterface(this.mInterface);
				this.mInterface = null;
			}

			this.mDeviceConnection.close();
		}

		if (this.mUsbDevice != null) {
			this.mUsbDevice = null;
		}

		if (this.mUsbmanager != null) {
			this.mUsbmanager = null;
		}

		if (READ_ENABLE == true) {
			READ_ENABLE = false;
		}

		/*
		 * No need unregisterReceiver
		 */
		if (BroadcastFlag == true) {
			this.mContext.unregisterReceiver(mUsbReceiver);
			BroadcastFlag = false;
		}

		// System.exit(0);
	}

本文主要参考CH34X系列厂商提供的官方开发手册以及demo,有兴趣的朋友可以直接前往官网下载相关资料。

http://www.wch.cn/download/CH341SER_ANDROID_ZIP.html

本人知识有限,如果有说的不对的地方,欢迎留言指点,大家一起交流。 

另外亦可以加Q交流,QQ:******* (此号码于2018.5.2删除,原因尾部介绍。)

附源代码下载地址:http://download.youkuaiyun.com/detail/ever_gz/9250423。


============分割线===============

首先,感谢各位看官的信任以及支持并且希望该文章对你有所帮助。

由于老师从小便教我们要乐于助人,本人原本在此留了个QQ号,有需要的时候可以给有需要的人些许帮助。然后,这2年多来,隔三差五地会有人加我交流USB编程。一开始,本人还是本着人道主义的精神,一一通过,并耐心地给予必要的帮助。渐渐地,我发现很多人真心不厚道。很多人都是先是提问了些许相关问题,我都会跟他分析,知道的会告诉他解决方法,不知道的会提供个思路给他去试试验证。然而,个个都说好的,去试一下。结果,每个都是试着试着就没消息了。这起码试完你也跟我反馈一下行还是不行啊。这种行为真心令我不喜。 这还好,更有甚者,有一些人一开始拿着合作的名头跟你咨询相关问题,当你跟他分析了整个项目该怎么做,并给予相关技术支持之后,最后到了真正谈钱这一步后,往往又是不见人影。遇见过太多不厚道之人后,本人还是决定回来把QQ号删掉罢了。----2018.5.2补充。

CH340、CP2102、FT232怎么选?USB转串口芯片选型与避坑指南 单片机开发、PLC通信、工业设备调试等场景都离不开USB转串口芯片,其核心原理是将USB协议转换为UART信号,由芯片内部的时钟管理、收发缓冲和协议控制逻辑协作完成。技术价值集中体现在驱动兼容性、高波特率下的传输稳定性、电气保护以及外围电路复杂度,这些因素直接决定产品量产后的可靠性与返修率。从Arduino下载程序到医疗外设、充电桩等工业应用,工程师都需在CH340、CP2102、FT232之间做出权衡。CH340以低成本和高性价比著称,Linux内核原生可识别;CP2102即插即用、外围器件最少;FT23 阅读详情

相关推荐

Flutter:如何在Android中实现USB转串口通信调试

本文介绍如何通过flutter_usb_serial插件在中实现USB转串口通信调试。

sg_knight的专栏 4086

Android USB通信(host转串口)

公司属于北斗通信行业,项目大多都需要和各式各样的硬件设备相结合来满足项目需求,因此所涉及到的各种技术也相对比较冷门。前段时间有个项目用到了一款定制 Android 设备,其中有多个接口,包括两个 USB 接口和一个 RS232 串口,需要用到其中一个 USB 连接北斗设备实现指令互通,经过摸索现在也大致了解了 Android USB(host)通信流程后续还有另一个项目则用到了 USB(accessory)有空再写一篇。在这里记录和分享一下,有错漏或可优化之处欢迎大家留言。

无 1万+

Android平台USB转串口编程实战详解

厂商自定义请求由和bRequest共同标识。常见组合如下表所示:芯片bRequest功能CH3400x400x9A初始化设备CP210x0x400x1E设置波特率FTDI0x400x03设置波特率(低位在前)示例:FTDI设置波特率(低速模式)// 计算分频因子此请求同时传递了计算值和原始参数,确保芯片准确配置时钟。

weixin_42596214的博客 903

Android系统开发-添加USB转串口设备驱动i.MX8M开发

这个驱动的作用就是在内核中虚拟出/dev/ttyUSB0、/dev/ttyUSB1、/dev/ttyUSB2、/dev/ttyUSB3 这几个。对于通过 USB 接口访问的模块,在 Linux 内核中集成 USB 驱动程序。我们需要配置内核选中支持 GSM。串口,他们的作用分别是错误诊断、gps 信息接口、模块的的通信接口。和 CDMA 模块的 USB 转串口驱动。

mucheni的博客 1134

android usb转串口数据通信示例

android usb转串口数据通信示例。物联网开发中也会经常用到usb转串口,对android手机进行通信。一般都会用otc线进行转换。我在GitHub下来一份代码,亲测可用。并进行了修改封装。我的博客地址:http://blog.csdn.net/qq_16064871

Android USB转串口通信开发实例详解

Android USB转串口通信开发实例详解 好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基本流程。 我们开发使用的是usb主机模式,即:安卓平板作为主机,usb外设作为从机进行数据通信。整个开发流程可以总结为以下几点: 1.发现设备 UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); Map<String, UsbDevic

安卓源码Android沁恒USB转串口芯片CH340通信程序:开启安卓串口通信新篇章

安卓源码Android沁恒USB转串口芯片CH340通信程序:开启安卓串口通信新篇章 去发现同类优质开源项目:https://gitcode.com/ 在安卓开发领域,串口通信一直是一项挑战性的技术。然而,有了Android沁恒USB转串口芯片CH340通信程序,这一挑战变得不再困难。下面,我们就来详细了解这个项目的核心功能、技术分析、应用场景以及项目特点。 项目介绍 Android沁恒USB转串...

gitblog_06718的博客 915

详解Android USB转串口通信开发基本流程

好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基本流程。 我们开发使用的是usb主机模式,即:安卓平板作为主机,usb外设作为从机进行数据通信。整个开发流程可以总结为以下几点: 1.发现设备 UsbManager usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE); Map usbList = usbManage

安卓usb转串口通讯

由于最近公司项目要连接一个usb转串口的设备,之前没有搞过这个,于是就各种网上找资料了1.首先我们得了解安卓的usb编程,我是参考了这篇博客http://blog.csdn.net/tianruxishui/article/details/38338087,里面讲解的很清楚,其实安卓串口转usb就是usb接收的数据还要经过那个usb转串口芯片的处理,也就需要数据处理的代码,相当于是安卓的驱动。我自己

tangchao5206的博客 1万+

CH341驱动同时适用于CH340端口驱动32位专用

CH341驱动程序是一种常用的USB转串口芯片的驱动程序,该驱动程序能够使计算机与串口设备进行通信。具体描述如下: CH341驱动程序是为了满足用户在计算机上使用串口设备而开发的软件。它通过安装驱动程序,将计算机的USB接口转换成串口接口,从而实现计算机与串口设备之间的数据传输。 CH341驱动程序具有以下特点和功能:首先,它支持多种操作系统,包括Windows、Linux、Mac等,因此用户可以在几乎所有的主流操作系统上使用这个驱动程序。其次,CH341驱动程序提供了稳定可靠的通信功能,保证了计算机与串口设备之间的数据传输的稳定性和可靠性。此外,它还提供了简单易用的配置界面,让用户能够方便地设置串口参数,并且可以自定义串行波特率、数据位、停止位等参数,以满足不同应用场景的需求。 使用CH341驱动程序的过程相对简单。当用户连接一个串口设备到计算机的USB接口时,系统会自动检测并识别出这个设备,并提示用户是否需要安装对应的驱动程序。用户只需按照系统提示,选择安装CH341驱动程序,并按照驱动程序提供的步骤进行安装即可。安装完成后,用户就可以在计算机上使用串口设备了。 总之,CH

手把手教你用LaTeX完成Elsevier期刊投稿:附完整文件上传清单与注意事项

本文提供了一份详尽的Elsevier期刊LaTeX投稿实战指南。文章系统拆解了从稿件准备、文件上传到最终提交的全流程,重点解析了Manuscript、Figure(s)等关键文件的上传逻辑与注意事项,并附有PDF生成前后的详细检查清单,旨在帮助研究者高效、规范地完成投稿,规避常见错误。

weixin_29300931的博客 487

Android串口调试新纪元:MauiUsbSerialForAndroid如何重构嵌入式开发工作流?

在嵌入式开发的世界里,你是否曾经历过这样的场景:深夜调试STM32设备,USB转串口模块连接不稳定,电脑上的调试工具频繁崩溃,而手机就在手边却无法使用?或是工业现场需要快速诊断PLC设备,却只能依赖笨重的笔记本电脑?这些痛点正是MauiUsbSerialForAndroid诞生的背景——它不仅仅是一个工具,更是嵌入式开发者口袋里的技术伙伴。 ## 技术解决方案总览:跨平台串口调试的架构革命 M

gitblog_00438的博客 796

STM32F103C8T6+HX711实战:从零打造智能体重秤(附OLED显示与语音播报)

本文详细介绍了基于STM32F103C8T6微控制器和HX711称重模块,从零构建智能体重秤的完整实战教程。内容涵盖硬件选型、系统架构、驱动编写、数据滤波校准算法,并实现了OLED显示与语音播报功能。该项目是嵌入式学习的综合性实践,尤其适合作为毕业设计课题,帮助开发者掌握传感器应用、数据处理及人机交互等核心技能。

weixin_28285943的博客 518

安卓开发中的USB转串口通讯

安卓开发中的USB转串口通讯 本文使用GitHub上开源的”hoho.android.usbserial”USB串口库。该库基于“Android USB Host API”,驱动完全由java开发,无需root,不限内核,很是方便。 简介Anddroid USB Host API 原文链接 android.hardware.usb包下提供了USB开发的相关类。 我们需要了解UsbManager、U...

u011555996的博客 4691

Halcon一维测量实战:从measure_pos与measure_pairs的底层原理到精准应用

本文深入解析Halcon中measure_pos与measure_pairs算子的底层原理与精准应用,涵盖参数调优、测量矩形方向设置及典型工业场景实战。通过对比分析,揭示两者在一维测量中的核心差异与适用场景,提供从基础到高级的完整解决方案,助力工业视觉检测精度提升。

weixin_42525551的博客 425

[零基础]用docker搭建Hadoop集群

[零基础]用docker搭建Hadoop集群,每一步都有详细的解释!

weixin_56114243的博客 2万+

Android USB转串口通信开发基本流程

好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信。一直忙到近期,才慢慢闲下来,趁着这个周末不忙。记录下usb转串口通信开发的基本流程。 我们开发使用的是usb主机模式,即:安卓平板作为主机,usb外设作为从机进行数据通信。整个开发流程能够总结为下面几点: 1.发现设备 UsbManager usbMan...

weixin_33850890的博客 724

从零到一:YOLOv11高帧率模型在RDK X5上的ONNX转换与部署实战

本文详细介绍了将最新的YOLOv11高帧率模型部署到地平线RDK X5开发板的完整实战流程。内容涵盖从PyTorch模型导出ONNX、地平线工具链环境配置与模型量化编译,到编写高效的板端推理代码,并针对高帧率目标进行了后处理优化。通过实战避坑指南,帮助开发者在RDK X5上实现30FPS以上的实时目标检测。

weixin_29089057的博客 139

安卓APP:利用AndroidStudio开发usb串口通信软件【第2步】

工程代码下载地址: //download.csdn.net/download/mm13420109325/12018905 连线如下: 参考:https://www.cnblogs.com/xqxacm/p/8966430.html 遇到的问题(上面的工程打开报错)的解决方法: *****************************************************...

mm13420109325的博客 3238

《低功耗方法学》翻译——第一章:介绍

第一章:介绍

记录所学,分享知识,结识挚友 2069

YOLO26涨点改进 | 损失函数改进篇 | 引入SlideLoss,适配尺度变化+遮挡+难易样本不平衡,手把手配置+实战案例

COCO-Hard是COCO数据集的复杂场景子集,包含80个类别,重点筛选多尺度、遮挡密集样本,其中小尺度目标(<32×32像素)占比42%,大尺度目标(>128×128像素)占比28%,遮挡目标占比57%,场景涵盖人群密集、车流拥堵、复杂工业环境,完美模拟真实复杂检测场景,适合验证SlideLoss的适配性。

qq_36130719的博客 157

Android 串口编程

Android 串口编程USB转串口,直接插在有OTG功能的安卓手机上,进行串行口收发,有驱动程序下载,无需root权限,连接单片机收发数据!!

madreain的博客 620

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

上一篇: AndroidStudio开发环境搭建之Failed to sync Gradle project
Ever_广州
博客等级 码龄11年 20粉丝 3原创
评论 12
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值