nrf52832 学习笔记蓝牙主机扫描
Posted 不咸不要钱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nrf52832 学习笔记蓝牙主机扫描相关的知识,希望对你有一定的参考价值。
nrf52832 学习笔记(四)蓝牙主机扫描
从机发出广播后就需要主机进行扫描了,主机扫描之前和从机一样,也需要协议栈初始化、GAP初始化、GATT初始化,这些和从机类似,参考 nrf52832 学习笔记(三)蓝牙从机广播即可。
扫描初始化
扫描初始化主要初始化扫描的四个参数:扫描模式、扫描间隔、扫描窗口、扫描持续时间。
/**@brief 扫描事件回调函数
*
* @param[in] p_scan_evt Scanning event.
*/
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
ret_code_t err_code;
switch(p_scan_evt->scan_evt_id)
case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
err_code = p_scan_evt->params.connecting_err.err_code;
APP_ERROR_CHECK(err_code);
break;
default:
break;
#define SCAN_INTERVAL 0x3000 /**< 扫描间隔 */
#define SCAN_WINDOW 0x3000 /**< 扫描窗口 */
#define SCAN_DURATION 0 /**< 持续扫描时间 */
static ble_gap_scan_params_t gap_scan =
.active = 0, //扫描模式:0:被动扫描; 1:主动扫描
.interval = SCAN_INTERVAL, //扫描间隔
.window = SCAN_WINDOW, //扫描窗口
.timeout = SCAN_DURATION, //扫描持续时间
.scan_phys = BLE_GAP_PHY_1MBPS,//1M
.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL, //扫描信道
;
/**@brief 扫描初始化
*/
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.connect_if_match = false; //如果开启过滤器,遇到匹配项是否直接进行连接
init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
init_scan.p_scan_param = &gap_scan;
err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
APP_ERROR_CHECK(err_code);
-
nrf52832有两种扫描模式
- 主动扫描
可以获取广播包和广播回包
- 被动扫描
只能获取广播包数据
- 主动扫描
-
扫描间隔和扫描窗口
-
扫描持续时间
10ms为单位,如果为0,则一直进行扫描操作。
扫描滤波
nrf52832 SDK中有一个软件滤波功能,可以根据UUIDS、name、short name、MAC、appearance 过滤广播包。
首先要开启SDK中对应的过滤功能
然后设置开启滤波器即可。
/**@brief 扫描事件回调函数
*
* @param[in] p_scan_evt Scanning event.
*/
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
ret_code_t err_code;
switch(p_scan_evt->scan_evt_id)
case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
err_code = p_scan_evt->params.connecting_err.err_code;
APP_ERROR_CHECK(err_code);
break;
default:
break;
#define SCAN_INTERVAL 0x3000 /**< 扫描间隔 */
#define SCAN_WINDOW 0x3000 /**< 扫描窗口 */
#define SCAN_DURATION 0 /**< 持续扫描时间 */
static ble_gap_scan_params_t gap_scan =
.active = 0, //扫描模式:0:被动扫描; 1:主动扫描
.interval = SCAN_INTERVAL, //扫描间隔
.window = SCAN_WINDOW, //扫描窗口
.timeout = SCAN_DURATION, //扫描持续时间
.scan_phys = BLE_GAP_PHY_1MBPS,//1M
.filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL, //扫描信道
;
static uint8_t filter_mac_addr[6] = 0x11, 0x22, 0x33, 0x44, 0x55, 0x66;
/**@brief 扫描初始化
*/
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.connect_if_match = false; //如果开启过滤器,遇到匹配项是否直接进行连接
init_scan.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
init_scan.p_scan_param = &gap_scan;
err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
APP_ERROR_CHECK(err_code);
// 使能 MAC 滤波器
err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
APP_ERROR_CHECK(err_code);
// 设置 MAC 滤波器
err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, filter_mac_addr);
APP_ERROR_CHECK(err_code);
如果 init_scan.connect_if_match = true; 则当扫描到和滤波器匹配的广播包时,SDK会自带进行连接操作。
扫描滤波事件处理
/**@brief Enumeration for scanning events.
*
* @details These events are propagated to the main application if a handler is provided during
* the initialization of the Scanning Module. @ref NRF_BLE_SCAN_EVT_WHITELIST_REQUEST cannot be
* ignored if whitelist is used.
*/
typedef enum
NRF_BLE_SCAN_EVT_FILTER_MATCH, /**< 过滤器匹配事件. */
NRF_BLE_SCAN_EVT_WHITELIST_REQUEST, /**< 请求白名单 */
NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT, /**< 发现白名单中设备. */
NRF_BLE_SCAN_EVT_NOT_FOUND, /**< 过滤器不匹配事件. */
NRF_BLE_SCAN_EVT_SCAN_TIMEOUT, /**< 扫描超时. */
NRF_BLE_SCAN_EVT_CONNECTING_ERROR, /**< 连接错误. */
NRF_BLE_SCAN_EVT_CONNECTED /**< 连接 */
nrf_ble_scan_evt_t;
/**@brief 扫描事件回调函数
*
* @param[in] p_scan_evt Scanning event.
*/
static void scan_evt_handler(scan_evt_t const * p_scan_evt)
ret_code_t err_code;
switch(p_scan_evt->scan_evt_id)
case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
err_code = p_scan_evt->params.connecting_err.err_code;
APP_ERROR_CHECK(err_code);
break;
case NRF_BLE_SCAN_EVT_FILTER_MATCH:
//连接或者干一些其他事情
break;
default:
break;
扫描事件处理
扫描到广播后,会触发协议栈初始化中的观察者函数 ble_evt_handler,事件标志位为 BLE_GAP_EVT_ADV_REPORT,可以在事件中获取广播包的MAC信息、信道信息、接收信号强度信息和完整的广播包数据。
#define MACSTR "%02x %02x %02x %02x %02x %02x"
#define MAC2STR(mac) (mac)[0],(mac)[1],(mac)[2],(mac)[3],(mac)[4],(mac)[5]
/**@brief Function for handling BLE events.
*
* @param[in] p_ble_evt Bluetooth stack event.
* @param[in] p_context Unused.
*/
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
switch (p_ble_evt->header.evt_id)
case BLE_GAP_EVT_ADV_REPORT://接收到广播
ble_gap_evt_adv_report_t const * p_adv_report = &p_ble_evt->evt.gap_evt.params.adv_report;
if(0xc9 == p_adv_report->peer_addr.addr[5] && 0x81 == p_adv_report->peer_addr.addr[4] && 0xe9 == p_adv_report->peer_addr.addr[3])
NRF_LOG_INFO(" mac:"MACSTR, MAC2STR(p_adv_report->peer_addr.addr));
NRF_LOG_INFO(" channel %d", p_adv_report->ch_index);
NRF_LOG_INFO(" rssi %d", p_adv_report->rssi);
NRF_LOG_INFO(" data len: %d", p_adv_report->data.len);
break;
default:
break;
广播包数据解析
nrf52832 学习笔记(三)蓝牙从机广播提到如何将信息封装成结构体通过广播包发送出去,广播包数据解析反过来进行即可,nordic的SDK也提供了对应的函数,例如查找广播包是否存在对应名字信息。
以上是关于nrf52832 学习笔记蓝牙主机扫描的主要内容,如果未能解决你的问题,请参考以下文章