LE Broadcaster

LE broadcaster示例工程可以作为开发基于broadcaster角色的APP的框架。

broadcaster角色特征:

  • 可以发送不可连接广播。

  • 不能创建连线。

环境需求

该示例支持以下开发工具包:

环境需求

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

该示例还需要一个设备运行一个LE observer角色,用于扫描广播。例如运行LE observer示例工程的另一个开发板,或者装LE dongle的电脑,或者装有 LightBlue 之类LE应用的手机。

更多要求,请参考 快速入门

硬件连线

请参考 快速入门 中的 EVB接口和模块

配置选项

APP配置选项

APP所有需要配置的内容在 samples\bluetooth\ble_broadcaster\src\app_flags.h 中, 开发者可以根据实际需求配置。

/** @brief  Config DLPS: 0-Disable DLPS, 1-Enable DLPS */
#define F_BT_DLPS_EN                        1

/** @} */ /* End of group BROADCASTER_Config */

编译和下载

该示例可以在SDK文件夹中找到:

Project file: samples\bluetooth\ble_broadcaster\proj\rtl87x2g\mdk

Project file: samples\bluetooth\ble_broadcaster\proj\rtl87x2g\gcc

编译和运行该示例请遵循以下步骤:

  1. 打开项目文件。

  2. 要编译目标文件, 请参考 快速入门编译APP Image 中列出的步骤。

  3. 编译成功后,目录 samples\bluetooth\ble_broadcaster\proj\rtl87x2g\mdk\bin 下会生成app bin文件 app_MP_sdk_xxx.bin

  4. 要下载app bin到 EVB ,请参考 快速入门MPTool 中列出的步骤。

  5. 在EVB上按下reset键,程序将开始运行。

测试验证

将示例工程烧录到EVB后,开发者可以使用另一个运行 LE Observer 工程的开发板或者装有 LightBlue 之类LE应用的手机来进行测试。

与另一块开发板对测

请参考 LE Observer 章节 与另一块开发板对测

与手机对测

  1. DUT 上的 reset 按钮, DUT 将开始发送不可连接的非定向广播。

如果成功启动广播,会打印下面的 DebugAnalyser 日志。 如果没有看到下列日志,说明广播启动失败。请检查软件和硬件环境 是否配置正确。

[APP] !**GAP adv start
  1. 在iOS设备上打开 LightBlue 搜索 DUT, 如图所示:

../../../../../_images/test_with_iOS_device.png

与iOS设备对测

开发者只能在手机端进行scan操作,因为 DUT 发送的广播是不可连接的。

代码介绍

本章的主要目的是帮助APP开发者熟悉Broadcaster Role相关的开发流程。本章将按照以下几个部分进行介绍:

源码路径

  • 工程目录: samples\bluetooth\ble_broadcaster\proj

  • 源码目录: samples\bluetooth\ble_broadcaster\src

LE broadcaster示例工程中的源文件当前被分为几个组,如下所示。

└── Project: broadcaster
    └── secure_only_app
        └── Device                   includes startup code
        ├── CMSE Library             Non-secure callable lib
        ├── Lib                      includes all binary symbol files that user application is built on
            ├── ROM_NS.lib
            └── lowerstack.lib
            └── rtl87x2g_sdk.lib
            └── gap_utils.lib
        ├── Peripheral               includes all peripheral drivers and module code used by the application
        ├── Profile                  includes LE profiles or services used by the sample application
        └── APP                      includes the ble_broadcaster user application implementation
            ├── app_task.c
            ├── main.c
            └── broadcast_app.c

示例工程使用与 bt_host_0_0 匹配的默认GAP lib,请参阅文档 BT Host Image 中的 GAP Lib的使用方法 以获取更多信息。

BT Host介绍

示例工程使用 bt_host_0_0 中的默认BT Host image,更多信息可参阅 BT Host Image

关于BT Host所支持的蓝牙功能的详细信息,请参阅文件 bin\rtl87x2g\bt_host_image\bt_host_0_0\bt_host_config.h

初始化

当EVB启动并且芯片复位时, main 函数将被调用,它执行以下初始化函数:

int main(void)
{
  board_init();
  le_gap_init(0);
  gap_lib_init();
  app_le_gap_init();
  pwr_mgr_init();
  task_init();
  os_sched_start();

  return 0;
}
void app_le_gap_init(void)
{
    /* Advertising parameters */
    uint8_t  adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND;
    uint8_t  adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC;
    uint8_t  adv_direct_addr[GAP_BD_ADDR_LEN] = {0};
    uint8_t  adv_chann_map = GAP_ADVCHAN_ALL;
    uint8_t  adv_filter_policy = GAP_ADV_FILTER_ANY;
    uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN;
    uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MIN;

    /* Set advertising parameters */
    le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type);
    le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type);
    le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr);
    le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map);
    le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy);
    le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min);
    le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max);
    le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data);
    le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data);
}

广播模式下的设备应使用不可连接广播发送数据。 因此,参数 adv_evt_type 应该配置为以下类型: GAP_ADTYPE_ADV_NONCONN_IND

更多关于LE GAP初始化和启动流程的信息可以查阅 LE Host 中的 GAP参数的初始化

GAP消息处理

任何时候当APP从GAP层接收到GAP消息时,函数 app_handle_gap_msg 会被调用。 更多关于GAP消息的信息可以查阅 LE Host 中的 蓝牙状态消息

void app_handle_gap_msg(T_IO_MSG *p_gap_msg)
{
    T_LE_GAP_MSG gap_msg;
    memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param));

    APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype);
    switch (p_gap_msg->subtype)
    {
    case GAP_MSG_LE_DEV_STATE_CHANGE:
        {
            app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state,
                                     gap_msg.msg_data.gap_dev_state_change.cause);
        }
        break;

    default:
        APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype);
        break;
    }
}

Broadcaster示例工程会在收到 GAP_INIT_STATE_STACK_READY 时调用 le_adv_start() 来启动广播。 如果 le_adv_start() 返回 true ,说明Bluetooth Host已经接收了这个命令并准备执行,当这个命令执行完成后,Bluetooth Host将发送 GAP_ADV_STATE_ADVERTISINGapp_handle_dev_state_evt 。 当Broadcaster示例工程在开发板上运行时, 设备将发送不可连接广播。

void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause)
{
    APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x",
                    new_state.gap_init_state, new_state.gap_adv_state, cause);
    if (gap_dev_state.gap_init_state != new_state.gap_init_state)
    {
        if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY)
        {
            APP_PRINT_INFO0("GAP stack ready");
            /*stack ready*/
            le_adv_start();
        }
    }

    if (gap_dev_state.gap_adv_state != new_state.gap_adv_state)
    {
        if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE)
        {
            APP_PRINT_INFO0("GAP adv stoped");
        }
        else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING)
        {
            APP_PRINT_INFO0("GAP adv start");
        }
    }

    gap_dev_state = new_state;
}

常见问题

  1. 如何修改advertising data参数?

Advertising data定义在数组 adv_data 中, 开发者可以直接修改数组的内容来修改广播数据。

static uint8_t adv_data[] =
{
  /* Flags */
  0x02,             /* length */
  GAP_ADTYPE_FLAGS, /* type="Flags" */
  GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

  /* Local name */
  0x10,
  GAP_ADTYPE_LOCAL_NAME_COMPLETE,
  'B', 'L', 'E', '_', 'B', 'R', 'O', 'A', 'D', 'C', 'A', 'S', 'T', 'E', 'R'
};