BLE-NRF51822教程6-创建一个自己的服务
生活随笔
收集整理的這篇文章主要介紹了
BLE-NRF51822教程6-创建一个自己的服务
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
首先打開 sdk 下的工程模板 在以下路徑中
XXXX\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_template\pca10028\s110\arm5打開工程后,可以發(fā)現(xiàn)該模板的框架和一般工程例子基本是一樣的。區(qū)別就是有一些函數(shù)內(nèi)部并未實(shí)現(xiàn),比如services_init() 。
Main 函數(shù)的整體初始化流程都是通用。
[cpp]?view plain?copy ? ? int?main(void)?? {?? ????uint32_t?err_code;?? ????bool?erase_bonds;?? ????//?Initialize.?? ????timers_init();?? ????buttons_leds_init(&erase_bonds);?? ????ble_stack_init();?? ????device_manager_init(erase_bonds);?? ????gap_params_init();?? ????advertising_init();?? ????services_i?nit();?? ????conn_params_init();?? ????//?Start?execution.?? ????application_timers_start();?? ????err_code?=?ble_advertising_start(BLE_ADV_MODE_FAST);?? ????APP_ERROR_CHECK(err_code);?? ????//?Enter?main?loop.?? ????for?(;;)?? ????{?? ????????power_manage();?? ????}?? }??
這一講我們來在該模板上創(chuàng)建個使用最少資源的服務(wù)。
我們只是創(chuàng)建一個服務(wù)這個服務(wù)具有可寫和通知的特性。從而實(shí)現(xiàn)手機(jī)發(fā)數(shù) 這個服務(wù)具有可寫和通知的特性。從而實(shí)現(xiàn)手機(jī)發(fā)數(shù) 據(jù)給設(shè)備,然后對數(shù)做 加 1操作 后再返回給手機(jī)。所以我們沒有使用:定時器、按鍵定時器、按鍵led、綁定功能、鏈接參數(shù)、更新操作、所以上面的main函數(shù)我們精簡成如下:
[cpp]?view plain?copy ? ? int?main(void)?? {?? ????uint32_t?err_code;?? ????bool?erase_bonds;?? ????ble_stack_init();?? ????gap_params_?init();?? ????advertising_init();?? ????services_init();?? ????err_code?=?ble_advertising_start(BLE_ADV_MODE_FAST);?? ????APP_ERROR_CHECK(err_code);?? ????//?Enter?main?loop.?? ????for?(;;)?? ????{?? ????????power_manage();?? ????}?? }??
這個時候編譯工程下載到板子后是可以搜索設(shè)備的。只是連接后并沒有服務(wù),下面我們來創(chuàng)建一個服務(wù)。 要實(shí)現(xiàn)的就是上面services_init() 函數(shù)。首先我們需要定義一個自己的服務(wù)結(jié)構(gòu)體來記錄這相關(guān)些信息。直接在 main.c 文件的上面定義如下結(jié)構(gòu)體。
[cpp]?view plain?copy ? ? typedef?struct?BlkMyServiceTag{?? ????uint16_t?conn_handle;??????????????//?連接后用?來記錄下句柄,供續(xù)使連接后用?? ????uint16_t?service_handle;???????????//?保存服務(wù)的句柄?? ????ble_gatts_char_handles_t?handle;???//?保存特性句柄?? }BlkMyService;??
然后定義一個全局變量
BlkMyService my_service; // 這個全局變量保存了我們的服務(wù)相關(guān)信息
然后實(shí)現(xiàn) service_init() 函數(shù)。
這里不使用模板工程中?建議的初始化方法,為簡單起見我 們就直接在該函數(shù)里面調(diào)用服務(wù)添加和特征值。
為方便也是直接就在 main.c 文件中實(shí)現(xiàn)如下函數(shù)
[cpp]?view plain?copy ? ? void?services_init(void){?? ????ble_uuid_t?service_uuid;?? ????service_uuid.type?=?BLE_UUID_TYPE_BLE;?? ????service_uuid.uuid?=?MY_UUID;?? ?? ????//?添加服務(wù)?? ????sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,&service_uuid,&my_service.service_handle);?? ?? ????ble_gatts_char_?md_t?char_md;?? ????ble_gatts_attr_t?attr_char_value;?? ????ble_gatts_attr_md_t?cccd_md;?? ????ble_gatts_attr_md_t?attr_md;?? ?? ????BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);?? ????BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);?? ?? ????cccd_md.vloc???????????=?BLE_GATTS_VLOC_?STACK;?? ????char_md.p_cccd_md??????=?&cccd_md;?? ????char_md.props.notify???=?1;?? ????char_md.props.write????=?1;?? ????char_md.p_pf???????????=?NULL;?? ????char_md.p_user_desc????=?NULL;?? ????char_md.p_sccd_md??????=?NULL;?? ????char_md.p_user_desc_md?=?NULL;?? ?? ????attr_md.rd_auth?=?0;?? ????attr_md.wr_auth?=?0;?? ????BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);?? ????BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);?? ????attr_md.vloc?=?BLE_GATTS_VLOC_STACK;?? ????attr_md.vlen?=?1;?? ?? ????ble_uuid_t?val_uuid;?? ????val_uuid.type???=?BLE_UUID_TYPE_BLE;?? ????val_uuid.uu?id??=?0x5678;?? ?? ????attr_char_value.p_uuid?????=?&val_uuid;?? ????attr_char_value.p_md???????=?&attr_md;?? ????attr_char_value.init_len???=?sizeof(uint8_t);?? ????attr_char_value.init_offs??=?0;?? ????attr_char_value.max_len????=?20;?? ?????//?添加特征值。?? ????sd_ble_gatts_characteristic_add(my_service.servi?ce_handle,?&char_md,?attr_value,&my_service.handle);?? }??
?到這里服務(wù)以及其中的特征值都已經(jīng)創(chuàng)建好了。編譯工程下載后,手機(jī)連接設(shè)備可以看到服務(wù)列表中已經(jīng)有了我們添加的服務(wù)uuid 為0x1234,點(diǎn)擊服務(wù)也可以看到其中的特征值 uuid 為0x5678;服務(wù)創(chuàng)建完后就是與手機(jī)通信了。我們要實(shí)現(xiàn)的是手機(jī)發(fā)送一個數(shù)據(jù),設(shè)備收到后對數(shù)據(jù)做加 1 操作后再發(fā)回給手機(jī)。
手機(jī)發(fā)給設(shè)備的數(shù)據(jù)最終會被打包成一個寫事件結(jié)構(gòu)然后交給 app 。
先實(shí)現(xiàn)對寫事件的處理。就是將數(shù)據(jù)加一然后在發(fā)送回給手機(jī)。
當(dāng)然發(fā)送數(shù)據(jù)給手機(jī)之前,我們要知道之前,我們要知道 conn_handle,這在手機(jī)連接的時候 app 會收到這個事件,記錄下句柄就可以了。
void?service_write_handle(ble_evt_t?*p_evt){?? ????uint16_t?data_len;?? ????uint8_t?data;?? ????data_len?=?sizeof(uint8_t);?? ????data?=?p_ble_evt?->evt.gatts_params.write.data[0];?? ????data++;?? ????ble_gatts_hvx_params_t?params;?? ????hvx_params.handle???=?my_service.char_handle.val?ue_handle;?? ????hvx_params.offset???=?0;?? ????hvx_params.p_data???=?&data;?? ????hvx_params.p_len????=?&data_len;?? ????hvx_params.type?????=?BLE_GATT_HVX_NOTIFICATION;?? ????sd_ble_gatts_hvx(my_service.conn_handle,&hvx_params);?? }??
[cpp]?view plain?copy ? ? void?my_server_handler(ble_evt_t?*p_evt){?? ????switch?(p_ble_evt?->header.evt_id)?? ????{?? ????????case?BLE_GAP_EVT_CONNECTED:?? ????????????my_service.conn_handl?=p_ble_evt?->evt.gap_conn_handle;?? ????????????break;?? ????????case?BLE_GATTS_EVT_WRITE:?? ????????????service_write_handle(p_ble_evt);?? ????????????break?;?? ????????default:?? ????????????//?No?implementation?needed.?? ????????????break;?? ????}?? }??
最后我們將這個 服務(wù)事件處理函數(shù) 添加到事件派發(fā)函數(shù)中
[cpp]?view plain?copy ? ? static?void?ble_evt_dispatch(t?*?p_evt)?? {?? ????dm_ble_evt_handler(p_evt);?? ????ble_conn_params_on_evt(p_evt);?? ????bsp_btn_ble_on_b?le_evt(p_ble_evt);?? ????on_ble_evt(p_evt);?? ????ble_advertising_on_evt(p_evt);?? ????//?添加到這里?? ????my_server_handler(p_ble_evt);?? }??
編譯工程下載后 ,手機(jī)連接上進(jìn)入服務(wù)的特征值勾選使能 notify 功能, 然后發(fā)送數(shù)據(jù)就可以看到收加 1 的數(shù)據(jù)了
XXXX\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_template\pca10028\s110\arm5打開工程后,可以發(fā)現(xiàn)該模板的框架和一般工程例子基本是一樣的。區(qū)別就是有一些函數(shù)內(nèi)部并未實(shí)現(xiàn),比如services_init() 。
Main 函數(shù)的整體初始化流程都是通用。
[cpp]?view plain?copy ? ?
這一講我們來在該模板上創(chuàng)建個使用最少資源的服務(wù)。
我們只是創(chuàng)建一個服務(wù)這個服務(wù)具有可寫和通知的特性。從而實(shí)現(xiàn)手機(jī)發(fā)數(shù) 這個服務(wù)具有可寫和通知的特性。從而實(shí)現(xiàn)手機(jī)發(fā)數(shù) 據(jù)給設(shè)備,然后對數(shù)做 加 1操作 后再返回給手機(jī)。所以我們沒有使用:定時器、按鍵定時器、按鍵led、綁定功能、鏈接參數(shù)、更新操作、所以上面的main函數(shù)我們精簡成如下:
[cpp]?view plain?copy ? ?
這個時候編譯工程下載到板子后是可以搜索設(shè)備的。只是連接后并沒有服務(wù),下面我們來創(chuàng)建一個服務(wù)。 要實(shí)現(xiàn)的就是上面services_init() 函數(shù)。首先我們需要定義一個自己的服務(wù)結(jié)構(gòu)體來記錄這相關(guān)些信息。直接在 main.c 文件的上面定義如下結(jié)構(gòu)體。
[cpp]?view plain?copy ? ?
然后定義一個全局變量
BlkMyService my_service; // 這個全局變量保存了我們的服務(wù)相關(guān)信息
然后實(shí)現(xiàn) service_init() 函數(shù)。
這里不使用模板工程中?建議的初始化方法,為簡單起見我 們就直接在該函數(shù)里面調(diào)用服務(wù)添加和特征值。
為方便也是直接就在 main.c 文件中實(shí)現(xiàn)如下函數(shù)
[cpp]?view plain?copy ? ?
手機(jī)發(fā)給設(shè)備的數(shù)據(jù)最終會被打包成一個寫事件結(jié)構(gòu)然后交給 app 。
先實(shí)現(xiàn)對寫事件的處理。就是將數(shù)據(jù)加一然后在發(fā)送回給手機(jī)。
當(dāng)然發(fā)送數(shù)據(jù)給手機(jī)之前,我們要知道之前,我們要知道 conn_handle,這在手機(jī)連接的時候 app 會收到這個事件,記錄下句柄就可以了。
我們針對寫事件實(shí) 我們實(shí)現(xiàn)如下的數(shù)據(jù)操作和發(fā)送函(為方便都是直接在 main.c 文件中實(shí)現(xiàn) )
[cpp]?view plain?copy ? ?
[cpp]?view plain?copy ? ?
[cpp]?view plain?copy ? ?
總結(jié)
以上是生活随笔為你收集整理的BLE-NRF51822教程6-创建一个自己的服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BLE-NRF51822教程5-静态密码
- 下一篇: nrf51822-添加DFU服务