NRF52832主机开发速成——一主多从模式(非解析官方例程)

一、前言

因项目需求,需要一个蓝牙设备当主机,去控制其它从机的蓝牙设备。因为想减少开发周期,最先方案是采用信驰达的ND04模块,结果特么的周期反而大大增加了,这里吐槽一下,本来第一批测试模块调试得好好的,结果第二批过来了之后,就搜索也搜索不到从机,然后在后面测试中发现第一批还会出现模块死机的状态,找他们解决硬生生给我拖了几星期,最后让我寄回去他们重新烧固件(手动微笑。最后实在怕了,这种使用别人模块开发产品实在不可取,不确定因素太多了,后面实在越想越气,准备自己着手开发固件,毕竟NRF52832现在网上资料啥的也一堆了,好好啃啃文档应该问题不大。然而还是折腾了些时间,网上的教程大多都是对官方例程的解读,或是基于其更改一下,和自己想要的还是差得太多,并且问题也是接连不断。为此写个博客记录一下思路和问题,技术有限,若有错误还请指出订正。

二、开发准备

先是NRF52832开发板一个,这里推荐E73-2G4M04S1B的测试套餐 就是引脚已经引出来的开发板 E73-2G4M04S1B-E73|nRF52832|2.4G|SOC模块|射频芯片|成都亿佰特电子科技有限公司 (ebyte.com)

然后就是下载设备J-LINK V8以上的最好

最后就是驱动和编译环境安装那些了 具体可以去上面那个链接里面找资料

这边插入遇到的一个问题 就是安装完J-LINK 怎么都没法烧写程序 线也没接错 最后是由于SN码为 -1 引起的 更改一下就正常了

三、开发过程

接触新芯片,个人习惯先从例程看看工程结构,大致理一下整个程序的运行过程,例程(nRF5_SDK_15.2.0_9412b96\examples\ble_central\ble_app_multilink_central)比较接近我的需求,大致看了里面程序,发现里面大多都是由底层蓝牙协议栈通知事件到指定回调函数,然后对事件类型和参数进行分析,在后面的开发过程里,测试得出,每一个蓝牙事件基本都会调用于初始化蓝牙协议栈时候传参进去的回调函数ble_evt_handler 很多主要的处理都是在该函数中

尽管后面蓝牙扫描还是发现服务初始化的时候也传参进去了相应的回调函数,有些事件还是会在两边都触发...所以事件处理在其中一个回调函数处理就可以了

然后在main主函数里,只有一个检查log输出和电源管理的东东,其它的业务逻辑基本都在回调函数和中断那边

大概了解了整个程序的结构,可以得出整个主机应该有以下几个流程:

初始化相关模块(蓝牙协议栈、扫描模块、发现服务模块、GATT模块)===>扫描设备===>连接设备===>发现对应的服务===>获取特征句柄===>使能CCCD===>发送数据或处理通知(从机发过来的数据)

红色部分是和一个从机建立通信缺一不可的过程,开发过程中因为少了个使能CCCD的过程 导致读取数据不完整 后面再细看一遍例程才发现...

注:启用哪些模块 则需要将sdk_config.h文件里对应的宏定义开启 不然会编译出错

1、初始化

这边可以先定义两个参数结构 后面连接设备和扫描设备需要用到

初始化全部模块

里面各个模块的初始化函数详见官方例程 这边就不贴出来了,基本没啥改动。

唯一要注意的是,我这边并没有使用例程的客户端初始化,也就是ble_lbs_c.c文件里的ble_lbs_c_init

它那个程序看起来脑壳都疼,就几个主要的参数和亮个灯非得搞一个那么复杂的结构体进行保存(不过可能是因为为了适应不同服务UUID的从机的原因)

所以我这边将例程ble_lbs_c.c的初始化操作里的注册服务放到了发现服务模块初始化函数里

在这里进行服务的UUID注册 不注册的话后面发现不了服务的

注:这边uuid定义的时候注意不能反了 然后12、13位为对应的16-bit UUID 也就是ble_uuid_t结构体里的uuid

2、扫描

扫描初始化操作如下,这边没有设置任何过滤

然后扫描回调函数

这边的神奇之处就是扫描收到的广播不会往这边回调,而且往ble_evt_handler里

处理广播数据 过滤掉其它广播以及没有名称的蓝牙设备

将其添加到设备列表,在扫描参数那边,设置了10秒扫描超时 故10后会触发扫描回调函数里的NRF_BLE_SCAN_EVT_SCAN_TIMEOUT事件,以及ble_evt_handler里的BLE_GAP_EVT_TIMEOUT事件

这边我仅在扫描回调里处理,也就是输出扫描到的设备信息到串口,测试结果如下:

可以看到扫描时间差不多为10s 超时后打印扫描到的设备信息

3、连接设备

扫描到设备之后,就可以根据扫描到的信息对其进行连接,连接函数如下

其主要是调用 sd_ble_gap_connect(ble_gap_addr_t const *p_peer_addr,ble_gap_scan_params_t const *p_scan_params,ble_gap_conn_params_t const *p_conn_params,uint8_t conn_cfg_tag) 函数

p_peer_addr:为扫描设备时获取到的设备地址对象

p_scan_params:扫描参数结构数据

p_conn_params:连接参数结构数据

conn_cfg_tag:连接标签

注:如果两个连接接得太快的话 会返回NRF_ERROR_INVALID_STATE(8)错误,这是因为前一个连接指令还未处理完毕,如果前一个连接一直连不上,则会一直返回该值,这个在我尝试连接那些不知名的蓝牙设备时出现过,想过使用断开0XFFFE句柄来取消连接,并没有任何效果,目前只能通过主机判断是否进入该状态来重启模块解决了。

当设备连接上之后,会触发回调函数ble_evt_handler里的BLE_GAP_EVT_CONNECTED事件

打印连接上设备的最新状态并开始发现从机相关的服务,一旦发现就会触发服务发现回调函数 如果事件类型为BLE_DB_DISCOVERY_COMPLETE说明服务已经发现完毕,开始获取特征值 并使能CCCD

测试:

连接速度还是可以的

4、使能CCCD

使能CCCD就是往该从机的CCCD句柄写入某个值 使能为0x0001 关闭为0X0000

5、发送数据与接收通知

发送数据也就是往该从机的写入句柄写入数据

主机接收到从机通知之后 会触发回调函数ble_evt_handler里的BLE_GATTC_EVT_HVX事件 在这里进行数据读取并返回给串口

测试:

数据发送与接收完全OK

注:在官方例程里,当收到BLE_GATTC_EVT_HVX事件时,它是调用了sd_ble_gattc_read函数对通知的数据进行读取,读取完成后触发BLE_GATTC_EVT_READ_RSP事件,刚开始我也是采用这种方式,后面发现,当两个通知接得特别近的时候,会出现前一个包丢失的现象...然后发现在BLE_GATTC_EVT_HVX事件的回调参数里 就有着该通知的数据了,完全没必要多此一举(可能也有需要那么做的理由,英语水平有限,官方文档实在有点难啃...以后有时间了再看看吧)

三、结束收工

主要功能出来了,其它串口、看门狗、错误复位等功能照着文档来基本没啥大问题,可以开始画板打样,开始下一步了。

 

 

 

 

 

 

  • 12
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值