.目的
学习nrf51822主机和从机通信
2.分析
nrf51822---主从通信(1)和nrf51822---主从通信(2)都是在已知服务的基础上面来找的。但是在实际中并不知道对方的属性,可能只告诉你要连接蓝牙的名字。那怎么办呢???
3.平台:
协议栈版本:SDK10.0.0
编译软件:keil 5.12
硬件平台:nrf51822最小系统
例子:SDK 10.0.0\examples\ble_peripheral\ble_app_uart\pca10028\s110\arm4 从机例子
SDK10.0\examples\ble_central_and_peripheral\experimental\ble_app_hrs_rscs_relay\pca10028\s130\arm4 做主机
4步骤.
首先来大概分析下代码。
首先在主函数里.2个从机,控制服务初始化的过程,然后扫描开始,广播开始,即主从一体
int main(void)
{
ret_code_t err_code;
bool erase_bonds;
err_code = NRF_LOG_INIT();
APP_ERROR_CHECK(err_code);
NRF_LOG_PRINTF("Relay Example\r\n");
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, NULL);
buttons_leds_init(&erase_bonds);
if (erase_bonds == true)
{
NRF_LOG("Bonds erased!\r\n");
}
ble_stack_init();
peer_manager_init(erase_bonds);
db_discovery_init();
hrs_c_init(); //HES初始化
rscs_c_init(); //rscs初始化
gap_params_init();
conn_params_init();
services_init();
advertising_init();
/** 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.
LEDS_ON(CENTRAL_SCANNING_LED);
// Start advertising.
err_code = ble_advertising_start(BLE_ADV_MODE_FAST); //广播初始化
APP_ERROR_CHECK(err_code);
for (;;)
{
// Wait for BLE events.
power_manage();
}
}
接下来看扫描到了广播,产生BLE_GAP_EVT_ADV_REPORT事件代码:
case BLE_GAP_EVT_ADV_REPORT:
{
uint32_t err_code;
data_t adv_data;
data_t type_data;
// For readibility. 找到扫描的地址
const ble_gap_addr_t * const peer_addr = &p_gap_evt->params.adv_report.peer_addr;
// Initialize advertisement report for parsing.
adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data; //扫描广播的数据地址
adv_data.data_len = p_gap_evt->params.adv_report.dlen; //扫描广播的长度
//找标识符为BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE的数据地址和长度
err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
&adv_data,
&type_data);
if (err_code != NRF_SUCCESS)
{
// Look for the services in 'complete' if it was not found in 'more available'.
err_code = adv_report_parse(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
&adv_data,
&type_data);
if (err_code != NRF_SUCCESS)
{
// If we can't parse the data, then exit.
break;
}
}
// Verify if any UUID match the Heart rate or Running speed and cadence services.
for (uint32_t u_index = 0; u_index < (type_data.data_len / UUID16_SIZE); u_index++)
{
bool do_connect = false;
uint16_t extracted_uuid;
//复制出UUID到extracted
UUID16_EXTRACT(&extracted_uuid, &type_data.p_data[u_index * UUID16_SIZE]);
/** We do not want to connect to two peripherals offering the same service, so when
* a UUID is matched, we check that we are not already connected to a peer which
* offers the same service. We then save the peer address, so that upon connection
* we can tell which peer has connected and update its respective connection
* handle. */ //判断UUID是不是心率的UUID并且看是否已经连上了
if ((extracted_uuid == BLE_UUID_HEART_RATE_SERVICE) &&
(m_conn_handle_hrs_c == BLE_CONN_HANDLE_INVALID))
{ do_connect = true;
memcpy(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t)); //复制扫描的蓝牙地址到periph_addr_hrs
} //或者UUID是不是RSCS的UUID并且没有连上
else if ((extracted_uuid == BLE_UUID_RUNNING_SPEED_AND_CADENCE) &&
(m_conn_handle_rscs_c == BLE_CONN_HANDLE_INVALID))
{
do_connect = true;
memcpy(&periph_addr_rsc, peer_addr, sizeof(ble_gap_addr_t)); //复制蓝牙地址
}
if (do_connect)
{
// Initiate connection. //连接这地址的设备
err_code = sd_ble_gap_connect(peer_addr, &m_scan_param, &m_connection_param);
if (err_code != NRF_SUCCESS)
{
APPL_LOG("[APPL]: Connection Request Failed, reason %d\r\n", err_code);
}
}
}
} break; // BLE_GAP_ADV_REPORT
如果连上了设备则产生BLE_GAP_EVT_CONNECTED事件
case BLE_GAP_EVT_CONNECTED:
{
uint32_t err_code;
// For readability.
const ble_gap_addr_t * const peer_addr = &p_gap_evt->params.connected.peer_addr; //找到蓝牙的地址
/** Check which peer has connected, save the connection handle and initiate DB discovery.
* DB discovery will invoke a callback (hrs_c_evt_handler and rscs_c_evt_handler)
* upon completion, which is used to enable notifications from the peer. */ if(memcmp(&periph_addr_hrs, peer_addr, sizeof(ble_gap_addr_t)) == 0) //连接上的蓝牙地址和和被连接的蓝牙地址对比 一直则正确
{
NRF_LOG_PRINTF("HRS central connected\r\n");
// Reset the peer address we had saved.
memset(&periph_addr_hrs, 0, sizeof(ble_gap_addr_t));
m_conn_handle_hrs_c = p_gap_evt->conn_handle; //保存连接的handle 这个很总有可以用来区别哪个设备
NRF_LOG_PRINTF("Starting DB discovery for HRS\r\n");
err_code = ble_db_discovery_start(&m_ble_db_discovery_hrs, p_gap_evt->conn_handle); //开始发现服务
APP_ERROR_CHECK(err_code);
} else if(memcmp(&periph_addr_rsc, peer_addr, sizeof(ble_gap_addr_t)) == 0) //连接上的蓝牙地址和和被连接的蓝牙地址对比 一直则正确
{
NRF_LOG_PRINTF("RSC central connected\r\n");
// Reset the peer address we had saved.
memset(&periph_addr_rsc, 0, sizeof(ble_gap_addr_t));
m_conn_handle_rscs_c = p_gap_evt->conn_handle;//保存连接的handle
NRF_LOG_PRINTF("Starting DB discovery for RSCS\r\n");
err_code = ble_db_discovery_start(&m_ble_db_discovery_rsc, p_gap_evt->conn_handle); //开始扫描服务设备
APP_ERROR_CHECK(err_code);
}
/** Update LEDs status, and check if we should be looking for more
* peripherals to connect to. */
LEDS_ON(CENTRAL_CONNECTED_LED);
if (ble_conn_state_n_centrals() == MAX_CONNECTED_CENTRALS)//判断连接的设备是否为设定的设备值
{
LEDS_OFF(CENTRAL_SCANNING_LED);//
}
else {
// Resume scanning.
LEDS_ON(CENTRAL_SCANNING_LED);
scan_start(); //继续扫描
}
} break; // BLE_GAP_EVT_CONNECTED
断开某设备。会产生BLE_GAP_EVT_DISCONNECTED事件,
case BLE_GAP_EVT_DISCONNECTED:
{
uint8_t n_centrals;
if (p_gap_evt->conn_handle == m_conn_handle_hrs_c) //判断断开的设备是哪个设备,是否为HRS设备。找出对应的handle
{
NRF_LOG_PRINTF("HRS central disconnected (reason: %d)\r\n",
p_gap_evt->params.disconnected.reason);
m_conn_handle_hrs_c = BLE_CONN_HANDLE_INVALID; //handle初始化
}
else if(p_gap_evt->conn_handle == m_conn_handle_rscs_c) //判断断开的设备是不是RSCS设备
{
NRF_LOG_PRINTF("RSC central disconnected (reason: %d)\r\n",
p_gap_evt->params.disconnected.reason);
m_conn_handle_rscs_c = BLE_CONN_HANDLE_INVALID; //handle初始化
}
// Start scanning
scan_start(); //这里会不会冲突。
// Update LEDs status.
LEDS_ON(CENTRAL_SCANNING_LED);
n_centrals = ble_conn_state_n_centrals();
if (n_centrals == 0)
{
LEDS_OFF(CENTRAL_CONNECTED_LED);
}
} break; // BLE_GAP_EVT_DISCONNECTED