510
个编辑
更改
→实验简介
==== 实验简介 ====
==== 实验现象 ====
主机部分,可以看到上电先打印'''1.3_ble_central_scan_filter'''字样,然后会周期打印扫描到的2.3例程的从机设备信息(MAC、扫描回调数据、RSSI)。
在扫描回调的数据的末尾,我们可以看到03030100的字样,这个就是我们实验限制扫描的UUID。
{{Note|text=03,// UUID数据长度
03,// 16bit UUID数据类型
01,00 // UUID 0x0001,这边是低位在前|type=info}}
[[文件:Nrf rtt 13.png|边框|居中|无框|656x656像素]]
从机部分,可以看到上电先打印'''2.3_ble_peripheral_adv_filter'''字样。
[[文件:Nrf rtt 23.png|边框|居中|无框|656x656像素]]
==== 工程及源码讲解 ====
===== 主机工程 =====
====== 工程说明 ======
本工程相对于上一章节的通用扫描实现,改动较小,只是对扫描返回的设备做出限制,不再像之前那样返回所有扫描到的设备。
所以我们的修改内容集中在scan_init()函数以及scan_evt_handler()回调函数当中。
====== scan_init()函数 ======
相对于通用扫描的主机程序,我们在限制扫描的初始化函数当中,新增了nrf_ble_scan_filter_set()函数用于限制扫描的设备,在这个例程中,我们给大家展示的是限制UUID扫描,大家也可以根据其他信息去进行限制。
我们限制了扫描的UUID是16bit的0x0001,并且调用nrf_ble_scan_filters_enable()使能了这个限制。<syntaxhighlight lang="c" line="1" start="65">
// 定义扫描限制的UUID
static ble_uuid_t const m_nus_uuid = {BLE_UUID_NUS_SERVICE, BLE_UUID_TYPE_BLE};
</syntaxhighlight><syntaxhighlight lang="c" line="1" start="162">
//******************************************************************
// 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);
// 设置扫描的UUID限制
err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_UUID_FILTER, &m_nus_uuid);
APP_ERROR_CHECK(err_code);
// 使能扫描的UUID限制
err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_UUID_FILTER, false);
APP_ERROR_CHECK(err_code);
}
</syntaxhighlight>
====== scan_evt_handler()回调函数 ======
大家可以看到,我们对于扫描回调的事件ID判断进行了更改,上一章的通用扫描我们的判断的是NRF_BLE_SCAN_EVT_NOT_FOUND,这一章的限制扫描我们判断的是NRF_BLE_SCAN_EVT_FILTER_MATCH。
由于上面的一系列对于扫描UUID的限制操作,所以我们的1.3主机实验的现象,才会仅扫描并返回给我们的2.3实验的从机设备。
为了给大家更直观的找到限制的UUID,我们这边临时注视掉了广播数据的打印,只保留了包含了UUID的扫描回调数据打印。<syntaxhighlight lang="c" line="1" start="102">
//******************************************************************
// 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_FILTER_MATCH:
{
// 下面这一段我们只保留了扫描回调数据获取的部分,因为从机筛选广播的UUID在扫描回调数据
// 判断是否为扫描回调数据
if(p_scan_evt->params.filter_match.p_adv_report->type.scan_response)
{
NRF_LOG_INFO("Device MAC: %s",
Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr));
if(p_scan_evt->params.filter_match.p_adv_report->data.len) // 存在扫描回调数据
{
NRF_LOG_INFO("scan data: %s",
Util_convertHex2Str(
p_scan_evt->params.filter_match.p_adv_report->data.p_data,
p_scan_evt->params.filter_match.p_adv_report->data.len));
}
else
{
NRF_LOG_INFO("scan data: %s","NONE");
}
NRF_LOG_INFO("rssi: %ddBm",p_scan_evt->params.filter_match.p_adv_report->rssi);
}
// else // 否则为广播数据
// {
// // 打印扫描的设备MAC
// NRF_LOG_INFO("Device MAC: %s",
// Util_convertBdAddr2Str((uint8_t*)p_scan_evt->params.filter_match.p_adv_report->peer_addr.addr));
//
// if(p_scan_evt->params.filter_match.p_adv_report->data.len) // 存在广播数据
// {
// NRF_LOG_INFO("adv data: %s",
// Util_convertHex2Str(
// p_scan_evt->params.filter_match.p_adv_report->data.p_data,
// p_scan_evt->params.filter_match.p_adv_report->data.len));
// }
// else
// {
// NRF_LOG_INFO("adv data: %s","NONE");
// }
// }
} break;
default:
break;
}
}
</syntaxhighlight>
===== 从机部分 =====
====== 工程说明 ======
从机部分相对于通用广播的从机,我们也仅仅增加了UUID的广播数据。所以这边我们查看一下广播数据初始化的函数advertising_init()。
====== advertising_init() ======
大家可以看到,在广播数据初始化函数中,我们在init.srdata中增加了uuids_complete的定义,这样我们的广播数据中就会携带16bit的UUID 0x0001数据(这个数据在m_adv_uuids中被定义)。<syntaxhighlight lang="c" line="1" start="53">
// 定义广播的UUID
static ble_uuid_t m_adv_uuids[] = {{BLE_UUID_NUS_SERVICE, BLE_UUID_TYPE_BLE}};
</syntaxhighlight><syntaxhighlight lang="c" line="1" start="87">
//******************************************************************
// fn : advertising_init
//
// brief : 用于初始化广播
//
// param : none
//
// return : none
static void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t init;
memset(&init, 0, sizeof(init));
// 广播数据包含所有设备名称(FULL NAME)
init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
// // 广播数据只包含部分设备名称(SHORT NAME,长度为6)
// init.advdata.name_type = BLE_ADVDATA_SHORT_NAME;
// init.advdata.short_name_len = 6;
// 扫描回调数据中包含16bit UUID:0x0001
init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.srdata.uuids_complete.p_uuids = m_adv_uuids;
// 扫描回调数据中包含设备MAC地址
init.srdata.include_ble_device_addr = true;
// 配置广播周期,先快速广播18s(周期40ms),再慢速广播18s(周期100ms),最后停止广播
init.config.ble_adv_fast_enabled = true;
init.config.ble_adv_fast_interval = 64; // 64*0.625 = 40ms
init.config.ble_adv_fast_timeout = 1800; // 1800*10ms = 18s
init.config.ble_adv_slow_enabled = true;
init.config.ble_adv_slow_interval = 160; // 160*0.625 = 100ms
init.config.ble_adv_slow_timeout = 18000; // 18000*10ms = 180s
err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
</syntaxhighlight>
==== 实验总结 ====
经过这个扫描限制实验的学习,大家需要掌握的要点。
主机部分:
1.如何添加一个扫描的限制并使能
2.限制扫描的回调事件ID是NRF_BLE_SCAN_EVT_FILTER_MATCH
3.自行编程,完成通过名称、地址等其他限制的扫描
从机部分:
1.如何添加个人的广播数据,例如本章节的UUID(本质上还是广播数据的配置)
=== 白名单扫描实验 ===