“NRF52832DK协议栈实验”的版本间的差异
(→低功耗实验) |
(→源码讲解) |
||
第12行: | 第12行: | ||
我们将万用表串联到电路中,并且打到电流档,此时我们可以看到功耗如下。 | 我们将万用表串联到电路中,并且打到电流档,此时我们可以看到功耗如下。 | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
− | 首先我们查看一下main() | + | |
+ | ===== 主机部分 ===== | ||
+ | |||
+ | ====== main()函数 ====== | ||
+ | 首先我们查看一下main.c文件,在此文件的mian()函数中,我们首先初始化了电源管理模块,然后初始化了BLE栈堆,最后在while大循环中我们调用空闲状态处理的函数。 | ||
+ | |||
+ | 接下来我们分别针对这三个部分进行介绍。<syntaxhighlight lang="c" line="1" start="170"> | ||
//****************************************************************** | //****************************************************************** | ||
// fn : main | // fn : main | ||
第35行: | 第41行: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | ====== ble_stack_init()函数及ble_evt_handler()回调函数 ====== | ||
+ | 我们查看一下BLE协议栈初始化,这个部分是一个格式化的东西。 | ||
+ | |||
+ | 首先调用nrf_sdh_enable_request()函数请求使能softdevice,原因在于ble协议、时钟、错误的回调以及中断的配置等,都需要这个sd(softdevice)支持。 | ||
+ | |||
+ | 接下来我们要配置默认的ble协议,主要包含了RAM起始地址、本工程的角色(根据设备支持连接的角色来判断)、MTU的大小及UUID和属性表大小。 | ||
+ | |||
+ | RAM的起始地址在下面的位置可以看到,我们打开'''\ble_ghostyu\1.0_ble_central_pm\LaunchIOT\s132\iar'''下的'''ble_app_ghostyu_iar_nRF5x.icf'''文件(将此文件拖到IAR中就可以打开,可以看到__ICFEDIT_region_RAM_start__ = 0x200029e0)。 | ||
+ | |||
+ | 然后我们携带RAM起始地址,使能BLE协议栈。 | ||
+ | |||
+ | 在最后,我们注册了一个ble_evt_handler回调,在这个回调中我们处理BLE的事件返回。<syntaxhighlight lang="c" line="1" start="102"> | ||
+ | //****************************************************************** | ||
+ | // fn : ble_stack_init | ||
+ | // | ||
+ | // brief : 用于初始化BLE协议栈 | ||
+ | // details : 初始化SoftDevice、BLE事件中断 | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | static void ble_stack_init(void) | ||
+ | { | ||
+ | ret_code_t err_code; | ||
+ | |||
+ | // SD使能请求,配置时钟,配置错误回调,中断(中断优先级栈堆默认设置) | ||
+ | err_code = nrf_sdh_enable_request(); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | |||
+ | // SD默认配置(如下),SD RAM起始地址配置(0x200029e0) | ||
+ | // 作为从机时的最大连接数量0 | ||
+ | // 作为主机时的最大连接数据1(本工程是主机) | ||
+ | // 初始化MTU大小23 | ||
+ | // 供应商特定的UUID数量1 | ||
+ | // 属性表大小248(必须是4的倍数,以字节为单位) | ||
+ | // 配置服务更改特性数量0 | ||
+ | uint32_t ram_start = 0; | ||
+ | err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | |||
+ | // 使能BLE栈堆 | ||
+ | err_code = nrf_sdh_ble_enable(&ram_start); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | |||
+ | // 注册BLE事件的处理程序,所有BLE的事件都将分派ble_evt_handler回调 | ||
+ | NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); | ||
+ | } | ||
+ | </syntaxhighlight>ble_evt_handler回调函数,用于处理BLE的事件回调,包含了COMMON、GAP、GATT Client、GATT Server、L2CAP等多种事件类型。在这个例程中,我们只给大家保留了最基础的两个GAP状态,分别为连接状态和断开连接状态。<syntaxhighlight lang="c" line="1" start="68"> | ||
+ | //****************************************************************** | ||
+ | // fn : ble_evt_handler | ||
+ | // | ||
+ | // brief : BLE事件回调 | ||
+ | // details : 包含以下几种事件类型:COMMON、GAP、GATT Client、GATT Server、L2CAP | ||
+ | // | ||
+ | // param : ble_evt_t 事件类型 | ||
+ | // p_context 未使用 | ||
+ | // | ||
+ | // return : none | ||
+ | static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context) | ||
+ | { | ||
+ | ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt; | ||
+ | |||
+ | switch (p_ble_evt->header.evt_id) | ||
+ | { | ||
+ | // 连接 | ||
+ | case BLE_GAP_EVT_CONNECTED: | ||
+ | NRF_LOG_INFO("Connected. conn_handle: 0x%x",p_gap_evt->conn_handle); | ||
+ | break; | ||
+ | |||
+ | // 断开连接 | ||
+ | case BLE_GAP_EVT_DISCONNECTED: | ||
+ | |||
+ | NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%x", | ||
+ | p_gap_evt->conn_handle, | ||
+ | p_gap_evt->params.disconnected.reason); | ||
+ | break; | ||
+ | |||
+ | default: | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ====== power_management_init()及idle_state_handle()函数 ====== | ||
+ | power_management_init()函数调用底层的nrf_pwr_mgmt_init()函数去初始化电源管理的部分。 | ||
+ | |||
+ | idle_state_handle()函数调用底层的nrf_pwr_mgmt_run()函数,用于处理空闲状态的功能(处理完所有的挂起事件,然后进入休眠,直到下一个事件发生)。<syntaxhighlight lang="c" line="1" start="138"> | ||
+ | //****************************************************************** | ||
+ | // fn : power_management_init | ||
+ | // | ||
+ | // brief : 初始化电源管理 | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | static void power_management_init(void) | ||
+ | { | ||
+ | ret_code_t err_code; | ||
+ | err_code = nrf_pwr_mgmt_init(); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | } | ||
+ | |||
+ | //****************************************************************** | ||
+ | // fn : idle_state_handle | ||
+ | // | ||
+ | // brief : 处理空闲状态的功能(用于主循环) | ||
+ | // details : 处理任何挂起的日志操作,然后休眠直到下一个事件发生 | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | static void idle_state_handle(void) | ||
+ | { | ||
+ | if (NRF_LOG_PROCESS() == false) | ||
+ | { | ||
+ | nrf_pwr_mgmt_run(); | ||
+ | } | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===== 从机部分 ===== | ||
+ | |||
+ | ====== ble_stack_init()函数 ====== | ||
+ | 从机部分大体上是和主机一样的,在nordic的协议栈例程中,(如果大家对BLE协议有一定的了解或者使用过其他厂家的BLE芯片)我们可以发现,nordic为了简化BLE的开发难度,可谓是不择手段,他减掉了很多的ble协议相关的内容(这里的减掉指的是放到底层处理,不需要开发者去配置),这其中就包含了GAP Role,也就是蓝牙的角色。 | ||
+ | |||
+ | ble_satck_init()函数在主机与从机中,唯一不同的点在初始化参数配置。<syntaxhighlight lang="c" line="1" start="99"> | ||
+ | //****************************************************************** | ||
+ | // fn : ble_stack_init | ||
+ | // | ||
+ | // brief : 用于初始化BLE协议栈 | ||
+ | // details : 初始化SoftDevice、BLE事件中断 | ||
+ | // | ||
+ | // param : none | ||
+ | // | ||
+ | // return : none | ||
+ | static void ble_stack_init(void) | ||
+ | { | ||
+ | ret_code_t err_code; | ||
+ | |||
+ | // SD使能请求,配置时钟,配置错误回调,中断(中断优先级栈堆默认设置) | ||
+ | err_code = nrf_sdh_enable_request(); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | |||
+ | // SD默认配置(如下),SD RAM起始地址配置(0x20002a98) | ||
+ | // 作为从机时的最大连接数量1(本工程为从机) | ||
+ | // 作为主机时的最大连接数据0 | ||
+ | // 初始化MTU大小23 | ||
+ | // 供应商特定的UUID数量1 | ||
+ | // 属性表大小248(必须是4的倍数,以字节为单位) | ||
+ | // 配置服务更改特性数量0 | ||
+ | uint32_t ram_start = 0; | ||
+ | err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | |||
+ | // 使能BLE栈堆 | ||
+ | err_code = nrf_sdh_ble_enable(&ram_start); | ||
+ | APP_ERROR_CHECK(err_code); | ||
+ | |||
+ | // 注册BLE事件的处理程序,所有BLE的事件都将分派ble_evt_handler回调 | ||
+ | NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); | ||
+ | } | ||
+ | </syntaxhighlight>主机初始化时设置的是作为主机时最大连接数量1,从机初始化时设置的是作为从机时最大连接数量1。这个配置的宏定义是在sdk_config.h文件中。我们go to define,进入nrf_sdh_ble_default_cfg_set()默认参数配置函数中查看,可以找到如下部分。 | ||
+ | |||
+ | NRF_SDH_BLE_PERIPHERAL_LINK_COUNT与NRF_SDH_BLE_CENTRAL_LINK_COUNT,在定义最大连接设备数量的同时,也决定了它本身的角色属性。 | ||
+ | |||
+ | BLE中我们称Central中心设备为主机(发起连接的设备)、Peripheral外部设备为从机(广播等待被连接的设备)。<syntaxhighlight lang="c" line="1" start="103"> | ||
+ | ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start) | ||
+ | { | ||
+ | uint32_t ret_code; | ||
+ | |||
+ | ... | ||
+ | |||
+ | // Configure the connection roles. | ||
+ | memset(&ble_cfg, 0, sizeof(ble_cfg)); | ||
+ | ble_cfg.gap_cfg.role_count_cfg.periph_role_count = NRF_SDH_BLE_PERIPHERAL_LINK_COUNT; | ||
+ | #ifndef S112 | ||
+ | ble_cfg.gap_cfg.role_count_cfg.central_role_count = NRF_SDH_BLE_CENTRAL_LINK_COUNT; | ||
+ | ble_cfg.gap_cfg.role_count_cfg.central_sec_count = MIN(NRF_SDH_BLE_CENTRAL_LINK_COUNT, | ||
+ | BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT); | ||
+ | #endif | ||
+ | |||
+ | ... | ||
+ | |||
+ | return NRF_SUCCESS; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== 实验总结 ==== | ||
+ | 在低功耗主从机的学习中,我们可以了解到最精简的主从机工程。也就是只包含了softdevice与ble协议栈初始化、以及电源管理初始化。 | ||
+ | |||
+ | 重点问题: | ||
+ | |||
+ | 1.了解如何定义一个BLE工程是主机还是从机,或者其他的属性(主从一体等等)。 | ||
+ | |||
+ | 2.了解如何进行低功耗处理(main()函数中while循环的idle_state_handle空闲任务处理函数)。 | ||
=== LOG打印实验 === | === LOG打印实验 === | ||
==== 实验简介 ==== | ==== 实验简介 ==== | ||
+ | LOG打印实验是在低功耗实验的基础上,新增了LOG打印部分。 | ||
+ | |||
+ | 那么为什么我们需要添加log功能,主要是因为在开发的过程中,我们几乎很难一次调通我们需求的功能,这个时候我们就需要一种好的方式去帮助我们调通,我们出现问题点在哪(查找bug),以及我们的流程进行到哪边了(流程监视)。说到这里,大家会说为什么不使用在线调试的方式解决问题呢,下面谈一谈我个人的使用感觉(仅针对BLE)。 | ||
+ | |||
+ | 何时使用在线调试: | ||
+ | |||
+ | 1.针对细小的问题点,例如某个参数的数值是否正确 | ||
+ | |||
+ | 2.针对不影响程序整机蓝牙功能运行的问题点,例如外设功能异常 | ||
+ | |||
+ | 何时使用log: | ||
+ | |||
+ | 1.不能使用在线调试功能的时候(例如蓝牙连接状态下的通信调试,由于连接参数的限制,如果在线打断点调试,会导致异常断开) | ||
+ | |||
+ | 2.监测关键节点信息(有些问题会出现在一些特殊情况下,可能需要监测N多次,才会出现一次异常) | ||
+ | {{Note|text=注意:我们的LOG工程,仅针对RTT部分,没有介绍UART|type=warning}} | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ===== 主机部分 ===== | ||
+ | log打印实验相对于前一章节的低功耗实验,新增的功能并不多,我们仅仅添加了LOG的RTT打印功能,这边 | ||
+ | |||
+ | ===== 从机部分 ===== | ||
+ | |||
+ | ==== 实验总结 ==== | ||
=== 通用扫描实验 === | === 通用扫描实验 === | ||
第50行: | 第275行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== 过滤扫描实验 === | === 过滤扫描实验 === | ||
第58行: | 第285行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== 白名单扫描实验 === | === 白名单扫描实验 === | ||
第66行: | 第295行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== 通用连接实验 === | === 通用连接实验 === | ||
第74行: | 第305行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== 过滤连接实验 === | === 过滤连接实验 === | ||
第82行: | 第315行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== 连接参数更新实验 === | === 连接参数更新实验 === | ||
第90行: | 第325行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== MTU更新实验 === | === MTU更新实验 === | ||
第98行: | 第335行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== NUS服务获取实验 === | === NUS服务获取实验 === | ||
第106行: | 第345行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== | ||
=== NUS通信实验 === | === NUS通信实验 === | ||
第114行: | 第355行: | ||
==== 实验现象 ==== | ==== 实验现象 ==== | ||
− | ==== | + | ==== 工程及源码讲解 ==== |
+ | |||
+ | ==== 实验总结 ==== |
2019年7月8日 (一) 16:56的版本
目录
1 蓝牙协议简介
2 蓝牙协议实验
蓝牙协议实验部分,我们借由串口透传实验,一步一步拆分,给大家介绍蓝牙的协议方面。
2.1 低功耗实验
2.1.1 实验简介
低功耗实验1.0_ble_central_pm与2.0_ble_peripheral_pm,这两个实验给大家带来的是最精简的主机以及从机例程,精简到什么程度呢,只保留了协议栈初始化以及电源管理部分。利用此实验,大家可以测试一下我们的BLE工程进入低功耗模式下的功耗情况。
2.1.2 实验现象
我们将万用表串联到电路中,并且打到电流档,此时我们可以看到功耗如下。
2.1.3 工程及源码讲解
2.1.3.1 主机部分
2.1.3.1.1 main()函数
首先我们查看一下main.c文件,在此文件的mian()函数中,我们首先初始化了电源管理模块,然后初始化了BLE栈堆,最后在while大循环中我们调用空闲状态处理的函数。
接下来我们分别针对这三个部分进行介绍。
170 //******************************************************************
171 // fn : main
172 //
173 // brief : 主函数
174 //
175 // param : none
176 //
177 // return : none
178 int main(void)
179 {
180 // 初始化
181 power_management_init();// 初始化电源控制
182 ble_stack_init(); // 初始化BLE栈堆
183
184 // 进入主循环
185 for (;;)
186 {
187 idle_state_handle(); // 空闲状态处理
188 }
189 }
2.1.3.1.2 ble_stack_init()函数及ble_evt_handler()回调函数
我们查看一下BLE协议栈初始化,这个部分是一个格式化的东西。
首先调用nrf_sdh_enable_request()函数请求使能softdevice,原因在于ble协议、时钟、错误的回调以及中断的配置等,都需要这个sd(softdevice)支持。
接下来我们要配置默认的ble协议,主要包含了RAM起始地址、本工程的角色(根据设备支持连接的角色来判断)、MTU的大小及UUID和属性表大小。
RAM的起始地址在下面的位置可以看到,我们打开\ble_ghostyu\1.0_ble_central_pm\LaunchIOT\s132\iar下的ble_app_ghostyu_iar_nRF5x.icf文件(将此文件拖到IAR中就可以打开,可以看到__ICFEDIT_region_RAM_start__ = 0x200029e0)。
然后我们携带RAM起始地址,使能BLE协议栈。
在最后,我们注册了一个ble_evt_handler回调,在这个回调中我们处理BLE的事件返回。
102 //******************************************************************
103 // fn : ble_stack_init
104 //
105 // brief : 用于初始化BLE协议栈
106 // details : 初始化SoftDevice、BLE事件中断
107 //
108 // param : none
109 //
110 // return : none
111 static void ble_stack_init(void)
112 {
113 ret_code_t err_code;
114
115 // SD使能请求,配置时钟,配置错误回调,中断(中断优先级栈堆默认设置)
116 err_code = nrf_sdh_enable_request();
117 APP_ERROR_CHECK(err_code);
118
119 // SD默认配置(如下),SD RAM起始地址配置(0x200029e0)
120 // 作为从机时的最大连接数量0
121 // 作为主机时的最大连接数据1(本工程是主机)
122 // 初始化MTU大小23
123 // 供应商特定的UUID数量1
124 // 属性表大小248(必须是4的倍数,以字节为单位)
125 // 配置服务更改特性数量0
126 uint32_t ram_start = 0;
127 err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
128 APP_ERROR_CHECK(err_code);
129
130 // 使能BLE栈堆
131 err_code = nrf_sdh_ble_enable(&ram_start);
132 APP_ERROR_CHECK(err_code);
133
134 // 注册BLE事件的处理程序,所有BLE的事件都将分派ble_evt_handler回调
135 NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
136 }
ble_evt_handler回调函数,用于处理BLE的事件回调,包含了COMMON、GAP、GATT Client、GATT Server、L2CAP等多种事件类型。在这个例程中,我们只给大家保留了最基础的两个GAP状态,分别为连接状态和断开连接状态。
68 //******************************************************************
69 // fn : ble_evt_handler
70 //
71 // brief : BLE事件回调
72 // details : 包含以下几种事件类型:COMMON、GAP、GATT Client、GATT Server、L2CAP
73 //
74 // param : ble_evt_t 事件类型
75 // p_context 未使用
76 //
77 // return : none
78 static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
79 {
80 ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
81
82 switch (p_ble_evt->header.evt_id)
83 {
84 // 连接
85 case BLE_GAP_EVT_CONNECTED:
86 NRF_LOG_INFO("Connected. conn_handle: 0x%x",p_gap_evt->conn_handle);
87 break;
88
89 // 断开连接
90 case BLE_GAP_EVT_DISCONNECTED:
91
92 NRF_LOG_INFO("Disconnected. conn_handle: 0x%x, reason: 0x%x",
93 p_gap_evt->conn_handle,
94 p_gap_evt->params.disconnected.reason);
95 break;
96
97 default:
98 break;
99 }
100 }
2.1.3.1.3 power_management_init()及idle_state_handle()函数
power_management_init()函数调用底层的nrf_pwr_mgmt_init()函数去初始化电源管理的部分。
idle_state_handle()函数调用底层的nrf_pwr_mgmt_run()函数,用于处理空闲状态的功能(处理完所有的挂起事件,然后进入休眠,直到下一个事件发生)。
138 //******************************************************************
139 // fn : power_management_init
140 //
141 // brief : 初始化电源管理
142 //
143 // param : none
144 //
145 // return : none
146 static void power_management_init(void)
147 {
148 ret_code_t err_code;
149 err_code = nrf_pwr_mgmt_init();
150 APP_ERROR_CHECK(err_code);
151 }
152
153 //******************************************************************
154 // fn : idle_state_handle
155 //
156 // brief : 处理空闲状态的功能(用于主循环)
157 // details : 处理任何挂起的日志操作,然后休眠直到下一个事件发生
158 //
159 // param : none
160 //
161 // return : none
162 static void idle_state_handle(void)
163 {
164 if (NRF_LOG_PROCESS() == false)
165 {
166 nrf_pwr_mgmt_run();
167 }
168 }
2.1.3.2 从机部分
2.1.3.2.1 ble_stack_init()函数
从机部分大体上是和主机一样的,在nordic的协议栈例程中,(如果大家对BLE协议有一定的了解或者使用过其他厂家的BLE芯片)我们可以发现,nordic为了简化BLE的开发难度,可谓是不择手段,他减掉了很多的ble协议相关的内容(这里的减掉指的是放到底层处理,不需要开发者去配置),这其中就包含了GAP Role,也就是蓝牙的角色。
ble_satck_init()函数在主机与从机中,唯一不同的点在初始化参数配置。
99 //******************************************************************
100 // fn : ble_stack_init
101 //
102 // brief : 用于初始化BLE协议栈
103 // details : 初始化SoftDevice、BLE事件中断
104 //
105 // param : none
106 //
107 // return : none
108 static void ble_stack_init(void)
109 {
110 ret_code_t err_code;
111
112 // SD使能请求,配置时钟,配置错误回调,中断(中断优先级栈堆默认设置)
113 err_code = nrf_sdh_enable_request();
114 APP_ERROR_CHECK(err_code);
115
116 // SD默认配置(如下),SD RAM起始地址配置(0x20002a98)
117 // 作为从机时的最大连接数量1(本工程为从机)
118 // 作为主机时的最大连接数据0
119 // 初始化MTU大小23
120 // 供应商特定的UUID数量1
121 // 属性表大小248(必须是4的倍数,以字节为单位)
122 // 配置服务更改特性数量0
123 uint32_t ram_start = 0;
124 err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
125 APP_ERROR_CHECK(err_code);
126
127 // 使能BLE栈堆
128 err_code = nrf_sdh_ble_enable(&ram_start);
129 APP_ERROR_CHECK(err_code);
130
131 // 注册BLE事件的处理程序,所有BLE的事件都将分派ble_evt_handler回调
132 NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
133 }
主机初始化时设置的是作为主机时最大连接数量1,从机初始化时设置的是作为从机时最大连接数量1。这个配置的宏定义是在sdk_config.h文件中。我们go to define,进入nrf_sdh_ble_default_cfg_set()默认参数配置函数中查看,可以找到如下部分。
NRF_SDH_BLE_PERIPHERAL_LINK_COUNT与NRF_SDH_BLE_CENTRAL_LINK_COUNT,在定义最大连接设备数量的同时,也决定了它本身的角色属性。
BLE中我们称Central中心设备为主机(发起连接的设备)、Peripheral外部设备为从机(广播等待被连接的设备)。
103 ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start)
104 {
105 uint32_t ret_code;
106
107 ...
108
109 // Configure the connection roles.
110 memset(&ble_cfg, 0, sizeof(ble_cfg));
111 ble_cfg.gap_cfg.role_count_cfg.periph_role_count = NRF_SDH_BLE_PERIPHERAL_LINK_COUNT;
112 #ifndef S112
113 ble_cfg.gap_cfg.role_count_cfg.central_role_count = NRF_SDH_BLE_CENTRAL_LINK_COUNT;
114 ble_cfg.gap_cfg.role_count_cfg.central_sec_count = MIN(NRF_SDH_BLE_CENTRAL_LINK_COUNT,
115 BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT);
116 #endif
117
118 ...
119
120 return NRF_SUCCESS;
121 }
2.1.4 实验总结
在低功耗主从机的学习中,我们可以了解到最精简的主从机工程。也就是只包含了softdevice与ble协议栈初始化、以及电源管理初始化。
重点问题:
1.了解如何定义一个BLE工程是主机还是从机,或者其他的属性(主从一体等等)。
2.了解如何进行低功耗处理(main()函数中while循环的idle_state_handle空闲任务处理函数)。
2.2 LOG打印实验
2.2.1 实验简介
LOG打印实验是在低功耗实验的基础上,新增了LOG打印部分。
那么为什么我们需要添加log功能,主要是因为在开发的过程中,我们几乎很难一次调通我们需求的功能,这个时候我们就需要一种好的方式去帮助我们调通,我们出现问题点在哪(查找bug),以及我们的流程进行到哪边了(流程监视)。说到这里,大家会说为什么不使用在线调试的方式解决问题呢,下面谈一谈我个人的使用感觉(仅针对BLE)。
何时使用在线调试:
1.针对细小的问题点,例如某个参数的数值是否正确
2.针对不影响程序整机蓝牙功能运行的问题点,例如外设功能异常
何时使用log:
1.不能使用在线调试功能的时候(例如蓝牙连接状态下的通信调试,由于连接参数的限制,如果在线打断点调试,会导致异常断开)
2.监测关键节点信息(有些问题会出现在一些特殊情况下,可能需要监测N多次,才会出现一次异常)
2.2.2 实验现象
2.2.3 工程及源码讲解
2.2.3.1 主机部分
log打印实验相对于前一章节的低功耗实验,新增的功能并不多,我们仅仅添加了LOG的RTT打印功能,这边