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

Posted 不咸不要钱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了nrf52832 学习笔记蓝牙主从机连接和连接参数更新相关的知识,希望对你有一定的参考价值。

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

主机连接

nrf52832 SDK中主机连接从机需要使用 sd_ble_gap_connect(ble_gap_addr_t const *p_peer_addr, ble_gap_scan_params_t const *p_scan_params, ble_gap_conn_params_t const *p_conn_params, uint8_t conn_cfg_tag)函数. 参数为目标MAC地址, 扫描参数, 连接参数, 连接配置标签, 这些参数均可以在扫描初始化参数部分获取.

/**@brief Create a connection (GAP Link Establishment).
 *
 * @note If a scanning procedure is currently in progress it will be automatically stopped when calling this function.
 *       The scanning procedure will be stopped even if the function returns an error.
 *
 * @events
 * @event@ref BLE_GAP_EVT_CONNECTED, A connection was established.
 * @event@ref BLE_GAP_EVT_TIMEOUT, Failed to establish a connection.
 * @endevents
 *
 * @mscs
 * @mmsc@ref BLE_GAP_WL_SHARE_MSC
 * @mmsc@ref BLE_GAP_CENTRAL_CONN_PRIV_MSC
 * @mmsc@ref BLE_GAP_CENTRAL_CONN_MSC
 * @endmscs
 *
 * @param[in] p_peer_addr   Pointer to peer identity address. If @ref ble_gap_scan_params_t::filter_policy is set to use
 *                          whitelist, then p_peer_addr is ignored.
 * @param[in] p_scan_params Pointer to scan parameters structure.
 * @param[in] p_conn_params Pointer to desired connection parameters.
 * @param[in] conn_cfg_tag  Tag identifying a configuration set by @ref sd_ble_cfg_set or
 *                          @ref BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration.
 *
 * @retval ::NRF_SUCCESS Successfully initiated connection procedure.
 * @retval ::NRF_ERROR_INVALID_ADDR Invalid parameter(s) pointer supplied.
 * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
 *                                   - Invalid parameter(s) in p_scan_params or p_conn_params.
 *                                   - Use of whitelist requested but whitelist has not been set, see @ref sd_ble_gap_whitelist_set.
 *                                   - Peer address was not present in the device identity list, see @ref sd_ble_gap_device_identities_set.
 * @retval ::NRF_ERROR_NOT_FOUND conn_cfg_tag not found.
 * @retval ::NRF_ERROR_INVALID_STATE The SoftDevice is in an invalid state to perform this operation. This may be due to an
 *                                   existing locally initiated connect procedure, which must complete before initiating again.
 * @retval ::BLE_ERROR_GAP_INVALID_BLE_ADDR Invalid Peer address.
 * @retval ::NRF_ERROR_CONN_COUNT The limit of available connections for this connection configuration tag has been reached.
 *                                To increase the number of available connections,
 *                                use @ref sd_ble_cfg_set with @ref BLE_GAP_CFG_ROLE_COUNT or @ref BLE_CONN_CFG_GAP.
 * @retval ::NRF_ERROR_RESOURCES Either:
 *                                 - Not enough BLE role slots available.
 *                                   Stop one or more currently active roles (Central, Peripheral or Observer) and try again.
 *                                 - The event_length parameter associated with conn_cfg_tag is too small to be able to
 *                                   establish a connection on the selected @ref ble_gap_scan_params_t::scan_phys.
 *                                   Use @ref sd_ble_cfg_set to increase the event length.
 * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported PHYs supplied to the call.
 */
SVCALL(SD_BLE_GAP_CONNECT, uint32_t, sd_ble_gap_connect(ble_gap_addr_t const *p_peer_addr, ble_gap_scan_params_t const *p_scan_params, ble_gap_conn_params_t const *p_conn_params, uint8_t conn_cfg_tag));

SDK自动连接

nrf52832 学习笔记(四)蓝牙主机扫描中,扫描初始化时如果开启了软件过滤器,可以配置 init_scan.connect_if_match = true;开启自动连接功能.

/**@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 = true;   //如果开启过滤器,遇到匹配项是否直接进行连接
    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);

当扫描到广播包后,在nrf_ble_scan.c 的观察者回调函数中,使用软件滤波器对广播包进行过滤,如果广播包通过过滤,则调用 sd_ble_gap_connect 函数连接从机.


手动连接

SDK中的软件滤波器可以适用于大部分情况,有时要连接的从机比较特殊,无法使用自动连接时就需要手动连接从机了.
在主机扫描到广播包后,协议栈观察者回调函数 BLE_GAP_EVT_ADV_REPORT 事件处理中,对广播包进行自定义分析处理,分析处理结束后,就可以调用 sd_ble_gap_connect 函数进行连接处理了.连接函数使用的参数均可以在扫描初始化部分找到.

/**@brief Function for establishing the connection with a device.
 *
 * @details Connection is established if @ref NRF_BLE_SCAN_EVT_FILTER_MATCH
 *          or @ref NRF_BLE_SCAN_EVT_WHITELIST_ADV_REPORT occurs and the module was
 *          initialized in the automatic connection mode. This function can generate an event
 *          to the main application when @ref sd_ble_gap_connect is used inside the function and it returns value
 *          that is different than @ref NRF_SUCCESS.
 *
 * @param[in] p_scan_ctx   Pointer to the Scanning Module instance.
 * @param[in] p_adv_report Advertising data.
 */
static void nrf_ble_scan_connect_with_target(nrf_ble_scan_t           const * const p_scan_ctx,
                                             ble_gap_evt_adv_report_t const * const p_adv_report)

    ret_code_t err_code;
    scan_evt_t scan_evt;

    // For readability.
    ble_gap_addr_t const        * p_addr        = &p_adv_report->peer_addr;
    ble_gap_scan_params_t const * p_scan_params = &p_scan_ctx->scan_params;
    ble_gap_conn_params_t const * p_conn_params = &p_scan_ctx->conn_params;
    uint8_t                       con_cfg_tag   = p_scan_ctx->conn_cfg_tag;

    // Return if the automatic connection is disabled.
    if (!p_scan_ctx->connect_if_match)
    
        return;
    

    // Stop scanning.
    nrf_ble_scan_stop();

    memset(&scan_evt, 0, sizeof(scan_evt));

    // Establish connection.
    err_code = sd_ble_gap_connect(p_addr,
                                  p_scan_params,
                                  p_conn_params,
                                  con_cfg_tag);

    NRF_LOG_DEBUG("Connecting");

    scan_evt.scan_evt_id                    = NRF_BLE_SCAN_EVT_CONNECTING_ERROR;
    scan_evt.params.connecting_err.err_code = err_code;

    NRF_LOG_DEBUG("Connection status: %d", err_code);

    // If an error occurred, send an event to the event handler.
    if ((err_code != NRF_SUCCESS) && (p_scan_ctx->evt_handler != NULL))
    
        p_scan_ctx->evt_handler(&scan_evt);
    


/**@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;
            
//                NRF_LOG_INFO("mac:"MACSTR, MAC2STR(p_adv_report->peer_addr.addr));
//                NRF_LOG_INFO(" rssi %d", p_adv_report->rssi);
//                NRF_LOG_INFO(" data len: %d", p_adv_report->data.len);
            
            //自定义处理
            //......

			//连接从机
			nrf_ble_scan_connect_with_target(&m_scan, p_adv_report);
            break;
        
        default:
            break;
    

MTU交换

MTU全称为 Maximum Transmission Unit(最大传输单元),指在一个PDU(Protocol Data Unit 协议数据单元)中能传输的最大数据量.BLE4.0时 MTU为固定的23个字节,BLE4.2以后, MTU为可变的 23-247字节. 为了兼容之前的BLE4.0,蓝牙在连接后会进行MTU交换,主机告诉从机,主机的MTU是多少,从机再回复主机,从机的MTU是多少.然后主从机选择使用较小的MTU值.

由于蓝牙在通信时必须保证MTU一致,因此蓝牙连接后必须要先进行MTU交换. nrf52832 SDK中会自动完成MTU交换工作.
在GATT初始化时会注册一个GATT 观察者回调函数, 发生连接事件后会在该回调函数中进行MTU交换

连接参数更新

从机

在从机连接参数初始化时,从机会创建软件定时器

当连接到主机时,在观察者回调函数中会开启软件定时器



在软件定时器超时回调函数中,进行参数更新

主机

接收到从机的连接参数更新请求后,会触发连接参数请求更新事件,如果同意从机的连接参数,则在连接参数更新事件里面更新主机的连接参数.

PHY 物理层参数更新

蓝牙5.0 以后,蓝牙的物理层由原来的只支持1M 变为了 可选的1M , 2M ,500K, 125K等速率. 需要高速数据通信时可以在主从机连接后将物理层参数更新为2M,当然物理层速率越高,传输距离越近.nrf52832 支持 1M 和 2M速率的物理层.

从机广播初始化和主机扫描初始化时均可以设置物理层信息,如果没有设置则默认为1M, 连接后主机和从机都可以发出物理层更新请求,收到物理层更新请求后进行物理层参数更新.物理层更新请求和物理层参数更新均使用协议栈函数 sd_ble_gap_phy_update

/**@brief Initiate or respond to a PHY Update Procedure
 *
 * @details   This function is used to initiate or respond to a PHY Update Procedure. It will always
 *            generate a @ref BLE_GAP_EVT_PHY_UPDATE event if successfully executed.
 *            If this function is used to initiate a PHY Update procedure and the only option
 *            provided in @ref ble_gap_phys_t::tx_phys and @ref ble_gap_phys_t::rx_phys is the
 *            currently active PHYs in the respective directions, the SoftDevice will generate a
 *            @ref BLE_GAP_EVT_PHY_UPDATE with the current PHYs set and will not initiate the
 *            procedure in the Link Layer.
 *
 *            If @ref ble_gap_phys_t::tx_phys or @ref ble_gap_phys_t::rx_phys is @ref BLE_GAP_PHY_AUTO,
 *            then the stack will select PHYs based on the peer's PHY preferences and the local link
 *            configuration. The PHY Update procedure will for this case result in a PHY combination
 *            that respects the time constraints configured with @ref sd_ble_cfg_set and the current
 *            link layer data length.
 *
 *            When acting as a central, the SoftDevice will select the fastest common PHY in each direction.
 *
 *            If the peer does not support the PHY Update Procedure, then the resulting
 *            @ref BLE_GAP_EVT_PHY_UPDATE event will have a status set to
 *            @ref BLE_HCI_UNSUPPORTED_REMOTE_FEATURE.
 *
 *            If the PHY Update procedure was rejected by the peer due to a procedure collision, the status
 *            will be @ref BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION or
 *            @ref BLE_HCI_DIFFERENT_TRANSACTION_COLLISION.
 *            If the peer responds to the PHY Update procedure with invalid parameters, the status
 *            will be @ref BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS.
 *            If the PHY Update procedure was rejected by the peer for a different reason, the status will
 *            contain the reason as specified by the peer.
 *
 * @events
 * @event@ref BLE_GAP_EVT_PHY_UPDATE, Result of the PHY Update Procedure.
 * @endevents
 *
 * @mscs
 * @mmsc@ref BLE_GAP_CENTRAL_PHY_UPDATE
 * @mmsc@ref BLE_GAP_PERIPHERAL_PHY_UPDATE
 * @endmscs
 *
 * @param[in] conn_handle   Connection handle to indicate the connection for which the PHY Update is requested.
 * @param[in] p_gap_phys    Pointer to PHY structure.
 *
 * @retval ::NRF_SUCCESS Successfully requested a PHY Update.
 * @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
 * @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied.
 * @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
 * @retval ::NRF_ERROR_NOT_SUPPORTED Unsupported PHYs supplied to the call.
 * @retval ::NRF_ERROR_INVALID_STATE No link has been established.
 * @retval ::NRF_ERROR_BUSY Procedure is already in progress or not allowed at this time. Process pending events and wait for the pending procedure to complete and retry.
 *
 */
SVCALL(SD_BLE_GAP_PHY_UPDATE, uint32_t, sd_ble_gap_phy_update(uint16_t conn_handle, ble_gap_phys_t const *p_gap_phys));

以上是关于nrf52832 学习笔记蓝牙主从机连接和连接参数更新的主要内容,如果未能解决你的问题,请参考以下文章

nrf52832 学习笔记配对和绑定

nrf52832 学习笔记蓝牙从机广播

nrf52832 学习笔记蓝牙从机广播

nrf52832 学习笔记配对和绑定

nrf52832 学习笔记蓝牙主机扫描

nrf52832 学习笔记蓝牙主机扫描