NRF52832学习笔记(29)——主从一体


一、简介

一个蓝牙设备同时作为主设备和从设备进行使用,这种能力的节点设备称为主从一体设备。

主从一体提供了扩展 BLE 蓝牙模块的能力,自从一个被称为“链路层拓扑”的功能被添加到蓝牙规范中后,就已经允许蓝牙设备同时作为主设备和从设备,在任何角色组合中操作。

NRF52832学习笔记(29)——主从一体

二、ble_app_hrs_rscs_relay

打开工程 不同SDK\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay

2.1 main

主从一体设备中,如何实现该设备即作为主机又作为从机,关键的问题就是主机和从机事件的切换。首先必须把主机服务和从机服务搭建起来,初始化两种服务类型,然后解决主机的扫描然后发起连接部分、从机的广播然后被连接部分,当两个类型的服务被搭建后,就开始处理蓝牙事件,决定数据流向。
NRF52832学习笔记(29)——主从一体

2.1.1 scan_init

设置一些扫描参数,如名字过滤、UUID过滤。

/**@brief Function for initialization the scanning and setting the filters.
*/
static 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.p_scan_param = &m_scan_param;

err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
APP_ERROR_CHECK(err_code);

if (strlen(m_target_periph_name) != 0)
{
err_code = nrf_ble_scan_filter_set(&m_scan,
SCAN_NAME_FILTER,
m_target_periph_name);
APP_ERROR_CHECK(err_code);
}

err_code = nrf_ble_scan_filter_set(&m_scan,
SCAN_UUID_FILTER,
&m_adv_uuids[HART_RATE_SERVICE_UUID_IDX]);
APP_ERROR_CHECK(err_code);

err_code = nrf_ble_scan_filter_set(&m_scan,
SCAN_UUID_FILTER,
&m_adv_uuids[RSCS_SERVICE_UUID_IDX]);
APP_ERROR_CHECK(err_code);

err_code = nrf_ble_scan_filters_enable(&m_scan,
NRF_BLE_SCAN_ALL_FILTER,
false);
APP_ERROR_CHECK(err_code);

}

2.1.2 gap_params_init

设置广播中蓝牙名称,连接参数。

/**@brief Function for initializing the GAP.
*
* @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
* device, including the device name, appearance, and the preferred connection parameters.
*/
static void gap_params_init(void)
{
ret_code_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *)DEVICE_NAME,
strlen(DEVICE_NAME));
APP_ERROR_CHECK(err_code);

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

gap_conn_params.min_conn_interval = m_scan.conn_params.min_conn_interval;
gap_conn_params.max_conn_interval = m_scan.conn_params.max_conn_interval;
gap_conn_params.slave_latency = m_scan.conn_params.slave_latency;
gap_conn_params.conn_sup_timeout = m_scan.conn_params.conn_sup_timeout;

err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
}

2.1.3 conn_params_init

连接参数初始化主要作为从机更新连接参数使用。

/**@brief Function for initializing the Connection Parameters module.
*/
static void conn_params_init(void)
{
ret_code_t err_code;
ble_conn_params_init_t cp_init;

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

cp_init.p_conn_params = NULL;
cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY;
cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT;
cp_init.start_on_notify_cccd_handle = BLE_CONN_HANDLE_INVALID; // Start upon connection.
cp_init.disconnect_on_fail = true;
cp_init.evt_handler = NULL; // Ignore events.
cp_init.error_handler = conn_params_error_handler;

err_code = ble_conn_params_init(&cp_init);
APP_ERROR_CHECK(err_code);
}

2.1.4 advertising_init

从机服务建立后,就需要对广播进行设置,广播是从机被主机发现的前提条件。

/**@brief Function for initializing the advertising functionality.
*/
static void advertising_init(void)
{
ret_code_t err_code;
ble_advertising_init_t init;

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

init.advdata.name_type = BLE_ADVDATA_FULL_NAME;
init.advdata.include_appearance = true;
init.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
init.advdata.uuids_complete.p_uuids = m_adv_uuids;

init.config.ble_adv_fast_enabled = true;
init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
init.config.ble_adv_fast_timeout = APP_ADV_DURATION;

init.evt_handler = on_adv_evt;

err_code = ble_advertising_init(&m_advertising, &init);
APP_ERROR_CHECK(err_code);

ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

2.1.5 adv_scan_start

广播和扫描同时运行

/**@brief Function for initializing the advertising and the scanning.
*/
static void adv_scan_start(void)
{
ret_code_t err_code;

//check if there are no flash operations in progress
if (!nrf_fstorage_is_busy(NULL)) // 检测如果没有flash操作
{
// Start scanning for peripherals and initiate connection to devices which
// advertise Heart Rate or Running speed and cadence UUIDs.
scan_start(); // 开始扫描

// Turn on the LED to signal scanning.
bsp_board_led_on(CENTRAL_SCANNING_LED);

// Start advertising. // 开始广播
err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);
}
}

三、蓝牙协议栈主机事件

当主机发起连接成功,或断开连接时,产生主机事件

/**@brief   Function for handling BLE events from the central application.
*
* @details This function parses scanning reports and initiates a connection to peripherals when a
* target UUID is found. It updates the status of LEDs used to report the central application
* activity.
*
* @param[in] p_ble_evt Bluetooth stack event.
*/
static void on_ble_central_evt(ble_evt_t const * p_ble_evt)
{
ret_code_t err_code;
ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

switch (p_ble_evt->header.evt_id)
{
// Upon connection, check which peripheral is connected (HR or RSC), initiate DB
// discovery, update LEDs status, and resume scanning, if necessary.
case BLE_GAP_EVT_CONNECTED:
{
NRF_LOG_INFO("Central connected");
// If no Heart Rate sensor or RSC sensor is currently connected, try to find them on this peripheral.
if ( (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID)
|| (m_conn_handle_rscs_c == BLE_CONN_HANDLE_INVALID))
{
NRF_LOG_INFO("Attempt to find HRS or RSC on conn_handle 0x%x", p_gap_evt->conn_handle);

err_code = ble_db_discovery_start(&m_db_discovery[0], p_gap_evt->conn_handle);
if (err_code == NRF_ERROR_BUSY)
{
err_code = ble_db_discovery_start(&m_db_discovery[1], p_gap_evt->conn_handle);
APP_ERROR_CHECK(err_code);
}
else
{
APP_ERROR_CHECK(err_code);
}
}

// Assign connection handle to the QWR module.
multi_qwr_conn_handle_assign(p_gap_evt->conn_handle);

// Update LEDs status, and check whether to look for more peripherals to connect to.
bsp_board_led_on(CENTRAL_CONNECTED_LED);
if (ble_conn_state_central_conn_count() == NRF_SDH_BLE_CENTRAL_LINK_COUNT)
{
bsp_board_led_off(CENTRAL_SCANNING_LED);
}
else
{
// Resume scanning.
bsp_board_led_on(CENTRAL_SCANNING_LED);
scan_start();
}
} break; // BLE_GAP_EVT_CONNECTED

// Upon disconnection, reset the connection handle of the peer that disconnected,
// update the LEDs status and start scanning again.
case BLE_GAP_EVT_DISCONNECTED:
{
if (p_gap_evt->conn_handle == m_conn_handle_hrs_c)
{
NRF_LOG_INFO("HRS central disconnected (reason: %d)",
p_gap_evt->params.disconnected.reason);

m_conn_handle_hrs_c = BLE_CONN_HANDLE_INVALID;

err_code = nrf_ble_scan_filter_set(&m_scan,
SCAN_UUID_FILTER,
&m_adv_uuids[HART_RATE_SERVICE_UUID_IDX]);
APP_ERROR_CHECK(err_code);
}
if (p_gap_evt->conn_handle == m_conn_handle_rscs_c)
{
NRF_LOG_INFO("RSC central disconnected (reason: %d)",
p_gap_evt->params.disconnected.reason);

m_conn_handle_rscs_c = BLE_CONN_HANDLE_INVALID;

err_code = nrf_ble_scan_filter_set(&m_scan,
SCAN_UUID_FILTER,
&m_adv_uuids[RSCS_SERVICE_UUID_IDX]);
APP_ERROR_CHECK(err_code);
}

if ( (m_conn_handle_rscs_c == BLE_CONN_HANDLE_INVALID)
|| (m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID))
{
// Start scanning.
scan_start();

// Update LEDs status.
bsp_board_led_on(CENTRAL_SCANNING_LED);
}

if (ble_conn_state_central_conn_count() == 0)
{
bsp_board_led_off(CENTRAL_CONNECTED_LED);
}
} break; // BLE_GAP_EVT_DISCONNECTED

case BLE_GAP_EVT_TIMEOUT:
{
// No timeout for scanning is specified, so only connection attemps can timeout.
if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
{
NRF_LOG_INFO("Connection Request timed out.");
}
} break;

case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
{
// Accept parameters requested by peer.
err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
&p_gap_evt->params.conn_param_update_request.conn_params);
APP_ERROR_CHECK(err_code);
} break;

case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
} break;

case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
NRF_LOG_DEBUG("GATT Client Timeout.");
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;

case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
NRF_LOG_DEBUG("GATT Server Timeout.");
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;

default:
// No implementation needed.
break;
}
}

四、蓝牙协议栈从机事件

当从机被连接,或断开连接时,产生从机事件

/**@brief   Function for handling BLE events from peripheral applications.
* @details Updates the status LEDs used to report the activity of the peripheral applications.
*
* @param[in] p_ble_evt Bluetooth stack event.
*/
static void on_ble_peripheral_evt(ble_evt_t const * p_ble_evt)
{
ret_code_t err_code;
ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;

switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
NRF_LOG_INFO("Peripheral connected");
bsp_board_led_off(PERIPHERAL_ADVERTISING_LED);
bsp_board_led_on(PERIPHERAL_CONNECTED_LED);

// Assign connection handle to the QWR module.
multi_qwr_conn_handle_assign(p_ble_evt->evt.gap_evt.conn_handle);
break;

case BLE_GAP_EVT_DISCONNECTED:
NRF_LOG_INFO("Peripheral disconnected. conn_handle: 0x%x, reason: 0x%x",
p_gap_evt->conn_handle,
p_gap_evt->params.disconnected.reason);

bsp_board_led_off(PERIPHERAL_CONNECTED_LED);
break;

case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
{
NRF_LOG_DEBUG("PHY update request.");
ble_gap_phys_t const phys =
{
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
APP_ERROR_CHECK(err_code);
} break;

case BLE_GATTC_EVT_TIMEOUT:
// Disconnect on GATT Client timeout event.
NRF_LOG_DEBUG("GATT Client Timeout.");
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;

case BLE_GATTS_EVT_TIMEOUT:
// Disconnect on GATT Server timeout event.
NRF_LOG_DEBUG("GATT Server Timeout.");
err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
APP_ERROR_CHECK(err_code);
break;

default:
// No implementation needed.
break;
}
}


• 由 Leung 写于 2020 年 9 月 30 日

• 参考:青风电子社区

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

NRF52832学习笔记(29)——主从一体

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » NRF52832学习笔记(29)——主从一体
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏