那么现在回到程序上去吧,这个比较适合已经看过一些蓝牙SDK代码。
1,首先协议栈是如何运作的?
协议栈是基于100%的事件驱动,也就是说协议栈向app发送任何数据都是基于事件的。
当设备收到数据,协议栈得到数据处理后,然后将数据打包成一个结构体,并附上事件id,比如BLE_GAP_EVT_CONNECTED,BLE_GATT_EVT_WRITE来分别告诉上层app这个事件结构体代表的事件。
比如BLE_GAP_EVT_CONNECTED代表链接事件,那么这个事件结构体中包含的数据就是连接参数等数据。而BLE_GATT_EVT_WRITE代表写事件,那么结构体中数据就是对端设备写给板子的数据。
根据上图可以明显看出ble_evt_dispatch()函数就是事件派发函数,举个例子:
static void ble_evt_dispatch(ble_evt_t *p_ble_evt)
{
ble_conn_params_on_evt(p_ble_evt);
ble_nus_ble_evt(&m_nus,p_ble_evt);
on_ble_evt(p_ble_evt);
}
连接参数管理处理函数ble_conn_params_on_evt(p_ble_evt);
UART服务时间处理函数ble_nus_ble_evt(&m_nus,p_ble_evt);
通用事件处理函数 on_ble_evt(p_ble_evt);
不同的事件在事件结构体ble_evt_t中通过id来区别。
然后创建一个服务应该添加到哪里?
在main()函数中有一个services_init();这个函数的内部就是添加服务,特征值等代码。
该函数内部其实就是注册了一个回调函数nus_data_handler(该函数会在手机发数据给板子时将数据从电脑串口打印出来)然后再执行真正的初始化函数ble_nus_init。该函数内部又会调用sd_ble_gatts_service_add这个协议栈的api接口来添加服务。后面也会调用 sd_ble_gatts_characteristic_add这个协议栈的api接口来添加特征值。如图所示:
最后手机发送的数据在哪里,如何发送数据给手机?
手机发送给设备的数据是在哪个函数里出来的? 没有函数,协议栈会抛上来一个事件结构体,收到的数据在结构体里。蓝牙数据接收在底层,接收完后会返回事件给上层的ble_evt_dispatch分发函数,他将事件分发给各个服务或者事件处理函数。服务或处理函数会捕获是否存在写事件case BLE_GATTS_EVT_WRITE:存在就做相应处理。BLE的发送数据给手机是有API接口的,即sd_ble_gatts_hvx(),可以通过参数来设置是以通知方式发送还是指示方式发送(通知不需要回复确认,指示需要)。但是手机发过来的数据没有接受函数,因为他是基于事件驱动的。