You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nordic nRF52840设置可扫描扩展广播后周期广播参数报错-22

问题分析与解决方案

问题描述

基于Nordic nRF52840开发周期性广播功能,搭配自研Android应用扫描设备时无法发现目标设备。排查Android端代码无异常后,发现将bt_le_ext_adv_create()的参数从BT_LE_EXT_ADV_NCONN_NAME(不可连接扩展广播)改为BT_LE_EXT_ADV_SCAN_NAME(可扫描扩展广播)后,调用bt_le_per_adv_set_param()会返回错误码-22(无效参数),相关代码如下:

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <bluetooth/bluetooth.h>
#define DEVICE_NAME     "RECEIVER"
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
static uint8_t mfg_data[] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,
                          0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,
                          0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,
                          0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10};

static const struct bt_data ad[] = {
BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, 40),
};

void main(void)
{
struct bt_le_ext_adv *adv;
int err;

printk("Starting Periodic Advertising Demo\n");

/* Initialize the Bluetooth Subsystem */
err = bt_enable(NULL);
if (err) {
    printk("Bluetooth init failed (err %d)\n", err);
    return;
}

/* Create a non-connectable non-scannable advertising set */
err = bt_le_ext_adv_create(BT_LE_EXT_ADV_SCAN_NAME, NULL, &adv); //  BT_LE_EXT_ADV_NCONN_NAME  BT_LE_EXT_ADV_SCAN_NAME
if (err) {
    printk("Failed to create advertising set (err %d)\n", err);
    return;
}

/* Set periodic advertising parameters */
err = bt_le_per_adv_set_param(adv, BT_LE_PER_ADV_DEFAULT);
if (err) {
    printk("Failed to set periodic advertising parameters"
           " (err %d)\n", err);
    return;
}

/* Enable Periodic Advertising */
err = bt_le_per_adv_start(adv);
if (err) {
    printk("Failed to enable periodic advertising (err %d)\n", err);
    return;
}

while (true) {
    printk("Start Extended Advertising...");
    err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
    if (err) {
        printk("Failed to start extended advertising "
               "(err %d)\n", err);
        return;
    }
    printk("done.\n");

    

    k_sleep(K_SECONDS(10));

    printk("Stop Extended Advertising...");
    err = bt_le_ext_adv_stop(adv);
    if (err) {
        printk("Failed to stop extended advertising "
               "(err %d)\n", err);
        return;
    }
    printk("done.\n");

    k_sleep(K_SECONDS(10));
    }
}

错误原因

错误码-22对应EINVAL,核心问题是可扫描扩展广播(BT_LE_EXT_ADV_SCAN_NAME)与周期性广播(Periodic Advertising)的参数组合不被Zephyr蓝牙栈允许。

根据蓝牙核心规范和Zephyr实现逻辑:

  • 周期性广播的设计目标是无连接场景下周期性发送数据,要求绑定的广告集必须是不可连接类型;
  • BT_LE_EXT_ADV_SCAN_NAME属于可扫描广告集,允许外部设备发送扫描请求,与周期性广播的逻辑冲突,因此调用bt_le_per_adv_set_param()会触发无效参数错误。

解决方案

拆分两个独立的广告集,分别实现可扫描发现和周期性广播功能:

  1. 一个广告集用BT_LE_EXT_ADV_SCAN_NAME配置,负责广播设备名称,确保Android设备能扫描发现;
  2. 另一个广告集用BT_LE_EXT_ADV_NCONN_NAME配置,绑定周期性广播,用于发送自定义厂商数据。

修改后的代码示例:

/*
 * Copyright (c) 2020 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <bluetooth/bluetooth.h>
#define DEVICE_NAME     "RECEIVER"
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

// 自定义厂商数据
static uint8_t mfg_data[] = { 
    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,
    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,
    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10,
    0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10
};

// 可扫描广告数据:包含完整设备名称
static const struct bt_data scan_ad[] = {
    BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

// 周期性广播数据:自定义厂商数据
static const struct bt_data periodic_ad[] = {
    BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, sizeof(mfg_data)),
};

void main(void)
{
    struct bt_le_ext_adv *scan_adv;
    struct bt_le_ext_adv *periodic_adv;
    int err;

    printk("Starting Periodic Advertising Demo\n");

    // 初始化蓝牙子系统
    err = bt_enable(NULL);
    if (err) {
        printk("Bluetooth init failed (err %d)\n", err);
        return;
    }

    // 创建可扫描扩展广告集
    err = bt_le_ext_adv_create(BT_LE_EXT_ADV_SCAN_NAME, NULL, &scan_adv);
    if (err) {
        printk("Failed to create scan adv set (err %d)\n", err);
        return;
    }

    // 设置可扫描广告数据
    err = bt_le_ext_adv_set_data(scan_adv, scan_ad, ARRAY_SIZE(scan_ad), NULL, 0);
    if (err) {
        printk("Failed to set scan adv data (err %d)\n", err);
        return;
    }

    // 启动可扫描广告(持续广播,确保被Android发现)
    err = bt_le_ext_adv_start(scan_adv, BT_LE_EXT_ADV_START_DEFAULT);
    if (err) {
        printk("Failed to start scan adv (err %d)\n", err);
        return;
    }
    printk("Scan advertising started.\n");

    // 创建不可连接扩展广告集,用于绑定周期性广播
    err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, &periodic_adv);
    if (err) {
        printk("Failed to create periodic adv set (err %d)\n", err);
        return;
    }

    // 设置周期性广播数据
    err = bt_le_ext_adv_set_data(periodic_adv, periodic_ad, ARRAY_SIZE(periodic_ad), NULL, 0);
    if (err) {
        printk("Failed to set periodic adv data (err %d)\n", err);
        return;
    }

    // 设置周期性广播参数
    err = bt_le_per_adv_set_param(periodic_adv, BT_LE_PER_ADV_DEFAULT);
    if (err) {
        printk("Failed to set periodic adv params (err %d)\n", err);
        return;
    }

    // 启用周期性广播
    err = bt_le_per_adv_start(periodic_adv);
    if (err) {
        printk("Failed to start periodic adv (err %d)\n", err);
        return;
    }

    // 周期性启停扩展广播(原逻辑保留)
    while (true) {
        printk("Start Periodic Extended Advertising...");
        err = bt_le_ext_adv_start(periodic_adv, BT_LE_EXT_ADV_START_DEFAULT);
        if (err) {
            printk("Failed (err %d)\n", err);
            return;
        }
        printk("done.\n");

        k_sleep(K_SECONDS(10));

        printk("Stop Periodic Extended Advertising...");
        err = bt_le_ext_adv_stop(periodic_adv);
        if (err) {
            printk("Failed (err %d)\n", err);
            return;
        }
        printk("done.\n");

        k_sleep(K_SECONDS(10));
    }
}

说明

  • 可扫描广告集持续广播设备名称,确保Android设备能正常发现设备;
  • 周期性广播集独立运行,按设定周期发送自定义数据,避免参数冲突;
  • 原代码中启停扩展广播的逻辑保留,可根据实际需求调整周期。

内容的提问来源于stack exchange,提问作者JayLin1119

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 21:45:33