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也提供了对应的函数,例如查找广播包是否存在对应名字信息。
在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值