这个实例将重点关注广播参数、制造商特定数据以及动态更新广播数据。
广播参数的控制,广播参数放在bt_le_adv_param变量里面。由于此变量需要初始化内容太多,因此使用宏 BT_LE_ADV_PARAM()来帮助初始化
options:用于配置广告选项的特定宏。例如,选择在哪个频道(37、38、39)上投放广告。有 19 个选项可用,可在此处找到。
最小广告间隔:(N * 0.625 毫秒):小于或等于最大广告间隔。N 的允许范围是 32 到 16384,相当于 20 毫秒到 10.24 秒。API 具有用于广告间隔的预定义值。
最大广告间隔:(N * 0.625 毫秒):大于或等于最小广告间隔。N 的允许范围是 32 到 16384,相当于 20 毫秒到 10.24 秒。API 具有用于广告间隔的预定义值。
对等地址:如果使用定向广告则包含。否则,设置为 NULL。
代码实现如下
- 使用自带的LED和BUTTON库,在prj.conf加入如下。
# Button and LED library
CONFIG_DK_LIBRARY=y
2.在main.c加入头文件
#include <dk_buttons_and_leds.h>
3.定义广播参数
static struct bt_le_adv_param *adv_param =
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_NONE,
800,
801,
NULL);
4.定义自定义数据
#define COMPANY_ID_CODE 0x0059
5.定义动态数据存放的变量,这里定义个结构体,方便管理
typedef struct adv_mfg_data {
uint16_t company_code; /* Company Identifier Code. */
uint16_t number_press; /* Number of times Button 1 is pressed*/
} adv_mfg_data_type;
初始化
static adv_mfg_data_type adv_mfg_data = {COMPANY_ID_CODE,0x00};
6.将自定义数据包含到广播包里面
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char *)&adv_mfg_data, sizeof(adv_mfg_data)), // 添加自定义数据
};
7.添加按钮初始化代码,和注册按钮回调函数
static void button_changed(uint32_t button_state, uint32_t has_changed)
{
if (has_changed & button_state & USER_BUTTON) {
adv_mfg_data.number_press += 1;
bt_le_adv_update_data(ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd)); //这里是动态更新广播数据的地方
}
}
static int init_button(void)
{
int err;
err = dk_buttons_init(button_changed);
if (err) {
printk("Cannot init buttons (err: %d)\n", err);
}
return err;
}
8.在main函数调用按钮初始化
static void button_changed(uint32_t button_state, uint32_t has_changed)
{
if (has_changed & button_state & USER_BUTTON) {
adv_mfg_data.number_press += 1;
bt_le_adv_update_data(ad, ARRAY_SIZE(ad),
sd, ARRAY_SIZE(sd));
}
}
在第7步,函数是动态更新广播数据
编译和测试
可以点击数据,选择显示数据的格式
完整代码
开启蓝牙后,建议将栈的空间加大到2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_MAIN_STACK_SIZE=2048