- 目的
如何在从模式的工程增加一个蓝牙主模式服务,方便快速了解工程的整合,本例是在ble外设的uart蓝牙实例上添加来
介绍的
- 添加步骤
在nRF_BLE目录中添加nrf_ble_scan.c和ble_db_discovery.c两个文件,在nRF_BLE_Services目录下添加
ble_nus_c.c文件
step 2:在C/C++选项的Include Paths中,添加以下路径
在main.c中加入头文件 #include "ble_db_discovery.h" #include "ble_nus_c.h" #include "nrf_ble_scan.h" #include "ble_advdata.h"
step 4:定义以下几个变量
BLE_NUS_C_DEF(m_ble_nus_c); /**< BLE Nordic UART Service (NUS) client instance. */ BLE_DB_DISCOVERY_DEF(m_db_disc); /**< Database discovery module instance. */ NRF_BLE_SCAN_DEF(m_scan); /**< Scanning Module instance. */ /**@brief NUS UUID. */ static ble_uuid_t const m_nus_uuid = { .uuid = BLE_UUID_NUS_SERVICE, .type = NUS_SERVICE_UUID_TYPE };
static uint16_t m_center_handle = BLE_CONN_HANDLE_INVALID;
step 5:在sdk_config.h中加入宏,注意红色字体的内容
// 主扫描设置
// BLE_DB_DISCOVERY_ENABLED - ble_db_discovery - Database discovery module
#ifndef BLE_DB_DISCOVERY_ENABLED
#define BLE_DB_DISCOVERY_ENABLED 1
#endif
// NRF_BLE_SCAN_ENABLED - nrf_ble_scan - Scanning Module
//==========================================================
#ifndef NRF_BLE_SCAN_ENABLED
#define NRF_BLE_SCAN_ENABLED 1
#endif
// NRF_BLE_SCAN_BUFFER - Data length for an advertising set.
#ifndef NRF_BLE_SCAN_BUFFER
#define NRF_BLE_SCAN_BUFFER 31
#endif
// NRF_BLE_SCAN_NAME_MAX_LEN - Maximum size for the name to search in the advertisement report.
#ifndef NRF_BLE_SCAN_NAME_MAX_LEN
#define NRF_BLE_SCAN_NAME_MAX_LEN 32
#endif
// NRF_BLE_SCAN_SHORT_NAME_MAX_LEN - Maximum size of the short name to search for in the advertisement report.
#ifndef NRF_BLE_SCAN_SHORT_NAME_MAX_LEN
#define NRF_BLE_SCAN_SHORT_NAME_MAX_LEN 32
#endif
// NRF_BLE_SCAN_SCAN_INTERVAL - Scanning interval. Determines the scan interval in units of 0.625 millisecond.
#ifndef NRF_BLE_SCAN_SCAN_INTERVAL
#define NRF_BLE_SCAN_SCAN_INTERVAL 160
#endif
// NRF_BLE_SCAN_SCAN_DURATION - Duration of a scanning session in units of 10 ms. Range: 0x0001 - 0xFFFF (10 ms to 10.9225 ms). If set to 0x0000, the scanning continues until it is explicitly disabled.
#ifndef NRF_BLE_SCAN_SCAN_DURATION
#define NRF_BLE_SCAN_SCAN_DURATION 0
#endif
// NRF_BLE_SCAN_SCAN_WINDOW - Scanning window. Determines the scanning window in units of 0.625 millisecond.
#ifndef NRF_BLE_SCAN_SCAN_WINDOW
#define NRF_BLE_SCAN_SCAN_WINDOW 80
#endif
// NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL - Determines minimum connection interval in milliseconds.
#ifndef NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL
#define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 7.5
#endif
// NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL - Determines maximum connection interval in milliseconds.
#ifndef NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL
#define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 30
#endif
// NRF_BLE_SCAN_SLAVE_LATENCY - Determines the slave latency in counts of connection events.
#ifndef NRF_BLE_SCAN_SLAVE_LATENCY
#define NRF_BLE_SCAN_SLAVE_LATENCY 0
#endif
// NRF_BLE_SCAN_SUPERVISION_TIMEOUT - Determines the supervision time-out in units of 10 millisecond.
#ifndef NRF_BLE_SCAN_SUPERVISION_TIMEOUT
#define NRF_BLE_SCAN_SUPERVISION_TIMEOUT 4000
#endif
// NRF_BLE_SCAN_SCAN_PHY - PHY to scan on.
// BLE_GAP_PHY_AUTO
// BLE_GAP_PHY_1MBPS
// BLE_GAP_PHY_2MBPS
// BLE_GAP_PHY_CODED
// BLE_GAP_PHY_NOT_SET
#ifndef NRF_BLE_SCAN_SCAN_PHY
#define NRF_BLE_SCAN_SCAN_PHY 1
#endif
// NRF_BLE_SCAN_FILTER_ENABLE - Enabling filters for the Scanning Module.
//==========================================================
#ifndef NRF_BLE_SCAN_FILTER_ENABLE
#define NRF_BLE_SCAN_FILTER_ENABLE 1
#endif
// NRF_BLE_SCAN_UUID_CNT - Number of filters for UUIDs.
#ifndef NRF_BLE_SCAN_UUID_CNT
#define NRF_BLE_SCAN_UUID_CNT 1
#endif
// NRF_BLE_SCAN_NAME_CNT - Number of name filters.
#ifndef NRF_BLE_SCAN_NAME_CNT
#define NRF_BLE_SCAN_NAME_CNT 0
#endif
// NRF_BLE_SCAN_SHORT_NAME_CNT - Number of short name filters.
#ifndef NRF_BLE_SCAN_SHORT_NAME_CNT
#define NRF_BLE_SCAN_SHORT_NAME_CNT 0
#endif
// NRF_BLE_SCAN_ADDRESS_CNT - Number of address filters.
#ifndef NRF_BLE_SCAN_ADDRESS_CNT
#define NRF_BLE_SCAN_ADDRESS_CNT 0
#endif
// NRF_BLE_SCAN_APPEARANCE_CNT - Number of appearance filters.
#ifndef NRF_BLE_SCAN_APPEARANCE_CNT
#define NRF_BLE_SCAN_APPEARANCE_CNT 0
#endif
//
//
//
// BLE_NUS_C_ENABLED - ble_nus_c - Nordic UART Central Service
#ifndef BLE_NUS_C_ENABLED#define BLE_NUS_C_ENABLED 1 #endif
// Requested BLE GAP data length to be negotiated.
#ifndef NRF_SDH_BLE_GAP_DATA_LENGTH #define NRF_SDH_BLE_GAP_DATA_LENGTH 251 #endif
// NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - Maximum number of peripheral links. #ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT #define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1 #endif
// NRF_SDH_BLE_CENTRAL_LINK_COUNT - Maximum number of central links. #ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 1 #endif
// NRF_SDH_BLE_TOTAL_LINK_COUNT - Total link count. // Maximum number of total concurrent connections using the default configuration.
#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT#define NRF_SDH_BLE_TOTAL_LINK_COUNT 2 #endif
// NRF_SDH_BLE_GAP_EVENT_LENGTH - GAP event length. // The time set aside for this connection on every connection interval in 1.25 ms units.
#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH #define NRF_SDH_BLE_GAP_EVENT_LENGTH 6 #endif
// NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. #ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247 #endif
// NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. #ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE #define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408 #endif
// NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. #ifndef NRF_SDH_BLE_VS_UUID_COUNT #define NRF_SDH_BLE_VS_UUID_COUNT 1 #endif
// NRF_SDH_BLE_SERVICE_CHANGED - Include the Service Changed characteristic in the Attribute Table.
#ifndef NRF_SDH_BLE_SERVICE_CHANGED #define NRF_SDH_BLE_SERVICE_CHANGED 0 #endif
// Enable/disable central-specific Peer Manager functionality.
#ifndef PM_CENTRAL_ENABLED #define PM_CENTRAL_ENABLED 1 #endif //
//
step 6:在main.c中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) { uint32_t err_code; uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle; uint16_t role = ble_conn_state_role(conn_handle); switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED:
// Based on the role this device plays in the connection, dispatch to the right handler. if (role == BLE_GAP_ROLE_PERIPH) { NRF_LOG_INFO("Connected"); m_conn_handle = conn_handle; err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle); APP_ERROR_CHECK(err_code); } else if (role == BLE_GAP_ROLE_CENTRAL) { m_center_handle = conn_handle; err_code = ble_nus_c_handles_assign(&m_ble_nus_c, m_center_handle, NULL); APP_ERROR_CHECK(err_code);
// start discovery of services. The NUS Client waits for a discovery result err_code = ble_db_discovery_start(&m_db_disc, m_center_handle); APP_ERROR_CHECK(err_code); } break;
case BLE_GAP_EVT_DISCONNECTED: NRF_LOG_INFO("Disconnected"); // LED indication will be changed when advertising starts. if (role == BLE_GAP_ROLE_PERIPH) { m_conn_handle = BLE_CONN_HANDLE_INVALID; } else if (role == BLE_GAP_ROLE_CENTRAL) { m_center_handle = BLE_CONN_HANDLE_INVALID; } 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_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_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. 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. 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; } }
step 7:在main.c中加入扫描数据报告代码typedef struct { uint8_t addr[6]; uint8_t data[32]; uint8_t len; int8_t rssi; }SCAN_DATA_INFO;
SCAN_DATA_INFO scanInfo[16]; uint8_t scanTotal;
void clearScanInfo(void) { for(uint8_t i=0;i=6) { return 0; } } } } return 1; }
/**@brief Function for handling Scanning Module events. */ static void scan_evt_handler(scan_evt_t const * p_scan_evt) { ret_code_t err_code; uint16_t data_offset = 0; uint8_t i; 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_NOT_FOUND: if(scanTotal < 16) { if(searchMac(p_scan_evt)) { scanInfo[scanTotal].len = ble_advdata_search(p_scan_evt->params.p_not_found->data.p_data, p_scan_evt->params.p_not_found->data.len, &data_offset, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME); if(scanInfo[scanTotal].len == 0) break; strncpy((char*)scanInfo[scanTotal].data,(const char*)&p_scan_evt->params.p_not_found
->data.p_data[data_offset],scanInfo[scanTotal].len); scanInfo[scanTotal].rssi = p_scan_evt->params.p_not_found->rssi; for(i=0;iparams.p_not_found->peer_addr.addr[i]; } for(uint8_t j=0;jparams.connected.p_connected; // Scan is automatically stopped by the connection. NRF_LOG_INFO("Connecting to target %02x%02x%02x%02x%02x%02x", p_connected->peer_addr.addr[0], p_connected->peer_addr.addr[1], p_connected->peer_addr.addr[2], p_connected->peer_addr.addr[3], p_connected->peer_addr.addr[4], p_connected->peer_addr.addr[5] ); clearScanInfo(); } break;
case NRF_BLE_SCAN_EVT_SCAN_TIMEOUT: { NRF_LOG_INFO("Scan timed out."); scan_start(); } break;
default: break; } }
step 8:在main.c中定义定时器变量及定时事件函数
#define TICK_1HZ_INTERVAL APP_TIMER_TICKS(1000) APP_TIMER_DEF(m_1hz_id); static volatile uint8_t tickFlag;
/**@brief Function for handling the Battery measurement timer timeout. * * @details This function will be called each time the battery level measurement timer expires. * * @param[in] p_context Pointer used for passing some arbitrary information (context) from the * app_start_timer() call to the timeout handler. */static void tick_1hz_timeout_handler(void * p_context) { UNUSED_PARAMETER(p_context); tickFlag = 1; }
/**@brief Function for starting application timers. */ static void application_timers_start(void) { ret_code_t err_code;
// Start application timers. err_code = app_timer_start(m_1hz_id, TICK_1HZ_INTERVAL, NULL); APP_ERROR_CHECK(err_code);
}
/**@brief Function for initializing the timer module. */ static void timers_init(void) { ret_code_t err_code = app_timer_init(); APP_ERROR_CHECK(err_code); err_code = app_timer_create(&m_1hz_id, APP_TIMER_MODE_REPEATED, tick_1hz_timeout_handler); APP_ERROR_CHECK(err_code); }
step 9:在main.c中的ble_nus_chars_received_uart_print函数打印数据
/**@brief Function for handling characters received by the Nordic UART Service (NUS). * * @details This function takes a list of characters of length data_len and prints the characters out on UART. * If @ref ECHOBACK_BLE_UART_DATA is set, the data is sent back to sender. */ static void ble_nus_chars_received_uart_print(uint8_t * p_data, uint16_t data_len) { for (uint32_t i = 0; i < data_len; i++) { printf("%02x ",p_data[i]); } printf("\n"); }
step 10:在main函数中初时化及定时发送数据
static uint32_t tick; static uint8_t sendBuf[4]; static uint16_t len = 4; /**@brief Application main function. */ int main(void) {
// Initialize. uart_init(); log_init(); timers_init(); power_management_init(); ble_stack_init(); db_discovery_init(); scan_init(); gap_params_init(); gatt_init(); conn_params_init(); nus_c_init(); services_init(); advertising_init(); // Start execution. printf("\r\nUART started.\r\n"); scan_start(); advertising_start(); application_timers_start(); // Enter main loop. for (;;) { if(tickFlag) { tickFlag = 0; if(m_center_handle != BLE_CONN_HANDLE_INVALID) { tick++; sendBuf[0] = (tick>>24) & 0xff; sendBuf[1] = (tick>>16) & 0xff; sendBuf[2] = (tick>>8) & 0xff; sendBuf[3] = tick & 0xff; ble_nus_c_string_send(&m_ble_nus_c,sendBuf,len); } } else { idle_state_handle(); } } }
step 11:RAM地址设置
Demo下载地址:https://download.csdn.net/download/mygod2008ok/11162759