Android的联通性---USB主机模式(三)

本文详细介绍了在Android应用中获取USB设备通信权限的方法,包括创建广播接收器、申请权限、与设备通信以及断开连接。同时,提供了同步和异步数据传输的示例代码,帮助开发者实现USB设备的高效通信。

获取跟设备通信的权限

在跟USB设备进行通信之前,你的应用程序必须要获取用户的许可。

注意:如果你的应用程序使用Intent过滤器来发现接入的USB设备,而且用户允许你的应用程序处理该Intent,那么它会自动的接收权限,否则,在你的应用程序接入该设备之前,必须明确的申请权限。

明确的申请权限在某些情况下是必须的,如你的应用程序列举已经接入的USB设备并想要跟其中的一个设备通信的时候。在试图跟一个设备通信之前,你必须要检查是否有访问设备的权限。否则,如果用户拒绝了你访问该设备的请求,你会收到一个运行时错误。

要明确的获取这个权限,首先要创建一个广播接收器。这个接收器用于监听你调用requestPermission()方法时,系统所发出的Intent对象。调用requestPermission()方法时,系统会显示一个对话框,询问用户是否允许跟该USB设备进行连接。下列代码演示如何创建这个广播接收器:

private static final String ACTION_USB_PERMISSION =

"com.android.example.USB_PERMISSION";

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (ACTION_USB_PERMISSION.equals(action)) {

synchronized (this) {

UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {

if(device != null){

//call method to set up device communication

}

}

else {

Log.d(TAG, "permission denied for device " + device);

}

}

}

}

};

在你的Activity中的onCreate()方法中添加注册该广播接收器的代码:

UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

private static final String ACTION_USB_PERMISSION =

"com.android.example.USB_PERMISSION";

...

mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);

registerReceiver(mUsbReceiver, filter);

调用requestPermission()方法,显示申请接入设备的权限的对话框:

UsbDevice device;

...

mUsbManager.requestPermission(device, mPermissionIntent);

当用户应答了该对话框时,你的广播接收器就会收到一个包含EXTRA_PERMISSINO_GRANTED类型附加字段的Intent对象,该字段用一个布尔值来代表回答结果。在连接该设备之前,要检查这个字段的值是否是true。

跟设备进行通信

跟USB设备的通信既可以是异步的,也可以是同步的。在异步的情况下,你应该创建一个线程来执行所有的数据传输,以便不至于阻塞UI线程。要正确的建立跟设备的通信,你需要获得准备与其通信的设备所对应的UsbInterface和UsbEndpoint对象,并且使用UsbDeviceConnection对象把请求发送给这个端点。通常步骤如下:

1. 检查UsbDevice对象的属性,如产品ID、供应商ID、或者设备的分类,判断该设备是否是你所想要的设备;

2. 当你确认它是你想要与其通信的设备时,就要找到该设备对应的UsbInterface对象以及跟该接口对象一起的UsbEndpoint对象。接口可以有一个或多个端点,通常会有用于双工通信的输入和输出端点;

3. 当你找正确的端点时,就可以打开一个该端点上的UsbDeviceConnection对象;

4. 使用bulkTransfer()或controlTransfer()方法,把你想要传输的数据提供给端点。你应该在另外一个线程中执行本步骤的操作,以便防止阻塞主UI线程。

以下代码片段是一个普通的同步传输数据的方法。你的代码应该有更多的逻辑用于查找用来通信的正确的接口和端点,并且还应该在一个不同于主UI线程的线程中来进行数据传输:

private Byte[] bytes

private static int TIMEOUT = 0;

private boolean forceClaim = true;

...

UsbInterface intf = device.getInterface(0);

UsbEndpoint endpoint = intf.getEndpoint(0);

UsbDeviceConnection connection = mUsbManager.openDevice(device);

connection.claimInterface(intf, forceClaim);

connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread

要异步的发送数据,就要使用UsbRequest类来进行初始化,并发送一个异步请求,让后用requestWait()方法等待结果。

更多的信息请看Adb test sample,它显示了怎样进行异步块数据数据传输,MissleLauncher sample显示了如何监听异步的中断端点。

中断跟设备的通信

在你完成跟设备的通信,或者设备被分离时,就要调用releaseInterface()方法和close()方法来关闭UsbInterface和UsbDeviceConnection对象。创建下面这样的广播接收器来监听分离事件:

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) {

// call your method that cleans up and closes communication with the device

}

}

}

};

如果在应用程序中创建广播接收器,但没有在清单中注册,那么就允许你的应用程序只在运行时处理分离事件。这种情况下,分离事件只会发送给当前运行的应用程序,并且不是广播给所有的应用程序

获取跟设备通信的权限

在跟USB设备进行通信之前,你的应用程序必须要获取用户的许可。

注意:如果你的应用程序使用Intent过滤器来发现接入的USB设备,而且用户允许你的应用程序处理该Intent,那么它会自动的接收权限,否则,在你的应用程序接入该设备之前,必须明确的申请权限。

明确的申请权限在某些情况下是必须的,如你的应用程序列举已经接入的USB设备并想要跟其中的一个设备通信的时候。在试图跟一个设备通信之前,你必须要检查是否有访问设备的权限。否则,如果用户拒绝了你访问该设备的请求,你会收到一个运行时错误。

要明确的获取这个权限,首先要创建一个广播接收器。这个接收器用于监听你调用requestPermission()方法时,系统所发出的Intent对象。调用requestPermission()方法时,系统会显示一个对话框,询问用户是否允许跟该USB设备进行连接。下列代码演示如何创建这个广播接收器:

private static final String ACTION_USB_PERMISSION =

"com.android.example.USB_PERMISSION";

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (ACTION_USB_PERMISSION.equals(action)) {

synchronized (this) {

UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {

if(device != null){

//call method to set up device communication

}

}

else {

Log.d(TAG, "permission denied for device " + device);

}

}

}

}

};

在你的Activity中的onCreate()方法中添加注册该广播接收器的代码:

UsbManager mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

private static final String ACTION_USB_PERMISSION =

"com.android.example.USB_PERMISSION";

...

mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);

IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);

registerReceiver(mUsbReceiver, filter);

调用requestPermission()方法,显示申请接入设备的权限的对话框:

UsbDevice device;

...

mUsbManager.requestPermission(device, mPermissionIntent);

当用户应答了该对话框时,你的广播接收器就会收到一个包含EXTRA_PERMISSINO_GRANTED类型附加字段的Intent对象,该字段用一个布尔值来代表回答结果。在连接该设备之前,要检查这个字段的值是否是true。

跟设备进行通信

跟USB设备的通信既可以是异步的,也可以是同步的。在异步的情况下,你应该创建一个线程来执行所有的数据传输,以便不至于阻塞UI线程。要正确的建立跟设备的通信,你需要获得准备与其通信的设备所对应的UsbInterface和UsbEndpoint对象,并且使用UsbDeviceConnection对象把请求发送给这个端点。通常步骤如下:

1. 检查UsbDevice对象的属性,如产品ID、供应商ID、或者设备的分类,判断该设备是否是你所想要的设备;

2. 当你确认它是你想要与其通信的设备时,就要找到该设备对应的UsbInterface对象以及跟该接口对象一起的UsbEndpoint对象。接口可以有一个或多个端点,通常会有用于双工通信的输入和输出端点;

3. 当你找正确的端点时,就可以打开一个该端点上的UsbDeviceConnection对象;

4. 使用bulkTransfer()或controlTransfer()方法,把你想要传输的数据提供给端点。你应该在另外一个线程中执行本步骤的操作,以便防止阻塞主UI线程。

以下代码片段是一个普通的同步传输数据的方法。你的代码应该有更多的逻辑用于查找用来通信的正确的接口和端点,并且还应该在一个不同于主UI线程的线程中来进行数据传输:

private Byte[] bytes

private static int TIMEOUT = 0;

private boolean forceClaim = true;

...

UsbInterface intf = device.getInterface(0);

UsbEndpoint endpoint = intf.getEndpoint(0);

UsbDeviceConnection connection = mUsbManager.openDevice(device);

connection.claimInterface(intf, forceClaim);

connection.bulkTransfer(endpoint, bytes, bytes.length, TIMEOUT); //do in another thread

要异步的发送数据,就要使用UsbRequest类来进行初始化,并发送一个异步请求,让后用requestWait()方法等待结果。

更多的信息请看Adb test sample,它显示了怎样进行异步块数据数据传输,MissleLauncher sample显示了如何监听异步的中断端点。

中断跟设备的通信

在你完成跟设备的通信,或者设备被分离时,就要调用releaseInterface()方法和close()方法来关闭UsbInterface和UsbDeviceConnection对象。创建下面这样的广播接收器来监听分离事件:

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) {

// call your method that cleans up and closes communication with the device

}

}

}

};

如果在应用程序中创建广播接收器,但没有在清单中注册,那么就允许你的应用程序只在运行时处理分离事件。这种情况下,分离事件只会发送给当前运行的应用程序,并且不是广播给所有的应用程序
<think>好的,我现在要帮助用户了解如何通过HC-05蓝牙模块实现STM32与手机之间的字符串传输。首先,我需要整理用户的问题,他需要配置教程和示例代码。根据提供的引用内容,我需要综合这些信息来构建一个清晰的步骤指南。 首先,硬件连接部分。根据引用[1]、[2]、[3],HC-05与STM32的连接主要是通过串口。HC-05的TXD接STM32的RX,RXD接TX,同时需要连接VCC和GND。此外,引用[3]提到要注意电源稳定,所以可能需要检查电压是否匹配,比如HC-05通常是3.3V或5V,而STM32的IO电压是3.3V,所以这里可能需要确认电源是否正确,避免损坏模块。 接下来是软件配置部分。引用[4]提到使用AT指令配置模块,比如设置名称、配对码、波特率等。用户需要先配置HC-05,可能需要进入AT模式,通常是通过拉高KEY引脚再上电。但引用[3]指出AT指令的波特率需要与STM32的串口配置一致,所以在代码中需要设置对应的波特率,比如默认可能是38400或9600。这一步可能需要详细说明如何发送AT指令,例如通过串口助手先测试,再集成到STM32代码中。 然后是STM32的串口初始化。引用[5]提到STM32的USART外设,所以需要配置USART的波特率、数据位、停止位等,与HC-05的配置一致。例如,如果HC-05设置为9600波特率,那么STM32的USART也要设置为相同的。同时,需要启用USART的中断,以便接收数据。引用[3]中的注意事项也提到这一点,确保波特率匹配。 代码实现部分,引用[2]和[4]提供了示例代码的结构。需要初始化USART,编写发送和接收函数。发送数据到手机可以通过调用串口发送函数,比如HAL_UART_Transmit。接收部分则需要使用中断,当接收到数据时触发中断处理函数,将数据存储到缓冲区,并处理字符串。比如,当收到换行符时认为一个字符串接收完成,进行后续处理。 手机端可能需要一个蓝牙串口APP,比如在Android上使用蓝牙串口助手,连接到HC-05后,发送和接收数据。用户需要确保手机与HC-05配对,密码通常是1234,引用[4]提到AT指令可以设置配对码。 最后,测试和调试部分。引用[3]提到使用串口助手检查数据传输,所以可能需要在STM32端通过USB转串口打印调试信息,或者在代码中加入LED指示,当收到数据时闪烁LED,方便调试。 需要注意的问题包括电源稳定、波特率一致、AT指令的正确使用,以及中断处理函数的编写是否正确,避免数据丢失。引用[3]中的注意事项部分已经提到这些,需要在教程中强调。 现在需要将这些步骤组织成一个逻辑清晰的教程,分步说明硬件连接、AT指令配置、STM32代码编写、手机端设置,以及示例代码和测试方法。同时,根据用户要求生成相关问题,可能涉及蓝牙模块的其他配置、错误排查、性能优化等。</think>### HC-05蓝牙模块实现STM32与手机字符串传输教程 #### 一、硬件连接 1. **接线说明** - HC-05模块的`TXD`接STM32的`USART_RX`引脚(如PA10) - HC-05模块的`RXD`接STM32的`USART_TX`引脚(如PA9) - `VCC`接3.3V或5V电源(需与模块电压匹配) - `GND`接共地 - `KEY`引脚(可选)接STM32的GPIO,用于进入AT指令模式[^3][^4]。 2. **注意事项** - 确保电源稳定,避免电压波动导致通信失败。 - 若需配置HC-05参数(如名称、波特率),需通过`KEY`引脚拉高电平后上电进入AT模式[^4]。 --- #### 二、HC-05模块配置(AT指令) 1. **AT模式进入** - 将`KEY`引脚接高电平(3.3V),重新上电模块,LED变为慢闪(1秒1次)表示进入AT模式- 使用STM32的USART发送AT指令(默认波特率通常为`38400`或`9600`)[^3][^4]。 2. **常用AT指令** ```plaintext AT+NAME=MY_BLUETOOTH // 设置模块名称 AT+PSWD=1234 // 设置配对密码 AT+UART=9600,0,0 // 设置波特率为9600(需与STM32串口配置一致) AT+ROLE=0 // 设置为从模式(手机作为主机连接) ``` --- #### 、STM32代码实现 1. **USART初始化** ```c // 配置USART1(以STM32F103C8T6为例) void USART1_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 9600; // 与HC-05波特率一致 huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; HAL_UART_Init(&huart1); // 启用接收中断 HAL_UART_Receive_IT(&huart1, &rx_buffer, 1); } ``` 2. **字符串发送函数(STM32→手机)** ```c void Send_String(char *str) { HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 100); } ``` 3. **接收中断处理(手机→STM32)** ```c char rx_buffer[128]; uint8_t idx = 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart == &huart1) { if (rx_buffer[idx] == '\n' || idx >= sizeof(rx_buffer)-1) { rx_buffer[idx] = '\0'; // 字符串结束符 Process_Received_Data(rx_buffer); // 自定义处理函数 idx = 0; } else { idx++; } HAL_UART_Receive_IT(&huart1, &rx_buffer[idx], 1); // 重新启用中断 } } ``` --- #### 四、手机端设置 1. **蓝牙连接** - 手机蓝牙设置中搜索并配对名为`MY_BLUETOOTH`的设备(密码`1234`)。 - 使用蓝牙串口APP(如“Serial Bluetooth Terminal”)连接HC-05模块。 2. **数据收发测试** - 手机发送字符串,STM32通过中断接收并处理。 - STM32调用`Send_String("Hello Phone!\n")`向手机发送数据。 --- #### 五、示例代码(基于HAL库) ```c #include "stm32f1xx_hal.h" UART_HandleTypeDef huart1; int main(void) { HAL_Init(); USART1_Init(); Send_String("Bluetooth Ready!\n"); while (1) { // 主循环可执行其他任务 } } // USART1初始化、Send_String和中断回调函数同上 ``` --- #### 六、注意事项 1. **波特率一致性**:确保STM32、HC-05和手机APP的波特率设置相同。 2. **电源干扰**:为HC-05单独供电时,需与STM32共地[^3]。 3. **AT指令超时**:发送AT指令后等待模块返回`OK`再继续操作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值