搜索
首页后端开发php教程BLE-NRF51822教程3-sdk程序框架剖析_PHP教程

BLE-NRF51822教程3-sdk程序框架剖析


nordicBLE 技术交流群498676838

本讲为框架介绍,不会牵涉到太多代码细节。

51822的官方SDK其实是没有框架依耐性的。什么叫框架,比如TI的BLE SDK中就有一个操作系统抽象层(OSAL)他是一个轮训的调度。你需要按照他的方式去创建任务等等。

而51822的SDK本质上只是提供了各种调用接口,比如开启初始化协议栈,初始化一些硬件功能模块,开始广播,发起链接等等。这些接口怎么用完全取决于自己。不过一般固件开发都是一些类似的流程各种资源的初始化,51822也不例外。所以sdk中的作为从机的例子main函数都是类似如下的步骤:

以官方的串口BLE 为例:

int main(void)

{

leds_init(); //非必须,只是该例子中用到了

timers_init(); //非必须,只是该例子中用到了

buttons_init(); //非必须,只是该例子中用到了

uart_init(); //非必须,只是该例子中用到了串口

ble_stack_init(); //必须

gap_params_init(); //必须

services_init(); //跟自己创建的服务相关,不同的服务细节不同但大体建立
//过程基本一致,通常在直接使用官方的例子修改一些参数即可

advertising_init(); //广播数据初始化,必须

conn_params_init(); //是情况而定,如果连接后不需要连接参数的协商,该初始化也 //可不要

sec_params_init(); //安全参数初始化,如果没用到配对绑定相关这个也可以不初始化

advertising_start(); //开启广播,必须

// Enter main loop

for (;;)

{

power_manage(); //进入睡眠

}

}

可以看到其实核心必要的只有这5个函数而已。你可以将其他代码全都去掉,只要留下这5个函数设备一样可以运行,手机也能搜到设备并与设备通信。

这种初始化的方式可以说是与我们一般的单片机开发没有区别。

那么初始化之后呢。以前的裸板单片机开发我们就是进入一个while循环执行一些周而复始的事,后面为了降低功耗开始在while(1)循环中加个睡眠代码让没有工作时芯片处于睡眠状态,并依靠中断来唤醒从而处理到来的事物。

而上面的51822的main函数最后也是一个for{}循环,power_manage(); 内部代码其实就是一个睡眠指令。Main函数到这里就已经没了,最后其实就是一个循环睡眠。这里看不到任何任务(task),只有睡眠。那么可想而知,51822的协议栈实现应该是基于”事件唤醒”的,也就是没事的时候睡眠,有事的时候唤醒工作而后继续睡眠。那么那些处理事件的代码都是在哪里的?

那协议栈到底是怎么运作的?

我希望创建一个服务在哪里添加?

手机发送来的数据在哪里?

我怎么发送数据给手机?

下面一一解释这些问题:

协议栈如何运作?

要明白协议栈怎么运作,首先就要理解51822的协议栈是基于100%的事件驱动的。就是说协议栈向app发送的任何数据都是基于事件的。

比如设备收到手机发来的链接请求,或是手机发过来的数据等等。协议栈首先收到这些数据后做一些处理,然后将这些数据(比如链接请求,或是普通数据等)打包成一个结构体,并附上事件ID,比如BLE_GAP_EVT_CONNECTED或BLE_GATTS_EVT_WRITE来分别告诉上层app这个事件结构体代表的事件。

比如BLE_GAP_EVT_CONNECTED代表链接事件,那么这个事件结构体中包含的数据就是连接参数等数据。

而BLE_GATTS_EVT_WRITE代表写事件,那么结构体中的数据就是对端设备(比如手机)写给板子的数据。



比如uart的demo中dispatch派发函数

static void ble_evt_dispatch(ble_evt_t *p_ble_evt)

{

ble_conn_params_on_ble_evt(p_ble_evt);

ble_nus_on_ble_evt(&m_nus, p_ble_evt);

on_ble_evt(p_ble_evt);

}

在任何与BLE相关的事件被协议栈上抛上来给app时,ble_evt_dispatch就会被调用。从而将事件抛给各个服务函数或处理模块,这里是将事件抛给了

连接参数管理处理函数ble_conn_params_on_ble_evt

Uart服务的事件处理函数ble_nus_on_ble_evt (nus为Nordicuart server)

通用的事件处理函数on_ble_evt

不同的事件在事件结构体ble_evt_t中通过id来区别。不同是事件处理函数通常也只是处理自己感情去的事件,我们来看看ble_nus_on_ble_evt事件处理函数的内部

voidble_nus_on_ble_evt(ble_nus_t * p_nus,ble_evt_t * p_ble_evt)

{
if ((p_nus == NULL) || (p_ble_evt == NULL))

{

return;

}

switch (p_ble_evt->header.evt_id)

{

caseBLE_GAP_EVT_CONNECTED:

on_connect(p_nus, p_ble_evt);

break;

caseBLE_GAP_EVT_DISCONNECTED:

on_disconnect(p_nus, p_ble_evt);

break;

caseBLE_GATTS_EVT_WRITE:

on_write(p_nus, p_ble_evt);

break;

default:

// No implementation needed.

break;

}

}

可以看到,uart服务事件处理函数只关心三个事件,链接事件,断开链接事件以及写事件(对端设备发数据过来),不同的事件再针对做不同的,这个就由开发人员自己来实现了。比如对于连接事件通常应该记录下事件结构体中的连接句柄,因为后续的BLE操作基本都要基于连接句柄(可以看做是两个设备通信的信道ID,实际为链路层中的数据接入地址概念)。

PS: 事件是交给dispatch来派发给各个服务以及模块的,对于更底层的事件又是如何交给dispatch函数的过程请参考群公告中的 51822教程-协议栈概述教程。


解决了所谓的事件驱动再来解决:如果希望创建一个服务在哪里添加?

在main函数的初始化过程中有一个services_init();这个函数的内部就是添加服务,添加特征值等代码。

函数内部其实就是注册了一会回调函数nus_data_handler(该函数会在手机发数据给板子时将数据从电脑串口打印出来) 然后再执行真正的初始化函数ble_nus_init。

该函数的内部又会调用sd_ble_gatts_service_add这个协议栈的api接口来添加服务。

后面也会调用sd_ble_gatts_characteristic_add这个协议栈的api接口来添加特征值。

层次关系如下:


也就是说完成一个完整的服务建立函数其实只要sd_ble_gatts_service_add()和sd_ble_gatts_characteristic_add()这两个核心函数。

通常建立服务并不需要自己去从头写过。而是直接赋值官方的这个services_init()函数,然后做一些小改动就可以。比如修改一下uuid, 修改一下读/写属性,多添加一个特征值等。要修改的其实很少。


下面解决最后两个问题:手机发送来的数据在哪里?我怎么发送数据给手机?

要搞清楚这两个问题,先来看一下群里常问的几个与上面相关的问题:



问:

手机发给51822设备的数据在哪个函数里出来的呀,
答:
没有函数
协议栈会抛上来一个事件结构体
收到的数据在结构体中


问:

蓝牙上传函数,与下发函数都是一样的吗?都是服务API函数?
答:
只有上传函数是服务器用来将数据传给客户端的。
下发数据是蓝牙芯片收到数据后,协议栈会拋上来一个有数据的事件结 构体。具体参看示例代码中的dispatch派发程序中各个事件处理函数对各 种事件的数据。

问:

sd_ble_gatts_hvx()这个函数是蓝牙的发送函数,有知道蓝牙的接收函数?
答:
蓝牙没有接收函数,蓝牙的数据接收在底层,接收完后会返回事件给上层的 ble_evt_dispatch分发函数,它将事件分发给各个服务或者事件处理函数。服 务或处理函数会捕获是否存在写事件caseBLE_GATTS_EVT_WRITE:存在就做 相应的处理。收到的数据都在返回的事件结构体里

其实看完这三个问题基本上上面的问题其实已经解决差不多了。作为从设备,BLE的发送数据给手机是有API接口的,就是上面问到的sd_ble_gatts_hvx(),可以通过参数来设置是以通知方式发送还是指示方式发送(通知不需要回复确认,指示需要)。但是手机发过来数据却是没有接收函数,为什么?因为协议栈是基于事件驱动的!所以收到数据后协议栈会给上层app一个写事件(指示对端设备写数据过来了),而写过来的数据时在这个事件结构体中。我们只要提取出来就行了。所以没有接收函数API。


从另一方面也可以解释为什么没有接收数据函数。因为发送数据时”同步的”,是主动调用的,在往想发送数据的时候。但是接收数据时”异步的”,数据可能随时到来,总不来一直调用一个函数然后原地等待数据到来吧,如果数据不来岂不是什么事都干不了了。所以接收是基于事件驱动的。有数据来再转过去处理。

用个图来解释下:



如果还是觉得有点抽象,回到前面看看协议栈运作讲解部分。应该更能体会所谓的事件驱动



www.bkjia.comtruehttp://www.bkjia.com/PHPjc/1068092.htmlTechArticleBLE-NRF51822教程3-sdk程序框架剖析 nordicBLE 技术交流群498676838 本讲为框架介绍,不会牵涉到太多代码细节。 51822的官方SDK其实是没有框架依耐...
声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
如何在 iPhone 和 Android 上关闭蓝色警报如何在 iPhone 和 Android 上关闭蓝色警报Feb 29, 2024 pm 10:10 PM

根据美国司法部的解释,蓝色警报旨在提供关于可能对执法人员构成直接和紧急威胁的个人的重要信息。这种警报的目的是及时通知公众,并让他们了解与这些罪犯相关的潜在危险。通过这种主动的方式,蓝色警报有助于增强社区的安全意识,促使人们采取必要的预防措施以保护自己和周围的人。这种警报系统的建立旨在提高对潜在威胁的警觉性,并加强执法机构与公众之间的沟通,以共尽管这些紧急通知对我们社会至关重要,但有时可能会对日常生活造成干扰,尤其是在午夜或重要活动时收到通知时。为了确保安全,我们建议您保持这些通知功能开启,但如果

在Android中实现轮询的方法是什么?在Android中实现轮询的方法是什么?Sep 21, 2023 pm 08:33 PM

Android中的轮询是一项关键技术,它允许应用程序定期从服务器或数据源检索和更新信息。通过实施轮询,开发人员可以确保实时数据同步并向用户提供最新的内容。它涉及定期向服务器或数据源发送请求并获取最新信息。Android提供了定时器、线程、后台服务等多种机制来高效地完成轮询。这使开发人员能够设计与远程数据源保持同步的响应式动态应用程序。本文探讨了如何在Android中实现轮询。它涵盖了实现此功能所涉及的关键注意事项和步骤。轮询定期检查更新并从服务器或源检索数据的过程在Android中称为轮询。通过

如何在Android中实现按下返回键再次退出的功能?如何在Android中实现按下返回键再次退出的功能?Aug 30, 2023 am 08:05 AM

为了提升用户体验并防止数据或进度丢失,Android应用程序开发者必须避免意外退出。他们可以通过加入“再次按返回退出”功能来实现这一点,该功能要求用户在特定时间内连续按两次返回按钮才能退出应用程序。这种实现显著提升了用户参与度和满意度,确保他们不会意外丢失任何重要信息Thisguideexaminesthepracticalstepstoadd"PressBackAgaintoExit"capabilityinAndroid.Itpresentsasystematicguid

Android逆向中smali复杂类实例分析Android逆向中smali复杂类实例分析May 12, 2023 pm 04:22 PM

1.java复杂类如果有什么地方不懂,请看:JAVA总纲或者构造方法这里贴代码,很简单没有难度。2.smali代码我们要把java代码转为smali代码,可以参考java转smali我们还是分模块来看。2.1第一个模块——信息模块这个模块就是基本信息,说明了类名等,知道就好对分析帮助不大。2.2第二个模块——构造方法我们来一句一句解析,如果有之前解析重复的地方就不再重复了。但是会提供链接。.methodpublicconstructor(Ljava/lang/String;I)V这一句话分为.m

如何在2023年将 WhatsApp 从安卓迁移到 iPhone 15?如何在2023年将 WhatsApp 从安卓迁移到 iPhone 15?Sep 22, 2023 pm 02:37 PM

如何将WhatsApp聊天从Android转移到iPhone?你已经拿到了新的iPhone15,并且你正在从Android跳跃?如果是这种情况,您可能还对将WhatsApp从Android转移到iPhone感到好奇。但是,老实说,这有点棘手,因为Android和iPhone的操作系统不兼容。但不要失去希望。这不是什么不可能完成的任务。让我们在本文中讨论几种将WhatsApp从Android转移到iPhone15的方法。因此,坚持到最后以彻底学习解决方案。如何在不删除数据的情况下将WhatsApp

同样基于linux为什么安卓效率低同样基于linux为什么安卓效率低Mar 15, 2023 pm 07:16 PM

原因:1、安卓系统上设置了一个JAVA虚拟机来支持Java应用程序的运行,而这种虚拟机对硬件的消耗是非常大的;2、手机生产厂商对安卓系统的定制与开发,增加了安卓系统的负担,拖慢其运行速度影响其流畅性;3、应用软件太臃肿,同质化严重,在一定程度上拖慢安卓手机的运行速度。

Android中动态导出dex文件的方法是什么Android中动态导出dex文件的方法是什么May 30, 2023 pm 04:52 PM

1.启动ida端口监听1.1启动Android_server服务1.2端口转发1.3软件进入调试模式2.ida下断2.1attach附加进程2.2断三项2.3选择进程2.4打开Modules搜索artPS:小知识Android4.4版本之前系统函数在libdvm.soAndroid5.0之后系统函数在libart.so2.5打开Openmemory()函数在libart.so中搜索Openmemory函数并且跟进去。PS:小知识一般来说,系统dex都会在这个函数中进行加载,但是会出现一个问题,后

Android APP测试流程和常见问题是什么Android APP测试流程和常见问题是什么May 13, 2023 pm 09:58 PM

1.自动化测试自动化测试主要包括几个部分,UI功能的自动化测试、接口的自动化测试、其他专项的自动化测试。1.1UI功能自动化测试UI功能的自动化测试,也就是大家常说的自动化测试,主要是基于UI界面进行的自动化测试,通过脚本实现UI功能的点击,替代人工进行自动化测试。这个测试的优势在于对高度重复的界面特性功能测试的测试人力进行有效的释放,利用脚本的执行,实现功能的快速高效回归。但这种测试的不足之处也是显而易见的,主要包括维护成本高,易发生误判,兼容性不足等。因为是基于界面操作,界面的稳定程度便成了

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
4 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
3 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!