具体内容直接参考《nRF52832开发指南》
本文仅对关键内容和容易搞错的内容进行描述。
广播事件
扫描事件
连接事件
从机框架
- 日志配置和初始化log_init,具体参考手册和示例程序;
- APP定时器初始化timers_init,具体参考手册和示例程序;
- led指示灯初始化leds_init,可选,具体参考手册和示例程序;
- 初始化和运行电源管理,初始化power_management_init,运行nrf_pwr_mgmt_run,具体参考手册和示例程序;
- BLE协议栈初始化ble_stack_init,这里面注册了BLE事件处理函数句柄ble_evt_handler,这里涉及到两个操作需要我们确定下,第一个就是配置低频时钟nrf_sdh_enable_request,再就是在工程Target界面中为协议栈和应用程序分配合适的内存,具体参考手册和示例程序;
- GAP初始化,gap_params_init,这里需要注意的是,设置设备名称sd_ble_gap_device_name_set,然后就是理解首选连接参数,具体参考手册和示例程序;
- GATT初始化gatt_init,具体参考手册和示例程序;
- 广播初始化advertising_init,这里需要注册一个广播事件处理函数on_adv_evt,具体参考手册和示例程序;
- 服务初始化services_init,可以在这里面初始化串口透传服务,设置串口透传事件回调函数,具体参考手册和示例程序;
- 连接参数协商模块初始化conn_params_init,这里面有一个连接参数协商模块事件处理函数on_conn_params_evt,用来处理协商成功或者失败,具体参考手册和示例程序;
- 启动广播advertising_start,该函数所用的模式必须和广播初始化中设置的广播模式一样,具体参考手册和示例程序;
SoftDevice,指的是NORDIC softDevice 蓝⽛协议栈;
日志打印
参考视频:
第22讲:(蓝牙从机工程框架篇)协议栈下log输出_哔哩哔哩_bilibili
选择日志的输出终端
STM32中一般使用printf进行打印,此时,会占用一个串口。
日志的相关设置,在sdk_config.h文件中,找到任意一个c文件,点击加号展开,即可找到该头文件(以下为头文件的向导模式展示)。
使用RTT输出日志时,可以节省一个串口,使用JLINK本身,既能实现烧录,也能输出日志。
注意:RTT和串口可以同时使能输出。
LOG有个总开关
5种日志级别
我们实际开发时,可根据情况分别调用这几个函数来实现不同信息的输出。
我们在程序里,不同的地方调用不同的日志函数来输出日志,但是并不是所有的日志都会打印出来,哪些会打印出来呢?这就由默认的日志级别来确定:
如果选择了Off,则不会打印任何日志;
如果选择了Error,则只会打印出NRF_LOG_ERROR函数所输出的内容;
如果选择了Warning,则只会打印出NRF_LOG_WARNING函数所输出的内容;
如果选择了Info,则只会打印出NRF_LOG_INFO函数所输出的内容;
如果选择了Debug,则会打印出所有LOG函数输出的内容。
通常,默认选择Info级别。
Log配置(RTT作为输出终端)
启动RTT
配置RTT
信息显示
上述选择完成后,点击OK,即可进入主界面
RTT常用操作补充
清除终端显示
保存日志
注意,以上日志操作都是NORDIC帮我们实现的,并不属于BLE协议的一部分。
自定义串口服务
具体参考手册第七章:《实现一个自定义的profile》
一上来就有个疑惑,这是从机直接发数据给主机,怎么还有串口的事呢?
使用步骤如下:
生成自定义UUID,可使用工具,网址Online UUID Generator Tool,并用数组保存起来,保存时注意字节序,是反着放的;
明确需求;
勾选串口透传服务
根据上面说的框架步骤,初始化和配置时设置各项参数;
在扫描响应中加入串口透传服务的UUID
相关代码
后续更多流程自行查阅手册和示例代码即可。
解惑:
这里的串口透传服务和特征,只是在有串口透传场景下的一种方式,其实,服务和特征名不一定要取TX和RX,不要被取名误导,关键是服务和特征的UUID唯一识别码,名称没那么重要。不是说这样取名就表示蓝牙之间传输使用的是串口,想想都不大可能。
这里更多的含义是:串口透传服务实现了蓝牙的串口收发数据,然后可以直接取数据并通过蓝牙收发,从而实现透传,这一块nordic已经写好了,而不用我们自己去写代码来实现。
如果只是主从机之间,根本就用不到串口透传。一般都是涉及到三方,其中有一侧是通过串口传输数据,然后有个中间方在牵桥搭线,这种情况下,可以在中间方芯片上使用透传。
又有个疑惑,如果不使用透传,那么数据是如何从蓝牙从机发送给主机的呢?在有其他MCU的场景下,MCU直接通过串口发送数据给从机,从机就会自动透传给主机;nRF52832如果只有主从机,连接后是调用什么来发送数据呢?难道就是从机打开发射模块和通知主机打开接收模块?数据就能发送了?而我们使用串口透传服务,难道如果没有用到串口,也就当做要发送的数据是从串口来的?然后调用透传服务函数,就能自动将数据发送出去了?
我觉得这应该就是物理层和链路层的事情,发送放和接收方各自打开发射模块和接收模块。
长包传输
设置支持的数量
MTU长度赋值给GATT实例
GATT事件回调函数
补充
主机界面示例:
打开对应的主机APP,nordic的nRF Connect,然后连接,可以看到有如下主机界面:
可以看到有一个订阅的服务,该服务还包括两个特征。
然后还有两个GAP服务和GATT服务是强制包含的,也就是图中的Generic Access 和 Generic Arrribute。
这两个一般是在协议栈里面实现的,不需要用户实现。
几个术语
经典蓝牙BR/EDR
LE:蓝牙低功耗
蓝牙断开的问题
蓝牙如能被发现,能连上,并且查看数据是对的,说明设置是没问题。
之后过程中又断开,通常是连接超时,可能是距离太远了。
可以在连接断开的事件中打印出断开连接的原因
错误编号所在处BLE_HCI_STATUS_CODES Bluetooth status codes
比如0x08连接超时。
断开后,nordic协议栈会使得从机重新进入广播。
为什么会自动广播?
NRF_SDH_BLE_OBSERVER——ble_advertising_on_ble_evt中可以查看
在广播或者扫描响应中放入数据
如果希望在广播或者扫描响应里放入某些数据,可直接参考手册的第四章《全面掌握广播》
我们要记住的是广播数据的组成:
广播或者扫描响应的数据报文一共有37个字节,前6个字节是广播设备的地址,所以,只有31个字节可以携带数据,这些数据由一个一个的AD Structure构成。
有哪些广播数据的类型?
AD Type的定义在程序的ble_gap.h头文件中,可自行查看。