硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1146|回复: 1
收起左侧

[技术讨论] zephyrBluetooth协议栈基于bl602的初体验

[复制链接]

102

主题

573

回帖

894

积分

金牌会员

积分
894
QQ
发表于 2024-10-30 10:15:04 | 显示全部楼层 |阅读模式
本帖最后由 会飞的猪_2020 于 2024-10-30 10:47 编辑

测试用的开发板:某宝链接
测试的例程: bl602_demo.tar.gz.rar (19.35 MB, 下载次数: 0)
固件: bl602_demo.bin (347.19 KB, 下载次数: 0)
nordic教程:nordic蓝牙基础教程1
zephyr github仓库地址:zephyr/bluetooth
nordic connect sdk仓库地址:nordic/bluetooth
zephyr api:api

bl602的蓝牙sdk和zephyr的蓝牙sdk一模一样,就是可能版本有些老,部分功能,宏定义有缺失。
直接把nordic教程里的代码抄过来会发现有的函数没定义,然后查看nordic connect sdk把缺少的补全之就能实现教程里的效果了。

在教程里建立了一个公开的LED按钮服务(LED Button Service),可以通过智能手机去控制开发板上的小灯亮灭。
实验结果如下(我用串口打印表示小灯亮灭,没有实际接小灯):
Snipaste_2024-10-30_10-16-38.png Snipaste_2024-10-30_10-16-27.png Snipaste_2024-10-30_10-14-35.png

这里的gatt serv注册方式有点复杂。一开始我没找到显示调用的地方。
后来在gatt初始化的源码里找到这样一个宏定义:
Snipaste_2024-10-30_10-20-39.png
[C] 纯文本查看 复制代码
/*
 * Itterator for structure instances gathered by Z_STRUCT_SECTION_ITERABLE().
 * The linker must provide a _<struct_type>_list_start symbol and a
 * _<struct_type>_list_end symbol to mark the start and the end of the
 * list of struct objects to iterate over.
 */
#define Z_STRUCT_SECTION_FOREACH(struct_type, iterator) \
        extern struct struct_type _CONCAT(_##struct_type, _list_start)[]; \
        extern struct struct_type _CONCAT(_##struct_type, _list_end)[]; \
        for (struct struct_type *iterator = \
                        _CONCAT(_##struct_type, _list_start); \
             ({ __ASSERT(iterator <= _CONCAT(_##struct_type, _list_end), \
                         "unexpected list end location"); \
                iterator < _CONCAT(_##struct_type, _list_end); }); \
             iterator++)

#endif /* ZEPHYR_INCLUDE_TOOLCHAIN_COMMON_H_ */


这种格式的代码看这个有点眼熟,于是在map里面搜索了下面这个变量。
[C] 纯文本查看 复制代码
_list_start

Snipaste_2024-10-30_10-24-46.png

看到这里有恍然大悟了。在应用程序里定义了lbs_svc这个gatt的结构体之后,的确没有去调用它。
它是被放到._bt_gatt_service_static.static.这个section里面,而在这个段的前面是_bt_gatt_service_static_list_start,后面是_bt_gatt_service_static_list_end。
于是不需要显示的被调用,在gatt_init的时候,自己会通过Z_STRUCT_SECTION_FOREACH这个宏定义,去搜索并且自己调用它。


所以在应用程序里面只需要把这个service定义就行了:
[C] 纯文本查看 复制代码
BT_GATT_SERVICE_DEFINE(lbs_svc,
BT_GATT_PRIMARY_SERVICE(BT_UUID_LBS),
#ifdef CONFIG_BT_LBS_POLL_BUTTON
	BT_GATT_CHARACTERISTIC(BT_UUID_LBS_BUTTON,
			       BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
			       BT_GATT_PERM_READ, read_button, NULL,
			       &button_state),
#else
	BT_GATT_CHARACTERISTIC(BT_UUID_LBS_BUTTON,
			       BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
			       BT_GATT_PERM_READ, NULL, NULL, NULL),
#endif
	BT_GATT_CCC(lbslc_ccc_cfg_changed,
		    BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
	BT_GATT_CHARACTERISTIC(BT_UUID_LBS_LED,
			       BT_GATT_CHRC_WRITE,
			       BT_GATT_PERM_WRITE,
			       NULL, write_led, NULL),
);


这些宏的含义,可以查看zephyr的API得知。
它就是构建了一个UUID为BT_UUID_LBS的服务(00001523-1212-efde-1523-785feabcd123)
这个服务下面有两个CHARACTERISTIC,一个是按钮的,一个是小灯的。
(我没有实现按钮,因为我的开发板上没有按钮)


如果你对蓝牙的service有了解的话,可以通过命名猜出这个宏里面的内容的含义。
关于这部分的基础概念,也可以通过阅读nordic的教程获取。
它的结构如下所示,一个profile有多个service,一个service可以有多个characteristic。
Snipaste_2024-10-30_10-44-11.png

知道了这个之后,看BT_GATT_SERVICE_DEFINE这个宏的结构,就和图片里的表示类似了。



更多详细的内容就不加赘述了,可以自行参考nordic的教程以及翻阅代码去了解。





回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117513
QQ
发表于 2024-10-30 10:58:07 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 09:10 , Processed in 0.049448 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表