NRF5340蓝牙外设无法支持多设备连接问题排查求助
NRF5340 Zephyr外设多连接故障排查
问题背景
基于Zephyr v2.5.1开发NRF Connect外设项目,硬件为NRF5340开发板。代码设计支持多连接功能,各项单连接功能正常,但仅允许一台手机连接,第二台手机需等待前一台断开后才能成功连接。
项目配置(proj.conf)
CONFIG_BT=y CONFIG_BT_DEBUG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DIS=y CONFIG_BT_DIS_PNP=n CONFIG_BT_BAS=y CONFIG_BT_HRS=y CONFIG_BT_DEVICE_NAME="Zephyr Heartrate Sensor" CONFIG_BT_DEVICE_APPEARANCE=833 CONFIG_BT_MAX_CONN=2
主程序代码(main.c)
/* main.c - Application main entry point */ /* * Copyright (c) 2015-2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/types.h> #include <stddef.h> #include <string.h> #include <errno.h> #include <sys/printk.h> #include <sys/byteorder.h> #include <zephyr.h> #include <bluetooth/bluetooth.h> #include <bluetooth/hci.h> #include <bluetooth/conn.h> #include <bluetooth/uuid.h> #include <bluetooth/gatt.h> #include <bluetooth/services/bas.h> #include <bluetooth/services/hrs.h> #define NUM_CONN_MAX CONFIG_BT_MAX_CONN static struct bt_conn *curr_conn[NUM_CONN_MAX]; static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_HRS_VAL), BT_UUID_16_ENCODE(BT_UUID_BAS_VAL), BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)) }; static struct bt_conn **find_curr_conn(struct bt_conn *conn) { int i; struct bt_conn **conn_found = NULL; for (i = 0; i < NUM_CONN_MAX; i++) { if (curr_conn[i] == conn) { conn_found = curr_conn + i; break; } } return conn_found; } static void connected(struct bt_conn *conn, uint8_t err) { struct bt_conn **conn_room; if (err) { printk("Connection failed (err 0x%02x)\n", err); } else { conn_room = find_curr_conn(NULL); if (conn_room) { *conn_room = bt_conn_ref(conn); printk("Connected\n"); } else { printk("No room to trace connection!\n"); } } } static void disconnected(struct bt_conn *conn, uint8_t reason) { struct bt_conn **conn_found; printk("Disconnected (reason 0x%02x)\n", reason); conn_found = find_curr_conn(conn); if (conn_found) { bt_conn_unref(*conn_found); *conn_found = NULL; } } static struct bt_conn_cb conn_callbacks = { .connected = connected, .disconnected = disconnected, }; static void bt_ready(void) { int err; printk("Bluetooth initialized\n"); err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { printk("Advertising failed to start (err %d)\n", err); return; } printk("Advertising successfully started\n"); } static void auth_cancel(struct bt_conn *conn) { char addr[BT_ADDR_LE_STR_LEN]; bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); printk("Pairing cancelled: %s\n", addr); } static struct bt_conn_auth_cb auth_cb_display = { .cancel = auth_cancel, }; static void bas_notify(void) { uint8_t battery_level = bt_bas_get_battery_level(); battery_level--; if (!battery_level) { battery_level = 100U; } bt_bas_set_battery_level(battery_level); } static void hrs_notify(void) { static uint8_t heartrate = 90U; /* Heartrate measurements simulation */ heartrate++; if (heartrate == 160U) { heartrate = 90U; } bt_hrs_notify(heartrate); } void main(void) { int err; err = bt_enable(NULL); if (err) { printk("Bluetooth init failed (err %d)\n", err); return; } bt_ready(); bt_conn_cb_register(&conn_callbacks); bt_conn_auth_cb_register(&auth_cb_display); /* Implement notification. At the moment there is no suitable way * of starting delayed work so we do it here */ while (1) { k_sleep(K_SECONDS(1)); /* Heartrate measurements simulation */ hrs_notify(); /* Battery level simulation */ bas_notify(); } }
排查与解决方案
1. 修改广播模式(核心问题)
当前代码使用BT_LE_ADV_CONN_NAME启动广播,该模式在建立第一个连接后会自动停止广播,导致后续设备无法发现外设。需要改为持续可连接广播模式:
将bt_ready()函数中的广播启动代码:
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
替换为:
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0);
BT_LE_ADV_CONN模式会在建立连接后继续广播,允许其他设备发起连接请求。
2. 补充外设连接数配置
在proj.conf中添加外设模式的最大连接数配置,确保与全局连接数一致:
CONFIG_BT_PERIPHERAL_MAX_CONN=2
虽然Zephyr默认CONFIG_BT_PERIPHERAL_MAX_CONN等于CONFIG_BT_MAX_CONN,但显式配置可避免版本差异导致的限制。
3. 优化连接跟踪日志
在connected函数中添加已连接数统计打印,方便调试:
static void connected(struct bt_conn *conn, uint8_t err) { struct bt_conn **conn_room; int connected_count = 0; // 统计当前已连接数 for (int i = 0; i < NUM_CONN_MAX; i++) { if (curr_conn[i] != NULL) { connected_count++; } } if (err) { printk("Connection failed (err 0x%02x), current connected: %d\n", err, connected_count); } else { conn_room = find_curr_conn(NULL); if (conn_room) { *conn_room = bt_conn_ref(conn); connected_count++; printk("Connected, current connected: %d\n", connected_count); } else { printk("No room to trace connection! Current connected: %d\n", connected_count); } } }
4. 验证硬件与资源支持
NRF5340硬件支持最多8个BLE连接,CONFIG_BT_MAX_CONN=2的配置完全符合硬件能力,无需担心资源不足问题。
5. 调试日志分析
利用已开启的CONFIG_BT_DEBUG_LOG=y,查看连接过程中的HCI日志:
- 当第二台手机发起连接时,检查是否收到连接请求
- 若连接被拒绝,查看错误码(如
0x0D表示资源不足,需检查配置;0x08表示连接超时,需检查广播是否正常)
内容的提问来源于stack exchange,提问作者Muhammad Ahmed
相关产品推荐
相关产品推荐

