基于 NORDIC softDevice 蓝牙协议栈 S132
蓝牙角色: 从机,ble_peripheral
应用主函数 main() 中必须的函数:
ble_stack_init();
gap_params_init();
gatt_init();
services_init();
advertising_init();
advertising_start();
/**@brief Function for application main entry.*/
int main(void)
{
// Initialize.
log_init();
leds_init();
timers_init();
buttons_init();
power_management_init();
ble_stack_init();
gap_params_init();
gatt_init();
services_init();
advertising_init();
conn_params_init();
// Start execution.
NRF_LOG_INFO("Blinky example started.");
advertising_start();
application_timers_start();
// Enter main loop.
for (;;)
{
idle_state_handle();
}
}
ble_stack_init()
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL); 语句中, ble_evt_handler 为 BLE 事件回调函数 (handler for BLE events).
/**@brief Function for initializing the BLE stack.
* @details Initializes the SoftDevice and the BLE event interrupt.
*/
static void ble_stack_init(void)
{
ret_code_t err_code;
err_code = nrf_sdh_enable_request();
APP_ERROR_CHECK(err_code);
// Configure the BLE stack using the default settings.
// Fetch the start address of the application RAM.
uint32_t ram_start = 0;
err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
APP_ERROR_CHECK(err_code);
// Enable BLE stack.
err_code = nrf_sdh_ble_enable(&ram_start);
APP_ERROR_CHECK(err_code);
// Register a handler for BLE events.
NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
BLE 事件回调函数,ble_evt_handler
/**@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)
{
ret_code_t err_code;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
NRF_LOG_INFO("Connected");
bsp_board_led_on(CONNECTED_LED);
bsp_board_led_off(ADVERTISING_LED);
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
APP_ERROR_CHECK(err_code);
err_code = app_button_enable();
APP_ERROR_CHECK(err_code);
break;
case BLE_GAP_EVT_DISCONNECTED:
NRF_LOG_INFO("Disconnected");
bsp_board_led_off(CONNECTED_LED);
m_conn_handle = BLE_CONN_HANDLE_INVALID;
err_code = app_button_disable();
APP_ERROR_CHECK(err_code);
advertising_start();
break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported
err_code = sd_ble_gap_sec_params_reply(m_conn_handle,
BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
NULL,
NULL);
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_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
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;
}
}
BLE GAP 事件列表 (GAP Event IDs.); (BLE 事件回调函数 ble_evt_handler 中常处理的事件)
enum BLE_GAP_EVTS |
GAP Event IDs. IDs that uniquely identify an event coming from the stack to the application.
Enumerator | |
---|---|
BLE_GAP_EVT_CONNECTED | GAP BLE Event base. |
BLE_GAP_EVT_DISCONNECTED | GAP BLE Event base. Disconnected from peer. |
BLE_GAP_EVT_CONN_PARAM_UPDATE | GAP BLE Event base. Connection Parameters updated. |
BLE_GAP_EVT_SEC_PARAMS_REQUEST | GAP BLE Event base. Request to provide security parameters. |
BLE_GAP_EVT_SEC_INFO_REQUEST | GAP BLE Event base. Request to provide security information. |
BLE_GAP_EVT_PASSKEY_DISPLAY | GAP BLE Event base. Request to display a passkey to the user. |
BLE_GAP_EVT_KEY_PRESSED | GAP BLE Event base. Notification of a keypress on the remote device. |
BLE_GAP_EVT_AUTH_KEY_REQUEST | GAP BLE Event base. Request to provide an authentication key. |
BLE_GAP_EVT_LESC_DHKEY_REQUEST | GAP BLE Event base. Request to calculate an LE Secure Connections DHKey. |
BLE_GAP_EVT_AUTH_STATUS | GAP BLE Event base. Authentication procedure completed with status. |
BLE_GAP_EVT_CONN_SEC_UPDATE | GAP BLE Event base. Connection security updated. |
BLE_GAP_EVT_TIMEOUT | GAP BLE Event base. Timeout expired. |
BLE_GAP_EVT_RSSI_CHANGED | GAP BLE Event base. RSSI report. |
BLE_GAP_EVT_ADV_REPORT | GAP BLE Event base. Advertising report. |
BLE_GAP_EVT_SEC_REQUEST | GAP BLE Event base. Security Request. |
BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST | GAP BLE Event base. Connection Parameter Update Request. |
BLE_GAP_EVT_SCAN_REQ_REPORT | GAP BLE Event base. Scan request report. |
BLE_GAP_EVT_PHY_UPDATE_REQUEST | GAP BLE Event base. PHY Update Request. |
BLE_GAP_EVT_PHY_UPDATE | GAP BLE Event base. PHY Update Procedure is complete. |
BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST | GAP BLE Event base. Data Length Update Request. |
BLE_GAP_EVT_DATA_LENGTH_UPDATE | GAP BLE Event base. LL Data Channel PDU payload length updated. |
BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT | GAP BLE Event base. Channel survey report. |
BLE_GAP_EVT_ADV_SET_TERMINATED | GAP BLE Event base. Advertising set terminated. |
BLE GATT Server 事件列表 (GATT Server Event IDs.)(BLE 事件回调函数 ble_evt_handler 中常处理的事件)
enum BLE_GATTS_EVTS |
GATT Server Event IDs.
Enumerator | |
---|---|
BLE_GATTS_EVT_WRITE | GATTS BLE Event base. Write operation performed. |
BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST | Read/Write Authorization request. |
BLE_GATTS_EVT_SYS_ATTR_MISSING | A persistent system attribute access is pending. |
BLE_GATTS_EVT_HVC | Handle Value Confirmation. |
BLE_GATTS_EVT_SC_CONFIRM | Service Changed Confirmation. |
BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST | Exchange MTU Request. |
BLE_GATTS_EVT_TIMEOUT | Peer failed to respond to an ATT request in time. |
BLE_GATTS_EVT_HVN_TX_COMPLETE | Handle Value Notification transmission complete. |
BLE GATT Client 事件列表 (GATT Client Event IDs.)(BLE 事件回调函数 ble_evt_handler 中常处理的事件)
enum BLE_GATTC_EVTS |
GATT Client Event IDs.
Enumerator | |
---|---|
BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP | GATTC BLE Event base. Primary Service Discovery Response event. |
BLE_GATTC_EVT_REL_DISC_RSP | Relationship Discovery Response event. |
BLE_GATTC_EVT_CHAR_DISC_RSP | Characteristic Discovery Response event. |
BLE_GATTC_EVT_DESC_DISC_RSP | Descriptor Discovery Response event. |
BLE_GATTC_EVT_ATTR_INFO_DISC_RSP | Attribute Information Response event. |
BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP | Read By UUID Response event. |
BLE_GATTC_EVT_READ_RSP | Read Response event. |
BLE_GATTC_EVT_CHAR_VALS_READ_RSP | Read multiple Response event. |
BLE_GATTC_EVT_WRITE_RSP | Write Response event. |
BLE_GATTC_EVT_HVX | Handle Value Notification or Indication event. |
BLE_GATTC_EVT_EXCHANGE_MTU_RSP | Exchange MTU Response event. |
BLE_GATTC_EVT_TIMEOUT | Timeout event. |
BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE | Write without Response transmission complete. |
gap_params_init()
/**@brief Function for the GAP initialization.
* @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 = MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
gap_conn_params.slave_latency = SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;
err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);
}
gatt_init()
/**@brief Function for initializing the GATT module.*/
static void gatt_init(void)
{
ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
APP_ERROR_CHECK(err_code);
}
ret_code_t nrf_ble_gatt_init(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_handler_t evt_handler)
{
VERIFY_PARAM_NOT_NULL(p_gatt);
p_gatt->evt_handler = evt_handler;
p_gatt->att_mtu_desired_periph = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
p_gatt->att_mtu_desired_central = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
p_gatt->data_length = NRF_SDH_BLE_GAP_DATA_LENGTH;
for (uint32_t i = 0; i < NRF_BLE_GATT_LINK_COUNT; i++)
{
link_init(&p_gatt->links[i]);
}
return NRF_SUCCESS;
}
services_init()
本例 services_init() 中,实现的是 LED Button Service; 其具体内容根据应用需求修改。
/**@brief Function for initializing services that will be used by the application.
*/
static void services_init(void)
{
ret_code_t err_code;
ble_lbs_init_t init = {0};
nrf_ble_qwr_init_t qwr_init = {0};
// Initialize Queued Write Module.
qwr_init.error_handler = nrf_qwr_error_handler;
err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
APP_ERROR_CHECK(err_code);
// Initialize LBS.
init.led_write_handler = led_write_handler;
err_code = ble_lbs_init(&m_lbs, &init);
APP_ERROR_CHECK(err_code);
}
/**@brief Function for handling write events to the LED characteristic.
* @param[in] p_lbs Instance of LED Button Service to which the write applies.
* @param[in] led_state Written/desired state of the LED.
*/
static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t led_state)
{
if (led_state)
{
bsp_board_led_on(LEDBUTTON_LED);
NRF_LOG_INFO("Received LED ON!");
}
else
{
bsp_board_led_off(LEDBUTTON_LED);
NRF_LOG_INFO("Received LED OFF!");
}
}
advertising_init()
/**@brief Function for initializing the Advertising functionality.
* @details Encodes the required advertising data and passes it to the stack.
* Also builds a structure to be passed to the stack when starting advertising.
*/
static void advertising_init(void)
{
ret_code_t err_code;
ble_advdata_t advdata;
ble_advdata_t srdata;
ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};
// Build and set advertising data.
memset(&advdata, 0, sizeof(advdata));
advdata.name_type = BLE_ADVDATA_FULL_NAME;
advdata.include_appearance = true;
advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
memset(&srdata, 0, sizeof(srdata));
srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
srdata.uuids_complete.p_uuids = adv_uuids;
err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
APP_ERROR_CHECK(err_code);
err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
APP_ERROR_CHECK(err_code);
ble_gap_adv_params_t adv_params;
// Set advertising parameters.
memset(&adv_params, 0, sizeof(adv_params));
adv_params.primary_phy = BLE_GAP_PHY_1MBPS;
adv_params.duration = APP_ADV_DURATION;
adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
adv_params.p_peer_addr = NULL;
adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
adv_params.interval = APP_ADV_INTERVAL;
err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
APP_ERROR_CHECK(err_code);
}
BLE 广播重要函数 sd_ble_advdata_encode
ret_code_t ble_advdata_encode | ( | ble_advdata_t const *const | p_advdata, |
uint8_t *const | p_encoded_data, | ||
uint16_t *const | p_len | ||
) |
Function for encoding data in the Advertising and Scan Response data format (AD structures).
This function encodes data into the Advertising and Scan Response data format (AD structures) based on the fields in the supplied structures. This function can be used to create a payload of Advertising packet or Scan Response packet, or a payload of NFC message intended for initiating the Out-of-Band pairing.
Parameters
[in] | p_advdata | Pointer to the structure for specifying the content of encoded data. |
[out] | p_encoded_data | Pointer to the buffer where encoded data will be returned. |
[in,out] | p_len | in: Size of p_encoded_data buffer. out: Length of encoded data. |
Return values
NRF_SUCCESS | If the operation was successful. |
NRF_ERROR_INVALID_PARAM | If the operation failed because a wrong parameter was provided in p_advdata . |
NRF_ERROR_DATA_SIZE | If the operation failed because not all the requested data could fit into the provided buffer or some encoded AD structure is too long and its length cannot be encoded with one octet. |
Warning
This API may override the application's request to use the long name and use a short name instead. This truncation will occur in case the long name does not fit the provided buffer size. The application can specify a preferred short name length if truncation is required. For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name. However, it should be noted that this is just a preference that the application can specify, and if the preference is too large to fit in the provided buffer, the name can be truncated further.
BLE 广播重要函数 sd_ble_gap_adv_set_configure
uint32_t sd_ble_gap_adv_set_configure | ( | uint8_t * | p_adv_handle, |
ble_gap_adv_data_t const * | p_adv_data, | ||
ble_gap_adv_params_t const * | p_adv_params | ||
) |
Configure an advertising set. Set, clear or update advertising and scan response data.
Note
The format of the advertising data will be checked by this call to ensure interoperability. Limitations imposed by this API call to the data provided include having a flags data type in the scan response data and duplicating the local name in the advertising data and scan response data.
In order to update advertising data while advertising, new advertising buffers must be provided.
Relevant Message Sequence Charts
Advertising |
Whitelist Sharing |
Parameters
[in,out] | p_adv_handle | Provide a pointer to a handle containing BLE_GAP_ADV_SET_HANDLE_NOT_SET to configure a new advertising set. On success, a new handle is then returned through the pointer. Provide a pointer to an existing advertising handle to configure an existing advertising set. |
[in] | p_adv_data | Advertising data. If set to NULL, no advertising data will be used. See ble_gap_adv_data_t. |
[in] | p_adv_params | Advertising parameters. When this function is used to update advertising data while advertising, this parameter must be NULL. See ble_gap_adv_params_t. |
Return values
NRF_SUCCESS | Advertising set successfully configured. |
NRF_ERROR_INVALID_PARAM | Invalid parameter(s) supplied:
|
BLE_ERROR_GAP_INVALID_BLE_ADDR | ble_gap_adv_params_t::p_peer_addr is invalid. |
NRF_ERROR_INVALID_STATE | Invalid state to perform operation.
|
BLE_ERROR_GAP_DISCOVERABLE_WITH_WHITELIST | Discoverable mode and whitelist incompatible. |
BLE_ERROR_INVALID_ADV_HANDLE | The provided advertising handle was not found. Use BLE_GAP_ADV_SET_HANDLE_NOT_SET to configure a new advertising handle. |
NRF_ERROR_INVALID_ADDR | Invalid pointer supplied. |
NRF_ERROR_INVALID_FLAGS | Invalid combination of advertising flags supplied. |
NRF_ERROR_INVALID_DATA | Invalid data type(s) supplied. Check the advertising data format specification given in Bluetooth Specification Version 5.0, Volume 3, Part C, Chapter 11. |
NRF_ERROR_INVALID_LENGTH | Invalid data length(s) supplied. |
NRF_ERROR_NOT_SUPPORTED | Unsupported data length or advertising parameter configuration. |
NRF_ERROR_NO_MEM | Not enough memory to configure a new advertising handle. Update an existing advertising handle instead. |
BLE_ERROR_GAP_UUID_LIST_MISMATCH | Invalid UUID list supplied. |
advertising_start()
/**@brief Function for starting advertising.
*/
static void advertising_start(void)
{
ret_code_t err_code;
err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
APP_ERROR_CHECK(err_code);
bsp_board_led_on( ADVERTISING_LED );
}
BLE 广播重要函数 sd_ble_gap_adv_start
uint32_t sd_ble_gap_adv_start | ( | uint8_t | adv_handle, |
uint8_t | conn_cfg_tag | ||
) |
Start advertising (GAP Discoverable, Connectable modes, Broadcast Procedure).
Note
Only one advertiser may be active at any time.
Events generated
BLE_GAP_EVT_CONNECTED | Generated after connection has been established through connectable advertising. |
BLE_GAP_EVT_ADV_SET_TERMINATED | Advertising set has terminated. |
BLE_GAP_EVT_SCAN_REQ_REPORT | A scan request was received. |
Relevant Message Sequence Charts
Advertising |
Peripheral Connection Establishment with Private Peer |
Directed Advertising |
Whitelist Sharing |
Parameters
[in] | adv_handle | Advertising handle to advertise on, received from sd_ble_gap_adv_set_configure. |
[in] | conn_cfg_tag | Tag identifying a configuration set by sd_ble_cfg_set or BLE_CONN_CFG_TAG_DEFAULT to use the default connection configuration. For non-connectable advertising, this is ignored. |
Return values
NRF_SUCCESS | The BLE stack has started advertising. |
NRF_ERROR_INVALID_STATE | Invalid state to perform operation. adv_handle is not configured or already advertising. |
NRF_ERROR_CONN_COUNT | The limit of available connections has been reached; connectable advertiser cannot be started. |
BLE_ERROR_INVALID_ADV_HANDLE | Advertising handle not found. Configure a new adveriting handle with sd_ble_gap_adv_set_configure. |
NRF_ERROR_NOT_FOUND | conn_cfg_tag not found. |
NRF_ERROR_INVALID_PARAM | Invalid parameter(s) supplied:
|
NRF_ERROR_RESOURCES | Either:
|