更改

跳转至: 导航搜索

NRF52832DK协议栈实验

添加7,167字节2019年7月9日 (二) 15:14
实验现象
==== 实验简介 ====
通用扫描实验给大家带来的是主机的扫描功能展示,以及从机的广播功能展示。
 
也就是从这一实验开始,我们才是真正进入到BLE协议的学习实验,我们将按照扫描、连接、获取服务、通信的流程,在接下来的实验中给大家介绍BLE协议。
大家都清楚,低功耗蓝牙主从机间交互数据的方式一般来说是有两种,一种是连接之后通信(这个是蓝牙的主要功能),另一种就是本实验带来的主机扫描获取从机的广播数据。而上述的两种方式,不管是哪一种,都是需要扫描功能的,毕竟连接通信之前,我们的主机也是需要扫描到从机设备才可以发起连接。
==== 实验现象 ====
主机log打印如下,先打印当前例程的名称'''1.2_ble_central_scan_all''',然后将会打印扫描到的从机设备的信息,格式如下:<syntaxhighlight lang="c">
Device MAC: 0x010203040506 // 从机设备MAC地址
 
adv data: 0x0102...xx...xx // 从机设备广播数据
 
scan data: 0x0102...xx...xx // 从机设备扫描回调数据
 
rssi: -xxdBm // 从机设备相当于当前主机的信号强度
 
 
</syntaxhighlight>
[[文件:Nrf rtt 12.png|边框|居中|无框|656x656像素]]
主机log打印如下,先打印当前例程的名称'''2.2_ble_peripheral_adv_all。'''
[[文件:Nrf rtt 22.png|边框|居中|无框|656x656像素]]
==== 工程及源码讲解 ====
 
===== 工程说明 =====
相对于LOG打印的工程,我们新增了nRF_BLE分组,这个分组下包含的就是BLE协议相关的文件,我们在本实验中只使用了nrf_ble_scan.c下的扫描功能函数。
[[文件:Nrf group nrf ble.png|边框|居中|无框|296x296像素]]
 
===== 主机部分 =====
 
====== main()函数 ======
在mian函数中,我们新增了扫描功能的scan_init()初始化函数,并且在初始化所有功能之后,我们调用了发起扫描的函数scan_start()。<syntaxhighlight lang="c" line="1" start="296">
//******************************************************************
// fn : main
//
// brief : 主函数
//
// param : none
//
// return : none
int main(void)
{
// 初始化
log_init(); // 初始化LOG打印,由RTT工作
power_management_init();// 初始化电源控制
ble_stack_init(); // 初始化BLE栈堆
scan_init(); // 初始化扫描
// 打印例程名称
NRF_LOG_INFO("1.2_ble_central_scan_all");
scan_start(); // 开始扫描
// 进入主循环
for (;;)
{
idle_state_handle(); // 空闲状态处理
}
}
</syntaxhighlight>
 
====== scan_init()函数及scan_evt_handler()回调函数 ======
首先我们看一下我们的扫描功能的初始化函数,可以看到我们最终调用的是库函数中的nrf_ble_scan_init()去初始化我们扫描,在这个函数中,有两个参数需要我们关注,一个是init_scan(这个参数携带的我们对于扫描的设置),另一个是scan_evt_handler(当我们扫描到设备之后,将会由这个回调函数返回事件信息给我们)。<syntaxhighlight lang="c" line="1" start="155">
//******************************************************************
// fn : scan_init
//
// brief : 初始化扫描(未设置扫描数据限制)
//
// param : none
//
// return : none
static void scan_init(void)
{
ret_code_t err_code;
nrf_ble_scan_init_t init_scan;
 
// 清空扫描结构体参数
memset(&init_scan, 0, sizeof(init_scan));
// 配置扫描的参数
init_scan.p_scan_param = &m_scan_params;
// 初始化扫描
err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
APP_ERROR_CHECK(err_code);
}
</syntaxhighlight>首先我们看一下扫描的参数设置,这边我们设置为主动扫描,扫描间隔是100ms,扫描窗口是50ms,扫描的持续时间设置为0(设置为0,则一直扫描,除非我们调用停止扫描的函数),另外我们设置扫描附近的所有BLE设备(不做扫描限制)。
{{Note|text=扫描模式分为两种:
1.被动扫描:只扫描从机设备的广播数据
 
2.主动扫描:扫描从机设备的广播数据以及扫描回调数据|type=info}}
[[文件:扫描窗口和扫描间隔.jpg|边框|居中|无框|800x800像素]]
<syntaxhighlight lang="c" line="1" start="55">
// 定义扫描参数
static ble_gap_scan_params_t m_scan_params =
{
.active = 1, // 1为主动扫描,可获得广播数据及扫描回调数据
.interval = NRF_BLE_SCAN_SCAN_INTERVAL, // 扫描间隔:160*0.625 = 100ms
.window = NRF_BLE_SCAN_SCAN_WINDOW, // 扫描窗口:80*0.625 = 50ms
.timeout = NRF_BLE_SCAN_SCAN_DURATION, // 扫描持续的时间:设置为0,一直扫描,直到明确的停止扫描
.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL, // 扫描所有BLE设备,不做限制
.scan_phys = BLE_GAP_PHY_1MBPS, // 扫描1MBPS的PHY
};
</syntaxhighlight>接下来我们查看一下我们处理扫描回调事件的函数,因为我们这个实验带给大家的是扫描附近所有的BLE广播设备,所以可以看到,我们判断的设备ID为NRF_BLE_SCAN_EVT_NOT_FOUND,这个ID代表的未被过滤的扫描数据。
 
在这个事件ID下,我们根据p_scan_evt->params.p_not_found->type.scan_response判断扫描到的数据是广播数据还是扫描回调数据,并且我们可以从这个消息结构体当中获取到上述的两包数据、以及设备的MAC、设备的RSSI信号强度等等。并且我们将扫描到的这些信息通过LOG向RTT格式化打印出来。<syntaxhighlight lang="c" line="1" start="99">
 
//******************************************************************
// fn : scan_evt_handler
//
// brief : 处理扫描回调事件
//
// param : scan_evt_t 扫描事件结构体
//
// return : none
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
{
switch(p_scan_evt->scan_evt_id)
{
// 未过滤的扫描数据
case NRF_BLE_SCAN_EVT_NOT_FOUND:
{
// 判断是否为扫描回调数据
if(p_scan_evt->params.p_not_found->type.scan_response)
{
if(p_scan_evt->params.p_not_found->data.len) // 存在扫描回调数据
{
NRF_LOG_INFO("scan data: %s",
Util_convertHex2Str(
p_scan_evt->params.p_not_found->data.p_data,
p_scan_evt->params.p_not_found->data.len));
}
else
{
NRF_LOG_INFO("scan data: %s","NONE");
}
NRF_LOG_INFO("rssi: %ddBm",p_scan_evt->params.p_not_found->rssi);
}
else // 否则为广播数据
{
// 打印扫描的设备MAC
NRF_LOG_INFO("Device MAC: %s",
Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.p_not_found->peer_addr.addr));
if(p_scan_evt->params.p_not_found->data.len) // 存在广播数据
{
NRF_LOG_INFO("adv data: %s",
Util_convertHex2Str(
p_scan_evt->params.p_not_found->data.p_data,
p_scan_evt->params.p_not_found->data.len));
}
else
{
NRF_LOG_INFO("adv data: %s","NONE");
}
}
} break;
 
default:
break;
}
}
</syntaxhighlight>
 
===== 从机部分 =====
 
====== 工程说明 ======
 
====== main()函数 ======
==== 实验总结 ====
510
个编辑

本PDF由谷雨文档中心自动生成,点击下方链接阅读最新内容。

取自“http://doc.iotxx.com/特殊:移动版差异/1749

导航菜单