2.#defineBLE_UUID_NUS_TX_C_CHARACTERISTIC0x0003/**< 主机的TX特性对应于从机的RX特性*/
3.#defineBLE_UUID_NUS_RX_C_CHARACTERISTIC0x0002/**< 主机的RX特性. */
4.
5.#defineBLE_NUS_MAX_DATA_LEN (GATT_MTU_SIZE_DEFAULT - 3) /**< 最大20字节Maximum length of data (inbytes) thatcanbetransmittedbytheNordicUARTservicemoduletothepeer. */
6.
7.#defineBLE_NUS_MAX_RX_CHAR_LENBLE_NUS_MAX_DATA_LEN/**< 等价于接收长度Maximum length of theRXCharacteristic (in bytes). */
8.#defineBLE_NUS_MAX_TX_CHAR_LENBLE_NUS_MAX_DATA_LEN/**< Maximum length of theTXCharacteristic (inbytes). */
蓝牙ble是基于属性协议的
属性协议:
客户端通过它可以发现并获取属**器上的属性:
6种基本操作
1、请求:
客户端发给请求给服务器,需要服务器回复一个响应
2、响应:
3、命令:
客户端发给请求给服务器,不需要服务器回复一个响应
4、指示:
服务器发给指示给客户端,需要客户端发一个确认给服务器
5、确认:
6、通知:
客户端发给请求给服务器,不需要服务器回复一个响应
例子用到了请求,通知。
写入请求包含:
一个句柄和一个该属性的值,什么是句柄?
首先服务器运行属性数据库(跟数组差不多),里面包含了很多属性,每一个属性都有一个句柄(跟内存地址差不多,随机分配)。
charhr_as_string[LCD_LLEN;
1. //接收到了通知事件,直接打印下来
2. APPL_LOG("[APP]:
receive=%s.\r\n", p_nus_c_evt->params.tx.tx_value);
3. break;
4. }
5. default:
6. break;
7. }
8.}
ble_nus_c_init函数主要是添加了一个自定义的uuid基数,并把服务的16位uuid号的回调函数注册到了发现模块,当系统运行扫描后,当发现模块发现这个uuid后,会调用这个回调函数
1./*
2.* @briefs120串口初始化
3.*
4.*/
5.uint32_tble_nus_c_init(ble_nus_c_t * p_ble_nus_c, ble_nus_c_init_t * p_ble_nus_c_init){
6.
7. uint32_terr_code;
8. if ((p_ble_nus_c == NULL) || (p_ble_nus_c_init == NULL))
9. {
10. returnNRF_ERROR_NULL;
11. }
12. //增加一个自定义的蓝牙uuid基数,
13. ble_uuid128_tnus_base_uuid = {0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0,
14. 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E};
15.
16. mp_ble_nus_c = p_ble_nus_c;
17.
18. err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &mp_ble_nus_c->nus_uuid.type);
19. if (err_code !
= NRF_SUCCESS)
20. {
21. returnerr_code;
22. }
23. //设置服务的16位uuid,配合前面加的蓝牙uuid基数,组成一组完整128位的uuid号
24. mp_ble_nus_c->nus_uuid.uuid = BLE_UUID_NUS_SERVICE;
25.
26.
27. mp_ble_nus_c->evt_handler = p_ble_nus_c_init->evt_handler;
28. //设置服务连接句柄为:
无效
29. mp_ble_nus_c->conn_handle = BLE_CONN_HANDLE_INVALID;
30. //设置特性的句柄为无效
31. mp_ble_nus_c->nus_rx_handle = BLE_GATT_HANDLE_INVALID;
32. mp_ble_nus_c->nus_tx_handle = BLE_GATT_HANDLE_INVALID;
33. //设置接收的描述符句柄为:
无效
34. mp_ble_nus_c->nus_rx_cccd_handle = BLE_GATT_HANDLE_INVALID;
35. mp_ble_nus_c->nus_tx_cccd_handle = BLE_GATT_HANDLE_INVALID;
36. //注册服务的uuid,及其回调函数,
37. //当发现模块发送有该uuid,就会调用db_discover_evt_handler
38. returnble_db_discovery_register(&mp_ble_nus_c->nus_uuid,
39. db_discover_evt_handler);
40.}
1.//当这个服务的uuid号被发现,那么这个函数就被调用
2.staticvoiddb_discover_evt_handler(ble_db_discovery_evt_t * p_evt) {
3. //检查uuid号和类型是不是一致
4. if (p_evt->evt_type == BLE_DB_DISCOVERY_COMPLETE
5. &&
6. p_evt->params.discovered_db.srv_uuid.uuid == mp_ble_nus_c->nus_uuid.uuid
7. &&
8. p_evt->params.discovered_db.srv_uuid.type == mp_ble_nus_c->nus_uuid.type)
9. {
10. //获取属性句柄
11. LOG("[NUS_C]:
服务被发现,获得了连接句柄\r\n");
12. mp_ble_nus_c->conn_handle = p_evt->conn_handle;
13.
14. //FindtheCCCDHandle of theHeartRateMeasurementcharacteristic.
15. uint8_ti;
16.
17. for (i = 0; i < p_evt->params.discovered_db.char_count; i++)
18. {
19. //检查特性的uuid号是不是一致
20. if (p_evt->params.discovered_db.charateristics[i.characteristic.uuid.uuid
21. ==
22. BLE_UUID_NUS_RX_C_CHARACTERISTIC)
23. {
24.
25. //characteristic. StoreCCCDhandle and break.
26.
27. //rx的描述符句柄
28. mp_ble_nus_c->nus_rx_cccd_handle =
29. p_evt->params.discovered_db.charateristics[i.cccd_handle;
30. //rx的句柄
31. mp_ble_nus_c->nus_rx_handle =
32. p_evt->params.discovered_db.charateristics[i.characteristic.handle_value;
33. LOG("[NUS_C]:
RX特性被发现,nus_rx_cccd_handle=%d nus_rx_handle=%d\r\n",mp_ble_nus_c->nus_rx_cccd_handle,mp_ble_nus_c->nus_rx_handle);
34.
35. } else if (p_evt->params.discovered_db.charateristics[i.characteristic.uuid.uuid
36. ==
37. BLE_UUID_NUS_TX_C_CHARACTERISTIC)
38. {
39.
40. //FoundHeartRatecharacteristic. StoreCCCDhandle and break.
41. mp_ble_nus_c->nus_tx_cccd_handle =
42. p_evt->params.discovered_db.charateristics[i.cccd_handle;
43. mp_ble_nus_c->nus_tx_handle =
44. p_evt->params.discovered_db.charateristics[i.characteristic.handle_value;
45. LOG("[NUS_C]:
TX特性被发现,nus_tx_cccd_handle=%d nus_tx_handle=%d\r\n",mp_ble_nus_c->nus_tx_cccd_handle,mp_ble_nus_c->nus_tx_handle);
46. } else {
47. LOG("[NUS_C]:
有其他的特性\r\n");
48. }
49.
50.
51. }
52.
53. ble_nus_c_evt_tevt;
54.
55. evt.evt_type = BLE_NUS_C_EVT_DISCOVERY_COMPLETE;
56. //运行main文件注册的回调函数,nus_c_evt_handler
57. mp_ble_nus_c->evt_handler(mp_ble_nus_c, &evt);
58. }
59.}
上面就是初始化做的所有事,接下来分析事件,每发生一个事件都会调用其回调函数,
看一下蓝牙协议栈初始化,主要有ble_evt_dispatch,sys_evt_dispatch两个回调函数,主要讲解ble_evt_dispatch
1.staticvoidble_stack_init(void)
2.{
3. uint32_terr_code;
4.
5. //InitializetheSoftDevicehandlermodule.
6. SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
7.
8. //RegisterwiththeSoftDevicehandlermodule for BLEevents.
9. err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
10. APP_ERROR_CHECK(err_code);
11.
12. //RegisterwiththeSoftDevicehandlermodule for Systemevents.
13. err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
14. APP_ERROR_CHECK(err_code);
15.}
ble_evt_dispatch:
把事件分派给各个模块处理,自己主要需要编写的ble_nus_c_on_ble_evt,及on_ble_evt
1.staticvoidble_evt_dispatch(ble_evt_t*p_ble_evt)
2.{
3.
4. app_trace_log("evt_id=%x\r\n",p_ble_evt->header.evt_id);
5. dm_ble_evt_handler(p_ble_evt);//管理模块的处理
6. ble_db_discovery_on_ble_evt(&m_ble_db_discovery, p_ble_evt);//发现模块的处理
7. ble_nus_c_on_ble_evt(&m_ble_nus_c, p_ble_evt);//nus的处理
8. on_ble_evt(p_ble_evt);//main的处理:
广播包处理->进行连接
9.}
看一下main函数中的on_ble_evt,
1./**@briefFunctionforhandlingtheApplication'sBLEStackevents.这里主要处理的广播包
2.*
3.* @param[in p_ble_evtBluetoothstackevent.,
4.*/
5.staticvoidon_ble_evt(ble_evt_t * p_ble_evt)
6.{
7. uint32_terr_code;
8. ble_uuid_tpeer_uuid;
9. const ble_gap_evt_t * p_gap_evt = &p_ble_evt->evt.gap_evt;
10. app_trace_log("on_ble_evt\r\n");
11. switch (p_ble_evt->header.evt_id)
12. {
13. //发现了一个广播包
14. case BLE_GAP_EVT_ADV_REPORT:
15. {
16. data_tadv_data;
17. data_ttype_data;
18.
19. // Initializeadvertisementreport for parsing.
20. //首先是要从广播包解析出数据
21. adv_data.p_data = (uint8_t *)p_gap_evt->params.adv_report.data;
22. adv_data.data_len = p_gap_evt->params.adv_report.dlen;
23. //获得完整的128bit,uuid号
24. err_code = adv_report_parse(BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
25. &adv_data,
26. &type_data);
27.
28. // Verify if short or completenamematchestarget.
29. if (err_code == NRF_SUCCESS)
30. { //对uuid进行换算:
128bit换算成一个16bit及其类型,
31. err_code = sd_ble_uuid_decode(type_data.data_len,type_data.p_data,&peer_uuid);
32. if (err_code == NRF_SUCCESS) {
33. if ((peer_uuid.uuid == m_ble_nus_c.nus_uuid.uuid )&&peer_uuid.type ==m_ble_nus_c.nus_uuid.type ) {
34. //发现了从机的,停止广播并尝试连接
35. err_code = sd_ble_gap_scan_stop();
36. if (err_code !
= NRF_SUCCESS) {
37. APPL_LOG("[APPL]:
Scanstopfailed,reason%d\r\n", err_code);
38. }
39. nrf_gpio_pin_clear(SCAN_LED_PIN_NO);
40. err_code = sd_ble_gap_connect(&p_gap_evt->params.adv_report.\
41. peer_addr,
42. &m_scan_param,
43. &m_connection_param);
44.
45. if (err_code !
= NRF_SUCCESS)
46. {
47. APPL_LOG("[APPL]:
ConnectionRequestFailed,reason%d\r\n", err_code);
48. } else {
49. APPL_LOG("连接建立\r\n");
50. }
51. break;
52.
53. }else {
54. APPL_LOG("匹配出错\r\n");
55. }
56.
57. }
58. }
59. break;
60. }
61.以下省略,直接拷贝官方的处理方式
看一下nus模块的处理
1.voidble_nus_c_on_ble_evt(ble_nus_c_t*p_ble_nus_c,constble_evt_t*p_ble_evt){
2. ble_uuid_tserver_uuid;
3. uint