在嵌入式领域中,STM32WB 系列微控制器以其双核架构和强大的无线连接能力而著称。特别是其蓝牙5.0的功能使得这款微控制器非常适合那些需要低功耗和高性能无线连接的应用。然而,在实际的应用中,合理和有效地管理蓝牙连接是非常关键的,尤其是当设备需要断开或重新建立连接时。
本文将针对STM32WB平台,提供如何利用其HAL库和Bluetooth stack来断开蓝牙连接的方法。我们将首先了解如何通过aci_hal_get_link_status函数获取当前的蓝牙连接状态,然后,我们将使用hci_disconnect函数来断开这些连接。
最近在弄ST的课程,需要样片的可以加群申请:615061293 。
首先需要准备一个开发板,这里我准备的是WB55RG 的开发板:
https://www.bilibili.com/video/BV1U14y16712/
STM32WB55开发(3)----断开蓝牙连接
https://www.wjx.top/vm/OhcKxJk.aspx#
HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用外置的时钟源,故都选择Crystal/Ceramic Resonator选项,如下所示:
RFWKP时钟配置
可以看到,需要开启RF、RTC、RCC、IPCC、HSEM。
硬件信号量(HSEM)模块用于管理多个进程之间共享的访问权限和资源同步。
开启HSEM如下。
通信控制器(IPCC)模块的主要用于cpu之间的信号消息交换。
开启如下所示。
配置为自定义模板。
命名设备名
配置BLE GATT
配置SVC
查看原理图可以得知PB0为蓝色LED,PB1为绿色LED。
配置PB0、PB1为输出IO。
https://wiki.st.com/stm32mcu/wiki/Connectivity:STM32WB_HeartRate
HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE事件可以判断是否构建完成。
SVCCTL_App_Notification函数是一个蓝牙事件处理器,用于响应和处理STM32WB BLE堆栈中发生的各种事件。
事件处理的主要内容:
“在HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE事件中,我们能够判断Bluetooth Low Energy(BLE)设备是否已成功建立了一个新的连接。相反,在HCI_DISCONNECTION_COMPLETE_EVT_CODE事件里,我们可以确认是否一个已存在的连接已经被断开。这两个事件为我们提供了监控BLE连接状态的重要手段,从而使我们能够更好地管理设备的连接生命周期。”
在HCI_DISCONNECTION_COMPLETE_EVT_CODE中添加一个IO翻转函数。
/* USER CODE BEGIN EVT_DISCONN_COMPLETE */
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
/* USER CODE END EVT_DISCONN_COMPLETE */
在HCI_DISCONNECTION_COMPLETE_EVT_CODE中添加一个IO翻转函数。
aci_hal_get_link_status函数描述中,它返回的Link_Status数组有8个元素,这意味着该设备可以管理最多8个Bluetooth Low Energy(BLE)连接。每一个元素代表一个可能的BLE连接的状态。
因此,当你想获取每一个BLE连接的状态并据此执行某些操作(例如断开连接)时,你需要循环遍历这8个可能的连接。
在ble_hci_le.h中有该函数的说明,要使用这个函数获取当前连接的句柄并随后断开连接,可以这样做:
声明两个数组来存储函数返回的连接状态和连接句柄。
调用aci_hal_get_link_status函数获取这些值。
遍历连接状态数组,查找任何标记为已连接的连接(例如,值为0x02或0x05)。
对于每个已连接的状态,从连接句柄数组中取得相应的连接句柄,并使用hci_disconnect函数来断开连接。
在main.c中添加ble_hci_le.h文件。
/* USER CODE BEGIN Includes */
#include "ble_hci_le.h"
/* USER CODE END Includes */
在main.c中添加变量。
/* USER CODE BEGIN 0 */
uint8_t connect_flag=0;//连接成功标志位
uint32_t connect_num=0;//断开连接计数器
/* USER CODE END 0 */
在app_ble.c中引用connect_flag变量,可以在连接成功侯让该标志位为1。
/* USER CODE BEGIN Includes */
extern uint8_t connect_flag;//连接成功标志位
/* USER CODE END Includes */
可以在HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE(连接更新完成)事件中添加标志位定义,将connect_flag置位位1。
/* USER CODE BEGIN HCI_EVT_LE_CONN_COMPLETE */
HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_0);
connect_flag=1;
/* USER CODE END HCI_EVT_LE_CONN_COMPLETE */
在主程序中延时5S左右之后断开连接,遍历连接状态数组,查找任何标记为已连接的连接(例如,值为0x02或0x05)。
对于每个已连接的状态,从连接句柄数组中取得相应的连接句柄,并使用hci_disconnect函数来断开连接。
/* Init code for STM32_WPAN */
MX_APPE_Init();
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
MX_APPE_Process();
/* USER CODE BEGIN 3 */
//检查连接标志,如果连接成功,则进行处理
if(connect_flag)
{
if(connect_num<5000)
connect_num++;
else
{
connect_num=0;
// 初始化连接句柄变量
uint16_t Connection_Handle1=0;
// 定义存储连接状态和连接句柄的数组
uint8_t linkStatus[8];
uint16_t linkHandles[8];
tBleStatus status;
// 获取当前的连接状态
status = aci_hal_get_link_status(linkStatus, linkHandles);
// 检查是否成功获取连接状态
if (status == BLE_STATUS_SUCCESS) {
// 遍历所有可能的连接
for (int i = 0; i < 8; i++) {
// 判断当前连接是否处于Peripheral或Central角色
if (linkStatus[i] == 0x02 || linkStatus[i] == 0x05) {
// 断开与此连接句柄关联的连接
hci_disconnect(linkHandles[i], 0x13); // 使用适当的断开原因
}
}
}
// 重置连接标志
connect_flag=0;
}
}
HAL_Delay(1);
}
/* USER CODE END 3 */
这是一个蓝牙HCI (Host Controller Interface) 命令的函数实现,名为 hci_disconnect。HCI是蓝牙规范中定义的一个接口,允许主机与蓝牙控制器之间的通信。
在ble_hci_le.h中有该函数的说明,要使用这个函数终止现有的蓝牙连接,可以这样做:
对应的参数有:
Connection_Handle:这是一个标识符,指明要断开的连接。其有效值范围为 0x0000 到 0x0EFF。
Reason:这是一个表示终止连接原因的参数。以下是可能的原因及其值:
0x05: 认证失败 (Authentication Failure)
0x13: 远程用户终止了连接 (Remote User Terminated Connection)
0x14: 由于资源不足,远程设备终止了连接 (Remote Device Terminated Connection due to Low Resources)
0x15: 由于关闭电源,远程设备终止了连接 (Remote Device Terminated Connection due to Power Off)
0x1A: 不支持的远程特性 (Unsupported Remote Feature)
0x3B: 不可接受的连接参数 (Unacceptable Connection Parameters)
所以可以用0x13进行蓝牙断开。