开发你的第一个BLE应用程序—Blinky
本文将基于Nordic nRF5 SDK开发我们的第一个BLE应用程序——Blinky(类似跑马灯小程序),哪怕你之前没有任何BLE开发经验,也不用担心,只要跟着文中所述步骤,你就可以一步步搭建自己的第一个BLE应用程序。通过这个Blinky程序的搭建,你将体会到BLE的一些基本概念,对BLE将会有一个非常直观的认识,为后续自己的BLE应用程序开发打下一个坚实的基础。
如果你已经有一些BLE应用开发经验,只是对Nordic产品开发不熟,那么建议你可以直接去阅读下一篇文章:手把手教你开发BLE数据透传应用程序
下文所述的代码工程我已经将其上传到百度云盘中,有需要的同学可以到如下链接下载:
- 链接: https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog 密码: y8fb
1. 开发准备
1) nRF52或者nRF51开发板1块。请参考“Nordic nRF51/nRF52开发流程说明”,购买相应开发板(DK)。
2) 开发环境搭建。简述如下(详细说明请参考“Nordic nRF51/nRF52开发环境搭建”):
- 安装Keil5 MDK
- 安装SDK。SDK下载链接:https://www.nordicsemi.com/Software-and-Tools/Software/nRF5-SDK/Download#infotabs。如果你开发的是nRF52系列,请选择最新版SDK(当前是SDK15.3.0);如果你开发的是nRF51系列,请下载nRF5 SDK12.3.0(nRF51最高SDK版本只能到12.3.0,后续SDK就不再支持nRF51了)
- 安装ARM CMSIS4.5.0,下载链接:https://github.com/ARM-software/CMSIS/releases/download/v4.5.0/ARM.CMSIS.4.5.0.pack。
- 安装Keil5 Device Family Pack,下载链接:https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-MDK/Download#infotabs,请选择“Pack,3-clause BSD license”
- 安装nRF5 Command Line Tools,下载链接(Windows版):https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF5-Command-Line-Tools/Download#infotabs。
- 安装安卓版或者iOS版nRF connect。iOS版nRF connect请到苹果app store下载,搜索“nRF”即可以找到。安卓版nRF connect可以到Nordic Github官网上下载,下载链接为:https://github.com/NordicSemiconductor/Android-nRF-Connect/releases
- 安装PC版nRF connect或者nRFgo studio。PC版nRF connect下载链接(Windows版):https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Connect-for-desktop/Download#infotabs。
注:如果你使用的是Linux系统/Mac系统,或者你使用的不是Keil5-MDK,请参考“Nordic nRF51/nRF52开发环境搭建”来搭建你的开发环境。
2. 运行Blinky程序
请按照如下步骤运行SDK自带的Blinky程序
1) 确认自己的芯片型号或者开发板。如果采用Nordic官方开发板的话,芯片型号和开发板编号对应关系如下:
- nRF52832和nRF52810对应开发板编号为PCA10040。虽然52832和52810共用同一块开发板,但是他们在SDK中的项目编号是不一样的,52832对应PCA10040目录,52810对应PCA10040e目录,由于52810和52832 PIN to PIN兼容,软件也是完全兼容的,因此SDK很多项目只有PCA10040的目录,而没有PCA10040e目录,此时需要你自己来建立PCA10040e对应的目录和工程,具体说明可参考:https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Fnrf52810_user_guide.html。
- nRF52840和nRF52811对应开发板编号为PCA10056。虽然52840和52811共用同一块开发板,但是他们在SDK中的项目编号是不一样的,52840对应PCA10056目录,52811对应PCA10056e目录,由于52811和52840 PIN to PIN兼容,软件也是完全兼容的,因此SDK很多项目只有PCA10056的目录,而没有PCA10056e目录,此时需要你自己来建立PCA10056e对应的目录和工程,具体说明可参考:https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Fnrf52811_user_guide.html&cp=5_1_5_1。
- nRF52840 dongle编号为PCA10059
- nRF51系列对应开发板编号为PCA10028
这里我会以nRF52832开发板PCA10040为例阐述整个开发过程,其他开发板与之类似,大家自己可以举一反三来开始自己的开发之旅。
2) 将开发板与PC机通过USB线相连,同时打开开发板电源(将左下角的拨位开关打到“ON”位置),打开桌面版nRF Connect,选择启动“Programmer”应用,由于驱动之前已经安装好了,设备可以立即识别成功。执行“Erase all”操作,以擦除芯片原始内容。
3) 打开SDK中的Blinky程序。对于blinky程序,如果是52832开发板,请打开:nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\ble_app_blinky\pca10040\s132\arm5_no_packs;如果是51822开发板,请打开:nRF5_SDK_12.3.0_d7731ad\examples\ble_peripheral\experimental_ble_app_blinky\pca10028\s130\arm5_no_packs
后续将以52832开发板为例来阐述,51822与之类似就不再阐述了。
注:Nordic SDK例程目录结构为:SDK版本/ examples /协议角色/例子名称/开发板型号/协议栈型号/工具链类型/具体工程,比如下面例子:
Nordic每一个例子都支持5种工具链:Keil5/Keil4/IAR/GCC/SES,如下所示:
4) 编译上面的blinky程序。如果你已经按照之前的说明配置好了开发环境,那么这里编译是不会报任何错的。(如果你遇到了编译错误,请重新按照前面说明去搭建你的开发环境,不要怀疑SDK例子代码有问题哦)
5) 程序下载。程序下载包括2步:先下载softdevice,再下载应用。Softdevice是Nordic蓝牙协议栈的名称,整个开发过程中只需下载一次。应用就是我们这里的blinky程序。
- 蓝牙协议栈下载(整个开发周期只下载一次)。在Keil ‘select target’下拉列表中,默认选择的是Keil工程对应的Target,即‘nrf52832_xxaa’。但我们还可以选择另一个target ‘flash_s132_nrf52_6.1.1_softdevice’,即softdevice对应的target,然后点击“下载download”(不需要编译哦!),此时会把softdevice下载到开发板中。
- 应用下载。重新选择Target:‘nrf52832_xxaa’,点击“下载Download”,此时会把Blinky程序下载到开发板中。此时开发板的LED1常亮,表示程序运行正常。
6) 打开手机蓝牙和手机版nRF connect。在nRF connect中,你将看到一个广播设备:Nordic_Blinky,这个就是我们的开发板。
7) 连接设备。点击“CONNECT”,手机将与设备建立连接,并开始服务发现过程,连接成功后,LED1熄灭,LED2点亮,最后将得到如下界面。
由上图可见,Blinky程序包含三个service:Generic Access(GAP),Generic Attribute(GATT),以及Nordic LED Button Service,GAP和GATT都是标准的蓝牙service,Nordic LED Button Service是Blinky程序自定义的service,它又具体包括两个characteristic:Button和LED。
8) 测试Blinky程序。点击右上角的“Enable CCCDs”以使能notification,如下:
按下开发板上的Button1按键,你会发现nRF connect中的Button characteristic Value会实时显示按键状态:pressed或者released。
点击nRF connect中的LED characteristic右边的向上箭头,选择“ON”并“SEND”,你会发现开发板的LED3将点亮;选择“OFF”并“SEND”,LED3又将熄灭。
3. 修改Blinky程序
3.1 修改广播名称
如前所述,Blinky程序默认的广播名字是:Nordic_Blinky,我们现在将其修改为“My_Blinky”,怎么做呢?我们在Keil中全文搜索“Nordic_Blinky”,发现有如下宏定义:
#define DEVICE_NAME "Nordic_Blinky"
我们只需将这里的Nordic_Blinky换成My_Blinky,即
#define DEVICE_NAME "My_Blinky"
就可以实现我们的目标了。重新编译下载blinky程序,在nRF connect中,你将看到:
你再全文搜索一下“DEVICE_NAME”,你会发现广播名字其实是通过如下API来完成修改的:
err_code = sd_ble_gap_device_name_set(&sec_mode,(const uint8_t *)DEVICE_NAME,strlen(DEVICE_NAME));
注:Keil的搜索功能非常好用,很多问题都可以通过它来解决
3.2 修改广播间隔
如nRF connect界面所示,blinky程序的广播间隔大概为40ms左右,现在为了节省功耗,我们将其改为200ms,通过搜索,我们可以看到如下宏定义:
#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms; this value corresponds to 40 ms). */
因此为了将广播间隔改为200ms,只需将APP_ADV_INTERVAL改成200/0.625 = 320,即
#define APP_ADV_INTERVAL 320
重新编译下载blinky程序,在nRF connect中,你将发现广播间隔已改为200ms了:
3.3 修改Button characteristic行为 (设备发数据给手机)
现在的Blinky程序,只有按下开发板的Button1时,nRF connect的Button characteristic 值才会更新。我们现在新增一个功能:当按下开发板的Button 2时,让Button characteristic value更新为5(注: nRF connect把1当成按键按下,把0当成按键释放,为了更直观,我们没有选择0或者1,而是随便选择一个值:5)。我们先找到Button1按下的回调函数,如下所示:
case LEDBUTTON_BUTTON:NRF_LOG_INFO("Send button state change.");err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action);if (err_code != NRF_SUCCESS &&err_code != BLE_ERROR_INVALID_CONN_HANDLE &&err_code != NRF_ERROR_INVALID_STATE &&err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING){APP_ERROR_CHECK(err_code);}break;
可以看出,我们是通过ble_lbs_on_button_change来更新Button characteristic的值的,ble_lbs_on_button_change具体函数实现如下所示:
uint32_t ble_lbs_on_button_change(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t button_state){ble_gatts_hvx_params_t params;uint16_t len = sizeof(button_state);memset(¶ms, 0, sizeof(params));params.type = BLE_GATT_HVX_NOTIFICATION;params.handle = p_lbs->button_char_handles.value_handle;params.p_data = &button_state;params.p_len = &len;return sd_ble_gatts_hvx(conn_handle, ¶ms);}
我们可以仿照Button1的做法,来添加Button2的代码。首先初始化app_button模块,让button2按下事件可以被button_event_handler捕获,如下:
static app_button_cfg_t buttons[] ={{LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler},{BSP_BUTTON_1, false, BUTTON_PULL, button_event_handler}};
然后在button_event_handler调用ble_button2_send(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t val),以更新Button characteristic的值,代码如下所示:
case BSP_BUTTON_1:NRF_LOG_INFO("Button2 pressed.");ble_button2_send(m_conn_handle, &m_lbs, 5);break;
ble_button2_send(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t val)实现代码如下所示:
uint32_t ble_button2_send(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t val){ble_gatts_hvx_params_t params;uint16_t len = sizeof(val);memset(¶ms, 0, sizeof(params));params.type = BLE_GATT_HVX_NOTIFICATION;params.handle = p_lbs->button_char_handles.value_handle; //Button characteristic value handleparams.p_data = &val;params.p_len = &len;return sd_ble_gatts_hvx(conn_handle, ¶ms); }
重新编译下载blinky程序,连接设备,使能cccd,按下Button2,你会看到Button characteristic的值变为5:
3.4 修改LED characteristic行为(手机发数据给设备)
由于nRF connect把LED characteristic的值写死了,只能发送“ON”或者“OFF”,前面也测试过,发送“ON”之后,LED3将点亮,其实这里的“ON”,就是数值1。我们现在增加一个新的功能:在收到“ON”命令后,把LED4 toggle一下。
这个实现起来比较简单,我们只需在led_write_handler中添加bsp_board_led_invert(BSP_BOARD_LED_3),整体代码如下所示:
static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t led_state){if (led_state){bsp_board_led_on(LEDBUTTON_LED);NRF_LOG_INFO("Received LED ON!");bsp_board_led_invert(BSP_BOARD_LED_3);}else{bsp_board_led_off(LEDBUTTON_LED);NRF_LOG_INFO("Received LED OFF!");}}
重新编译下载blinky程序,连接设备,你会发现第一次发送“ON”,LED4点亮,第二次发送“ON”,LED4又将熄灭。
通过全文搜索“led_write_handler”,你会发现这个函数是被ble_lbs.c中的on_write调用,而on_write又被ble_lbs_on_ble_evt调用,而ble_lbs_on_ble_evt就是我们的BLE事件回调函数,每当softdevice收到LED characteristic的写操作时,都会调用它,这就是通过nRF connect操作设备的过程和原理。
上述代码工程我已经将其上传到百度云盘中,有需要的同学可以到如下链接下载:
- 链接: https://pan.baidu.com/s/1FKTfY3Q_zBVvviO7KC7Gyg#list/path=%2Fblog 密码: y8fb
下载“tutorial_ble_app_blinky_SDK15_3_0.rar”,然后解压缩到SDK15.3.0如下目录下:nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\
即可成功编译。
4. 开发手机端Blinky程序
Nordic同时提供手机端的Blinky程序,该程序源代码完全向用户开放,以帮助用户快速开发自己的第一个Android或者iOS BLE应用程序。用户可以先到app store下载iOS版nRF blinky,或者到Github下载Android版nRF blinky(下载链接:https://github.com/NordicSemiconductor/Android-nRF-Blinky/releases)。手机版的nRF Blinky跟前面介绍的Blinky固件是配合工作的,通过手机版nRF Blinky可以对前面的blinky固件进行操作。nRF Blinky app图标如下所示:
nRF Blinky操作界面如下所示:
- nRF Blinky Android版源代码及开发说明请参考:https://github.com/NordicSemiconductor/Android-nRF-Blinky
- nRF Blinky iOS版源代码及开发说明请参考:https://github.com/NordicSemiconductor/iOS-nRF-Blinky
这篇文章主要让大家对BLE有个大概的认识,后面我会专门写一篇文章来介绍上面提到的BLE service,characteristic,write,notify以及CCCD等,以帮助大家深刻理解这些概念,感兴趣的读者请参考:
手把手教你开发BLE数据透传应用程序
转载于:https://www.cnblogs.com/iini/p/8996025.html
开发你的第一个BLE应用程序—Blinky相关推荐
- Moblin v2开发环境设置——创建一个新应用程序
(翻译:徐诚 http://blog.csdn.net/shizhebsys 保留版权) 这里是开始Moblin开发重要起点.本页描述如何创建一个简单的应用程序,并且介绍少数有用的工具帮助你快速启动开 ...
- 如何成为Web开发人员—编写第一个Web应用程序
Where to begin? This is perhaps the most common question asked by all newcomers to IT. There are so ...
- imx6 android 最新,IMX6开发板创建第一个Android应用程序helloworld
运行行 AndroidStudio 程序.如下图,选择创建一个新的 androidstudio 工程(基于 迅为-i.mx6开发板) 应用名称改为"helloworld",项目保存 ...
- [培训-DSP快速入门-4]:C54x DSP开发环境与第一个C语言程序
作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing 本文网址:https://blog.csdn.net/HiWangWenBing/article ...
- iOS 11开发教程(三)运行第一个iOS 11程序
iOS 11开发教程(三)运行第一个iOS 11程序 运行iOS11程序 创建好项目之后,就可以运行这个项目中的程序了.单击运行按钮,如果程序没有任何问题的话,会看到如图1.6和1.7的运行效果. 图 ...
- Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序
Xamarin iOS开发实战第1章使用C#编写第一个iOS应用程序 C#原本是用来编写Windows以及Windows Phone的应用程序.自从Xamarin问世后,C#的作用就发生了很大的变化. ...
- 《Unity 3D 游戏开发技术详解与典型案例》——1.3节第一个Unity 3D程序
本节书摘来自异步社区<Unity 3D 游戏开发技术详解与典型案例>一书中的第1章,第1.3节第一个Unity 3D程序,作者 吴亚峰 , 于复兴,更多章节内容可以访问云栖社区" ...
- java的应用程序开发_开发一个Java应用程序(1)
开发一个Java应用程序(1) App Engine上的Java Web应用程序通过Java Servlet标准接口与应用程序服务器交互.一个应用程序由一个或多个类组成,这些类都扩展自一个servle ...
- 只需6步,教你从零开发一个签到小程序
摘要:针对于具备瞬时流量.业务场景比较简单的小程序,开发者借助FunctionGraph,可以方便快捷的搭建一个健壮的小程序后台. 本文分享自华为云社区<智慧校园想搞好,FunctionGrap ...
- 一个程序如何连接到外网_如何从头开始开发一个微信小程序
网上有很多的人在问:怎么开发一个微信小程序?今天我来给大家详细讲讲如何申请开发并部署一个微信小程序,大家看完这篇文章后就能够自己运营一个属于自己的小程序了. 现在的小程序有百度小程序,头条小程序,支付 ...
最新文章
- 设置按钮不可见_华为手机居然有【3种录屏方法】,很多人都不知道,真的太实用了...
- Linux下的tar归档及解压缩功能详解
- BZOJ3123: [Sdoi2013]森林
- Python-学生信息管理系统.exe
- 数据结构与算法专题——第十二题 Trie树
- leetcode91. 解码方法
- 东华大学计算机年薪,东华大学公布应届毕业生薪酬:本科生月薪中位数6637元...
- api文档数据量太大崩溃_Tableau的API操作(一)-取消任务刷新
- 美股本周第二次熔断:道指大跌近10% 费城半导体指数大跌11%
- 写入和读取外部存储文件
- docker 镜像修改的配置文件自动还原_基于Docker搭建Redis一主两从三哨兵
- 在做UDP传输的时候,出现的这个问题,哪个大佬能帮忙看一看啊
- c语言求布尔矩阵的乘积,离散数学 关系矩阵的布尔乘法的简便方法
- python词云分析 jieba+wordcloud 按词频生成词云
- lvgl chart
- ICTCLAS代码学习笔记之CSpan类
- 手机显示DNS服务器异常,手机dns服务器异常怎么设置
- 自己整理的运维面试题,必须会。
- NLP模型笔记2022-03:简单理解nlp句法分析
- 常见花材的固定的方法有哪些_别再傻傻只知道使用花泥了,这4种纯天然花材固定方法你该试试!...