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));
在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全称为 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交换
在从机连接参数初始化时,从机会创建软件定时器
当连接到主机时,在观察者回调函数中会开启软件定时器
在软件定时器超时回调函数中,进行参数更新
接收到从机的连接参数更新请求后,会触发连接参数请求更新事件,如果同意从机的连接参数,则在连接参数更新事件里面更新主机的连接参数.
蓝牙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));