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 学习笔记蓝牙主机扫描的主要内容,如果未能解决你的问题,请参考以下文章

nrf52832 学习笔记蓝牙从机广播

nrf52832 学习笔记蓝牙从机广播

nrf52832 学习笔记蓝牙主机发现服务

nrf52832 学习笔记蓝牙主机发现服务

nrf52832 学习笔记蓝牙主机发现服务

nrf52832 学习笔记蓝牙主从机连接和连接参数更新