BLE-NRF51822教程6-创建一个自己的服务

该教程基于 sdk9.0
首先打开 sdk 下的工程模板 在以下路径中
XXXX \Keil_v5 \ARM \Pack \NordicSemiconductor \nRF_Examples \9.0.0 \ble_peri pheral \ble_app_template \pca10028 \s110 \arm5
打开工程后,可以发现该模板的框架和 一般工程例子基本是一样的。区别 就是有一些函数内部并未实现,比如 services_init() 。
Main 函数的整体初始化流程都是通用。
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();
    }
}
这一讲我们来在该模板上创建个使用最少资源的 服务。
我们只是创建一个 服务 这个服务具有可写和通知的特性。从而实现手机发数 这个服务具有可写和通知的特性。从而实现手机发数 据给设备,然后对数做 加 1操作 后再返回给手机。


所以我们没有使用 定时器, 按键定时器, 按键led ,以及绑定功能我们也不做链接参数的 ,以及绑定功能我们也不做链接参数的 ,以及绑定功能我们也不做链接参数的 ,以及绑定功能我们也不做链接参数的 更新操作 所以上面的 main 函数我们精简成如下:
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();
    }
}

这个时候编译工程下载到板子后是可以搜索设备的。
只是连接后并没有服务,下面我们来创建一个服务。 要实现的 就是上面services_init() 函数。
首先我们需要定义一个自己的服务结构体来记录这相关些信息。
直接在 main.c 文件的上面 定义如下结构体。
typedef struct BlkMyServiceTag{
    uint16_t conn_handle; // 连接后用 来记录下句柄,供续使连接后用
    uint16_t service_handle; // 保存服务的句柄
    ble_gatts_char_handles_t handle; //保存特性句柄
}BlkMyService;

然后定义一个全局变量
BlkMyService my_service; // 这个全局变量保存了我们的服务相关信息

然后实现 service_init() 函数。
这里不使用模板工程中 建议的初始化方法,为简单起见我 们就直接在该函数里面调用服务添加和特征值。

为方便也是直接就在 main.c 文件中实现如下函数
void services_init(void){
    ble_uuid_t service_uuid;
    service_uuid.type = BLE_UUID_TYPE_BLE;
    service_uuid.uuid = MY_UUID;

    // 添加服务
    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 = & ccc d_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);
}

到这里服务以及其中的特征值都已经创建好了。编译工程下载后,手机连接设备可以看到服务列表中 已经有了我们添加的服务 uuid 为 0x1234 ,点击服务也可以看到 其中的特征值 uuid 为 0x5678

服务 创建完后就是与手机 创建完后就是与手机 创建完后就是与手机 创建完后就是与手机 通信了。我们要实现的是手机发送一个 数据
设备收到后对数据做 加 1 操作后再发回给手机。

手机发给设备的数据最 终会被打包成一个 写事件结构 然后交给 app 。
先实现对写事件的处理。就是将数据 加一 然后在发送回给手机。
当然发送数据 给手机 之前,我们要知道 之前,我们要知道 conn_handle ,这在 手机连接的时候 app 会受到这个事件,记录下句 柄就可以了。
我们针对写事件实 我们实现如下的数 据操作和发送函( 为方便都是直接在 main.c 文 件中实现 )
void servic e_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);
}

然后实现的服务处理函数如下
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;
    }
}
最后我们将这个 服务事件处理函数 添加到事件派发函数中
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);
}
编译工程下载后 ,手机连接上进入服务的特征值勾选使能 notify 功能, 然后发送数据就可以看到 收加 1的数据了
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是使用Nordic nRF5 SDK创建新的BLE服务的详细示例: 1. 首先,在nRF5 SDK中打开“examples\ble_peripheral\ble_app_template”示例。 2. 在“ble_app”文件夹中,打开“ble_srv_common.h”文件。此文件包含了一些常用的BLE服务定义,你可以通过阅读该文件来了解BLE服务的实现方式。 3. 在“ble_app”文件夹中,打开“ble_srv_common.c”文件。此文件包含了一些常用的BLE服务实现代码,你可以通过阅读该文件来了解BLE服务的实现方式。 4. 在“ble_app”文件夹中,创建一个新的文件夹,命名为“my_service”。 5. 在“my_service”文件夹中,创建一个新的文件,命名为“my_service.h”。在该文件中,你需要定义你的自定义BLE服务的UUID,以及相关的特性和属性等信息。例如: ``` #ifndef MY_SERVICE_H #define MY_SERVICE_H #include "ble.h" #include "ble_srv_common.h" #define BLE_UUID_MY_SERVICE 0x1234 // 自定义服务的UUID // 自定义服务的特性UUID #define BLE_UUID_MY_SERVICE_CHARACTERISTIC 0x5678 // 自定义服务的特性值结构体 typedef struct { uint8_t value; } ble_my_service_characteristic_t; // 自定义服务的事件结构体 typedef struct { ble_my_service_characteristic_t char_value; } ble_my_service_evt_t; // 自定义服务的事件句柄类型 typedef void (*ble_my_service_evt_handler_t) (ble_my_service_evt_t * p_evt); // 自定义服务的初始化函数 uint32_t ble_my_service_init(void); // 自定义服务的事件注册函数 void ble_my_service_evt_handler_register(ble_my_service_evt_handler_t evt_handler); #endif // MY_SERVICE_H ``` 6. 在“my_service”文件夹中,创建一个新的文件,命名为“my_service.c”。在该文件中,你需要实现你的自定义BLE服务的初始化、事件处理等功能。例如: ``` #include "my_service.h" static uint16_t m_service_handle; // 自定义服务的句柄 static ble_gatts_char_handles_t m_char_handles; // 自定义服务的特性句柄 static ble_my_service_evt_handler_t m_evt_handler; // 自定义服务的事件处理函数 // 自定义服务的事件回调函数 static void my_service_evt_handler(ble_evt_t const * p_ble_evt) { switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: break; case BLE_GAP_EVT_DISCONNECTED: break; case BLE_GATTS_EVT_WRITE: if (p_ble_evt->evt.gatts_evt.params.write.handle == m_char_handles.value_handle) { ble_my_service_evt_t evt; evt.char_value.value = p_ble_evt->evt.gatts_evt.params.write.data[0]; m_evt_handler(&evt); } break; default: break; } } // 自定义服务的事件注册函数 void ble_my_service_evt_handler_register(ble_my_service_evt_handler_t evt_handler) { m_evt_handler = evt_handler; } // 自定义服务的初始化函数 uint32_t ble_my_service_init(void) { uint32_t err_code; ble_uuid_t ble_uuid; ble_uuid128_t base_uuid = {BLE_UUID_MY_SERVICE_BASE}; // 生成自定义服务的UUID err_code = sd_ble_uuid_vs_add(&base_uuid, &ble_uuid.type); VERIFY_SUCCESS(err_code); ble_uuid.uuid = BLE_UUID_MY_SERVICE; // 添加自定义服务 err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &m_service_handle); VERIFY_SUCCESS(err_code); // 添加自定义服务的特性 ble_gatts_char_md_t char_md; memset(&char_md, 0, sizeof(char_md)); char_md.char_props.read = 1; char_md.char_props.write = 1; ble_gatts_attr_md_t attr_md; memset(&attr_md, 0, sizeof(attr_md)); attr_md.read_perm = BLE_GAP_CONN_SEC_MODE_OPEN; attr_md.write_perm = BLE_GAP_CONN_SEC_MODE_OPEN; attr_md.vloc = BLE_GATTS_VLOC_STACK; ble_uuid_t char_uuid; char_uuid.uuid = BLE_UUID_MY_SERVICE_CHARACTERISTIC; char_uuid.type = ble_uuid.type; ble_gatts_attr_t attr; memset(&attr, 0, sizeof(attr)); attr.p_uuid = &char_uuid; attr.p_attr_md = &attr_md; attr.init_len = sizeof(ble_my_service_characteristic_t); attr.max_len = sizeof(ble_my_service_characteristic_t); attr.p_value = NULL; err_code = sd_ble_gatts_characteristic_add(m_service_handle, &char_md, &attr, &m_char_handles); VERIFY_SUCCESS(err_code); // 注册事件回调函数 err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_GENERIC_TAG); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) DEVICE_NAME, strlen(DEVICE_NAME)); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, TX_POWER); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_SCAN_INIT, 0, TX_POWER); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, 0, TX_POWER); VERIFY_SUCCESS(err_code); err_code = sd_ble_gap_ppcp_set(&ppcp); VERIFY_SUCCESS(err_code); return NRF_SUCCESS; } ``` 7. 在“main.c”文件中,包含“my_service.h”头文件,并在初始化函数中调用“ble_my_service_init()”函数来初始化你的自定义BLE服务。例如: ``` #include "my_service.h" int main(void) { uint32_t err_code; // 初始化BLE协议栈 ble_stack_init(); // 初始化GAP参数 gap_params_init(); // 初始化GATT参数 gatt_init(); // 初始化自定义服务 err_code = ble_my_service_init(); APP_ERROR_CHECK(err_code); // 启动广播 advertising_start(); // 进入主循环 for (;;) { idle_state_handle(); } } ``` 到此为止,我们已经完成了一个简单的自定义BLE服务的创建实例。你可以根据自己的需要修改“my_service.h”和“my_service.c”文件,来实现更加复杂的自定义BLE服务

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值