开发环境:
Ubuntu 18.04 + Zephyr‘s SDK and Tools
硬件平台:
PCA10056 DK (nRF52840)
zephyr-env.sh
。cd ~/git/zephyr/
source ./zephyr-env.sh
有时候会打开多个终端,每个终端都需要 source zephyr-env.sh
, 这样比较繁琐。我们把该命令加入到 zshrc
或者 bashrc
中即可。
cd sample/bluetooth/peripheral
mkdir -p build/nrf52 && cd build/nrf52 # 创建文件夹
cmake -GNinja -DBOARD=nrf52840_pca10056 ../.. # 利用 cmake 自动生成 build 系统。 依赖 CMakeLists.txt ,最后路径是当前目录与 CMakeLists.txt 的相对路径
如果出问题,请在检查:
- 在当前终端运行
source zephyr-env.sh
- 检查路径
../..
是否对
ninja # ninja 或者 make
ninja flash # 烧录代码
使用 nRF connect (Android) 可以观察到
设备名 Zephyr Peripheral Sample Long
复位重启硬件会发现MAC地址在变更。第一次: 44:3A:6B:C6:30:9A
; 第二次: 5C:0A:1D:CE:2D:38
bt_enable(bt_ready) 当初始化完成,调用bt_ready,在bt_ready中进行 service初始化,开启广播。
bt_conn_cb_register 注册连接和断连的回调函数,我们可以在回调函数中处理相关事件。
conn_callbacks = { .connected = connected, .disconnected = disconnected};
static void connected(struct bt_conn *conn, u8_t err){ printk("Connected\n");} static void disconnected(struct bt_conn *conn, u8_t reason){ printk("Disconnected\n");}
bt_conn_auth_cb_register(&auth_cb_display)
在 bt_ready 函数里,可以初始化所需要的 service
, 例如 BAS
和 DIS
或者自定义 service
。
在 prj.conf 中修改设备名
CONFIG_BT_DEVICE_NAME="BLE_Zephyr" # 设置设备名
# CONFIG_BT_DEVICE_NAME_DYNAMIC=y # 注释掉该配置信息,取消动态设备名
在 prj.conf 中修改
# CONFIG_BT_PRIVACY=y # 注释掉该配置信息,取消动态 MAC 地址
广播间隔,可否连接,显示设备名。
默认设备名是放在扫描响应包里。
// 在 bt_ready() 函数上方定义广播参数
#define BT_GAP_ADV_FAST_INT_MIN_3 0x00f0
#define BT_GAP_ADV_FAST_INT_MAX_3 0x00f0
#define BT_LE_ADV_CONN_NAME1 BT_LE_ADV_PARAM( BT_LE_OPT_CONNECTABLE | \
BT_LE_ADV_OPT_USE_NAME, \
BT_GAP_ADV_FAST_INT_MIN_2, \ //0x00a0=160 160*0.625=100ms
BT_GAP_ADV_FAST_INT_MAX_2) //0x00f0=240 240*0.625=150ms
// 在 bt_ready() 函数中修改参数
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME1, ad, ARRAY_SIZE(ad), NULL, 0);
// ad advertising data
// sd scan response data
编译 & 烧录
ninja
ninja flash
可以验证广播连接间隔变成了 150ms 左右。
static struct bt_gatt_attr vnd_attrs[] = {
BT_GATT_PRIMARY_SERVICE(&vnd_uuid),
BT_GATT_CHARACTERISTIC(&vnd_uuid.uuid,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE |
BT_GATT_CHRC_INDICATE,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE,
read_vnd, write_vnd, vnd_value),
BT_GATT_CCC(vnd_ccc_cfg, vnd_ccc_cfg_changed),
}
static struct bt_gatt_service vnd_svc = BT_GATT_SERVICE(vnd_attrs);
bt_gatt_service_register(&vnd_svc);
必须有该项
/* Custom Service Variables */
static struct bt_uuid_128 vnd_uuid = BT_UUID_INIT_128(
0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
BT_GATT_PRIMARY_SERVICE(&vnd_uuid)
如果有多个特性,需要多个UUID
static struct bt_uuid_128 vnd_enc_uuid = BT_UUID_INIT_128(
0xf1, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
0x78, 0x56, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12);
ccc
启动。
static struct bt_gatt_ccc_cfg blvl_ccc_cfg[BT_GATT_CCC_MAX] = {};
static void blvl_ccc_cfg_chaged(const struct bt_gatt_attr *attr, u16_t value){
simulate_blvl = (value == BT_GATT_CCC_NOTIFY) ? 1 : 0;
}
BT_GATT_CCC(blvl_ccc_cfg, blvl_ccc_cfg_changed);
// process
void bas_nofity()
{
if (!simulate_blvl) {
return;
}
battery--;
if (!battery) {
battery = 0;
}
// attrs[0] = primary service
bt_gatt_notify(NULL, &attrs[1], &battery, sizeof(battery));
}
iOS 配对有问题,暂时不使用