当前位置: 首页 > news >正文

Nordic SoftDevice蓝牙主机操作流程

Nordic SoftDevice蓝牙主机操作流程


整理了一下nordic的nus client 主机例程。
在这里插入图片描述

NRF_SDH_BLE_OBSERVER 宏介绍

  • 这个宏可以设置多个BLE事件的回调函数,并按设置的优先级依次执行。这么一来,就可以将扫描,广播,连接,服务发现,读写等蓝牙事件的处理分到多个函数中去处理。
  • 比如,在mian.c里会调用NRF_BLE_SCAN_DEF(m_scan)来使能扫描功能,实际上用的是NRF_SDH_BLE_OBSERVER(_name ## _ble_obs, NRF_BLE_SCAN_OBSERVER_PRIO,nrf_ble_scan_on_ble_evt, &_name),也就是之后所有的ble事件都会来到nrf_ble_scan_on_ble_evt函数,这个函数里面只针对扫描相关的事件进行处理,然后再调用用户在scan_init时注册的回调函数来做所需要的逻辑。
  • 也就是说,ble事件的发生其实会调用很多回调:
    1.ble事件 —> 系统定义好的扫描事件回调 —> 针对特定ble事件,调用用户在mian.c编写的回调实现逻辑
    2.ble事件 —> 系统定义好的扫描服务发现回调 —> 针对特定ble事件,调用用户在mian.c编写的回调实现逻辑
    3.ble事件 —> nus服务里定义好的回调 —> 针对特定ble事件,转为nus事件,再调用用户在mian.c编写的回调实现逻辑
    4.ble事件 —> 由于main.c的stack_init函数里也有一句NRF_SDH_BLE_OBSERVER,所以ble事件也会来到main.c的ble_evt_handler \
  • 在nus的例程中,有4个具体的实例,都在mian.c开头都进行了DEF的宏操作,也就是注册了一个默认的回调,ble事件是先到默认回调,再到用户在各种init函数中设置的回调函数的。
  • 使用这种叫做观测者模式的方法,可以将众多ble事件分发到具体的回调函数中去处理,而且回调函数可以分散写在多个文件当中,减少了耦合程度。

nus服务实例

  • nus实例:m_ble_nus_c
  • nus初始化:void nus_c_init(void),里面设置了nus服务的用户回调函数(写在mian.c的那个)。实际上,在nus的服务文件里面调用了NRF_SDH_BLE_OBSERVER宏进行观察者注册,发生ble事件时,首先由观察者分发到nus服务回调,里面将ble事件转换了成nus事件,再调用mian.c的用户服务回调。通过这种方式,可以很方便的复用nus这个模块,并且用户只需要对转换后的nus事件进行处理即可,不再需要对ble的读和写和通知事件进行区分。
  • nus服务的用户回调函数:ble_nus_c_evt_handler(ble_nus_c_t * p_ble_nus_c, ble_nus_c_evt_t const * p_ble_nus_evt);

scan实例

  • 扫描实例:m_scan
  • 扫描初始化,scan_init(void),设置扫描参数,使能滤波器,找到就连接,这里还设置了扫描的用户回调函数
  • 开始扫描,scan_start(void);
  • 扫描的用户回调函数:scan_evt_handler(scan_evt_t const * p_scan_evt);

    NRF_BLE_SCAN_EVT_CONNECTING_ERROR:报错

    NRF_BLE_SCAN_EVT_CONNECTED:打印连接MAC地址

    NRF_BLE_SCAN_EVT_SCAN_TIMEOUT:重新扫描

gatt实例

  • gatt实例:m_gatt
  • gatt队列:m_ble_gatt_queue
  • gatt初始化:设置MTU,设置gatt层的用户回调:gatt_init(void)
  • gatt层的用户回调:gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)

    NRF_BLE_GATT_EVT_ATT_MTU_UPDATED:调整MTU

服务搜索实例

  • 搜索实例:m_db_disc
  • db_discovery_init(void),这个函数设置了服务发现的用户回调函数,当连接成功后会调用ble_db_discovery_start进行服务发现,服务发现完成后调用用户回调函数
  • 服务发现用户回调函数:db_disc_handler(ble_db_discovery_evt_t * p_evt);这里面就的调用了ble_nus_c_on_db_disc_evt(&m_ble_nus_c, p_evt),这个是具体服务的函数,里面会去判断当前设备有无这个服务,然后调用用户的服务回调。

协议栈初始化

  • 协议栈初始化,ble_stack_init(void); 主要是时钟配置、使能协议栈。这个函数会打印出使用的RAM空间,需要在keil进行相应的配置。最后,调用了NRF_SDH_BLE_OBSERVER宏进行注册观察者,有ble事件发生时调用相应的回调函数。
  • 蓝牙事件回调函数,各种事件的处理:ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    BLE_GAP_EVT_CONNECTED:连接事件,调用ble_db_discovery_start函数,开始搜索服务
    BLE_GAP_EVT_DISCONNECTED:断开连接事件,打印LOG
    BLE_GAP_EVT_TIMEOUT:打印超时LOG
    BLE_GAP_EVT_SEC_PARAMS_REQUEST:
    BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:连接参数更新应答
    BLE_GAP_EVT_PHY_UPDATE_REQUEST:PHY更新应答
    BLE_GATTC_EVT_TIMEOUT:客户端超时,主动断开连接
    BLE_GATTS_EVT_TIMEOUT:服务端超时,主动断开连接

串口打印

  • ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len);
  • uart_event_handle(app_uart_evt_t * p_event);
  • void uart_init(void);

错误处理

  • assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name);
  • nus_error_handler(uint32_t nrf_error);

关闭电源

  • shutdown_handler(nrf_pwr_mgmt_evt_t event);

板子相关函数,主要是指示灯

  • 按键的中断函数:bsp_event_handler(bsp_event_t event)
  • 按键和指示灯初始化:buttons_leds_init(void)

以下函数略

  • 定时器初始化:timer_init(void)
  • 调试器打印初始化:log_init(void);
  • 能量管理器初始化:power_management_init(;void);
  • 这个不知道是啥:idle_state_handle(void);

流程整理,整体是事件驱动流转的

  • 初始化,开始扫描
  • 发现要连接的目标,触发BLE_GAP_EVT_ADV_REPORT事件,调用on_adv_report进行分析,如果是要连接的设备则进行连接。也可以通过设置相关的filter,一旦发现需要的目标则自动连接。
  • 如果连接成功,触发BLE_GAP_EVT_CONNECTED,调用ble_db_discovery_start寻找gatt层的服务。
  • 等待服务发现完成触发回调,进入到具体服务(比如nus)的处理过程,主要是判断有无相应的svc和char,然后转换成具体服务的一个事件,调用mian.c文件中写的具体服务的回调。
  • main.c中的用户服务回调进行订阅或者读写
  • 触发蓝牙读写事件,进入到具体服务的回调函数中进行初步处理,然后转为具体服务的事件,再调用mian.c文件中写的用户服务回调,如此往复。

http://www.mrgr.cn/news/68658.html

相关文章:

  • Qt多边形填充/不填充绘制
  • 【客观理性深入讨论国产中间件及数据库-科创基础软件】
  • 机器学习与深度学习-1-线性回归从零开始实现
  • MySQL存储目录与配置文件(ubunto下)
  • 【LGBM】LightGBM sklearn API超参数解释与使用方法(优化)
  • 大数据新视界 -- 大数据大厂之经典案例解析:电商企业如何靠 Impala性能优化逆袭(上)(9/30)
  • 管道(Pipes)、过滤器(Filters)和拦截器(Interceptors)
  • 深度学习:预训练(Pre-training详解
  • sublime Text的提取查找结果功能
  • 超分辨重建——复现SwinIR网络推理测试(详细图文教程)
  • 云上拼团GO指南——腾讯云博客部署案例,双11欢乐GO
  • Swagger的介绍和使用方式+常用注解
  • 运放进阶篇-多种波形可调信号发生器-产生方波-三角波-正弦波
  • 使用jmeter查询项目数据库信息,保存至本地txt或excel文件1108
  • 【C++】std::cout与std::cin缓冲区
  • 基于微信小程序的电子购物系统的设计与实现(lw+演示+源码+运行)
  • 第二篇-进阶-第十四章-上传与下载
  • 指针的运用
  • 数据库基础(9) . DML-多表操作
  • C++11的简介
  • 【go从零单排】error错误处理及封装
  • 电脑Windows藏着的高手——WMIC命令
  • MySQL数据库基础(一) MySQL安装及数据类型
  • 电商企业店云账户提现探析
  • 【Ant.design pro】 formRef 用法
  • C++ 二分法