当前页面为 开发中 版本,查看特定版本的文档,请在页面左下角的下拉菜单中进行选择。

NDK 蓝牙开发指南

本文主要通过一些示例,介绍蓝牙应用开发过程中常用的方法以及可能遇到的问题。

1 基础指标

1.1 功耗

蓝牙在不同的工作模式下功耗如下表所示:

测试条件:

  • 基于例程 nimble\samples\ble_periph_hr

  • 发射功率:0 dBm,广播数据:11 Bytes,PAN1070和PAN1010发射功率和广播数据一致;

测试配置:CONFIG_SOC_DCDC_PAN1070,CONFIG_PM_ENABLE,CONFIG_LOW_SPEED_CLOCK_SRC 测试选项:LOW_POWER_TESET_CI_100MSLOW_POWER_TESET_CI_1000MS

img

PAN1070UA1A EVB 核心板功耗测试数据

img

PAN1070UA1A EVB 核心板配置latency功耗测试数据

img

PAN1010S9FA EVB 核心板功耗测试数据

2 开发流程

2.1 确认开发环境

参考 NDK 快速入门指南,确认软硬件开发环境,可以正常的编译、下载和调试SDK提供的基础例程。

建议连接板载的 micro USB,通过串口工具监测 Log。

2.2 参考相关例程

蓝牙开发需要了解一些蓝牙协议相关的知识,可以参考蓝牙协议规范,网上也有很多协议的介绍,此处不作赘述。

当前SDK中提供了一些蓝牙相关的例程,涵盖了central、peripheral等。

在进行蓝牙开发之前,建议先看一下相关的文档,磨刀不误砍柴工,相信这些例程会对你的开发有所帮助。

2.3 了解蓝牙app代码的基本框架

2.3.1 蓝牙初始化

我们以ble_periph_hr为例。芯片上电启动以后,进入main() 函数, 然后执行用户初始化函数setup(), 在setup() 函数中调用 app_ble_init() 函数初始化和启动蓝牙

int main(void)
{
    /* user initialization entry. */
    setup();

    /**
     *  "main()" is a thread if CONFIG_OS_EN=1
     *  "main()" is a main entry if CONFIG_OS_EN=0
     *  
     *  If the user is using the main thread, you need t·····o enable the following code 
     *  and add the user's processing logic to the "loop()" function.
     */
#if 0
    while(1)
    {
        loop();
    }
#endif
}

/**
 *******************************************************************************
 * @brief user initialization entry
 *******************************************************************************
 */
void setup(void)
{
    /* ble stack initialization. */
    app_ble_init();

    /**
     * TODO: user add application initialization code in here.
     */
}

void app_ble_init(void)
{
    /* BLE Stack Initialization. */
    pan_ble_stack_init(app_ble_pre_init_cb, app_ble_enabled_cb);
}

pan_ble_stack_init() 函数是ble stack初始化和启动函数,该函数将自动创建ble thread以处理蓝牙相关的数据和事件。 这个函数提供了两个回调函数,如下:

  • ble_stack_pre_init_cb

    ble stack 预初始化回调, 这个回调用于在ble stack启动之前初始化一些与ble stack相关的参数,例如设置mac address/ 注册 GATT services / 初始化SDP等 。

    注意:mac address设置 /  GATT services 注册/ SDP初始化 必须在这个回调中完成。

  • ble_stack_enabled_cb

    该回调指示ble stack已经启动完成,用户可以在这个回调中启动adv或者scan或者干一些其他的事。

2.3.2 蓝牙广播或者扫描

广播函数:

app_ble_gap_event 是 ble event处理回调。

void app_ble_advertise_start(void)
{		
    struct ble_gap_adv_params adv_params;
    struct ble_hs_adv_fields fields;
    int rc;
    (void)rc; //remove compiler warning 

	/* set advertising data. */
    memset(&fields, 0, sizeof(fields));

    fields.flags = BLE_HS_ADV_F_DISC_GEN |
                   BLE_HS_ADV_F_BREDR_UNSUP;
	
    fields.name = (uint8_t *)device_name;
    fields.name_len = strlen(device_name);
    fields.name_is_complete = 1;

    fields.uuids16 = (ble_uuid16_t[]) {
        BLE_UUID16_INIT(BLE_SVC_HRS_UUID16),
    };
    fields.num_uuids16 = 1;
    fields.uuids16_is_complete = 1;

    rc = ble_gap_adv_set_fields(&fields);
    if (rc != 0) {
        APP_LOG_ERR("setting advertisement data failed; rc=%d\n", rc);
        app_assert(rc == 0);
    }

    /* set advertising parameter. */
    memset(&adv_params, 0, sizeof(adv_params));
	
    adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
    adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
    adv_params.itvl_min = BLE_GAP_ADV_ITVL_MS(CONFIG_ADV_INTRVL_MS);
    adv_params.itvl_max = BLE_GAP_ADV_ITVL_MS(CONFIG_ADV_INTRVL_MS + 10);
    
    /* start adv with "adv_params" */
    rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER, &adv_params, 
	                       app_ble_gap_event, NULL);
    if (rc != 0) {
        APP_LOG_ERR("enabling advertisement failed; rc=%d\n", rc);
        return;
    }
    APP_LOG_INFO("BLE adv start...\n");
}

扫描函数:

app_ble_gap_event 是 ble event处理回调。

void app_ble_scan_start(void)
{
    struct ble_gap_disc_params disc_params;
    int rc;
    (void)rc; //remove compiler warning 

    /* set scan parameter. */
    disc_params.passive       = 1;
    disc_params.itvl          = BLE_GAP_SCAN_ITVL_MS(60);
    disc_params.window        = BLE_GAP_SCAN_WIN_MS(50);
    disc_params.filter_policy = 0;
    disc_params.limited       = 0;
    disc_params.filter_duplicates = 0;

    /* start scan with "disc_params" */
    rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params, app_ble_gap_event, NULL);
    if (rc != 0) {
        APP_LOG_ERR("Error initiating GAP discovery procedure; rc=%d\r\n", rc);
    }
    APP_LOG_INFO("scan starting\r\n");
}

2.3.3 GATT服务注册

GATT服务注册如下:

void app_ble_svc_init(void)
{
    /* Register DIS service */
    ble_svc_dis_init();

    /* Register HRS service */
    ble_svc_hrs_init();
	
    /* register call-back(options) */
    ble_hs_cfg.gatts_register_cb  = app_ble_svr_register_cb;
    ble_hs_cfg.gatts_register_arg = NULL;
}

NDK 提供了一系列的配置文件供用户使用:

  • 如果用户要使用的service在profiles中有实现,可以直接添加相关的实现文件,然后调用初始化函数即可注册;

  • 如果用户使用的service在profiles中没有实现,用户需要自己添加service的实现,可以参考profiles文件中的任意一个service的实现。

2.3.4 GAP事件处理

Nimble提供了一系列的事件供用户使用。用户需要注册ble event处理回调(ble event处理回调在start adv或者start scan时注册,参看”2.3.2 蓝牙广播或者扫描”的相关内容)。需要注意的是:在adv和scan启动时注册的GAP event回调可以是同一个函数,也可以是不同的函数,具体使用哪一个由用户根据自己的习惯来。

Nimble GAP事件如下:

#define BLE_GAP_EVENT_CONNECT               0  /*!< connection complete event. */
#define BLE_GAP_EVENT_DISCONNECT            1  /*!< disconnection complete event */
/* Reserved                                 2 */
#define BLE_GAP_EVENT_CONN_UPDATE           3  /*!< connection parameter update complete event. */
#define BLE_GAP_EVENT_CONN_UPDATE_REQ       4  /*!< RX LL connection param req */
#define BLE_GAP_EVENT_L2CAP_UPDATE_REQ      5  /*!< RX slave L2cap connection update req. */
#define BLE_GAP_EVENT_TERM_FAILURE          6  /*!< */
#define BLE_GAP_EVENT_DISC                  7  /*!< adv report event */
#define BLE_GAP_EVENT_DISC_COMPLETE         8  /*!< scan duration expired event */
#define BLE_GAP_EVENT_ADV_COMPLETE          9  /*!< adv duration expired event */
#define BLE_GAP_EVENT_ENC_CHANGE            10 /*!< Encrypt Changed event */
#define BLE_GAP_EVENT_PASSKEY_ACTION        11 /*!< PinCode display/request event */
#define BLE_GAP_EVENT_NOTIFY_RX             12 /*!< Central Rx notify event. */
#define BLE_GAP_EVENT_NOTIFY_TX             13 /*!< Peripheral Tx notify cmpl event. */
#define BLE_GAP_EVENT_SUBSCRIBE             14 /*!< Enable/Disable Peripheral Notify & Indicate status event. */
#define BLE_GAP_EVENT_MTU                   15 /*!< MTU update complete event. */
#define BLE_GAP_EVENT_IDENTITY_RESOLVED     16 /*!< indicate peer address is RPA event. */
#define BLE_GAP_EVENT_REPEAT_PAIRING        17 /*!< The user is asked whether to delete the existing pair info to create a new pair. */
#define BLE_GAP_EVENT_PHY_UPDATE_COMPLETE   18 /*!< PHY update complete event. */
#define BLE_GAP_EVENT_EXT_DISC              19 /*!< extended adv report event. */
#define BLE_GAP_EVENT_PERIODIC_SYNC         20 /*!< period adv sync event. */
#define BLE_GAP_EVENT_PERIODIC_REPORT       21 /*!< period adv report event. */
#define BLE_GAP_EVENT_PERIODIC_SYNC_LOST    22 /*!< period adv sync loss event. */
#define BLE_GAP_EVENT_SCAN_REQ_RCVD         23 /*!< rx scan req event. */
#define BLE_GAP_EVENT_PERIODIC_TRANSFER     24 /*!< */
#define BLE_GAP_EVENT_PATHLOSS_THRESHOLD    25 /*!< */
#define BLE_GAP_EVENT_TRANSMIT_POWER        26 /*!< */

GAP event 回调如下:

int app_ble_gap_event(struct ble_gap_event *event, void *arg)
{
    struct ble_gap_conn_desc out_desc;
	
    switch (event->type) 
	{
    case BLE_GAP_EVENT_CONNECT:
         APP_LOG_INFO("connection %s; status=%d\n", event->connect.status == 0 ? "established" : "failed",
					event->connect.status);

        if (event->connect.status != 0) {
            app_ble_advertise_start();
            conn_handle = 0xFFFF;
            break;
        }
		
        ble_gap_conn_find(event->conn_update.conn_handle, &out_desc);
        APP_LOG("\t-peer_ota_addr:%s(at:%d)\r\n"
                "\t-peer_id_addr:%s(at:%d)\r\n"
                "\t-conn_intvl:%d us\r\n"
                "\t-latency:%d\r\n"
                "\t-to:%d ms\r\n",
                addr_to_str(out_desc.peer_ota_addr.val), 
                out_desc.peer_ota_addr.type,
                addr_to_str(out_desc.peer_id_addr.val),
                out_desc.peer_id_addr.type,
                out_desc.conn_itvl*1250, 
                out_desc.conn_latency, 
                out_desc.supervision_timeout*10);
  
        conn_handle = event->connect.conn_handle;
        break;

    case BLE_GAP_EVENT_DISCONNECT:
        APP_LOG_INFO("disconnect; reason=0x%02x\n", (uint8_t)event->disconnect.reason & 0xff);
        conn_handle = 0xFFFF;

        app_ble_advertise_start();
        break;

    case BLE_GAP_EVENT_ADV_COMPLETE:
        APP_LOG_INFO("adv duration expired - restart adv\n");
        app_ble_advertise_start();
        break;

    case BLE_GAP_EVENT_SUBSCRIBE:
        APP_LOG_INFO("subscribe event; cur_notify=%d, val_handle=%d\n",
                   event->subscribe.cur_notify, hrs_hrm_handle);
	
        if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_WRITE)
        {
            if (event->subscribe.attr_handle == hrs_hrm_handle) {
                notify_state = event->subscribe.cur_notify;
                app_ble_hr_tx_timer_start();
            } 
            else if (event->subscribe.attr_handle != hrs_hrm_handle) {
                notify_state = event->subscribe.cur_notify;
                app_ble_hr_tx_timer_stop();
            }
        }
       // indicate user that connection terminate.
       else if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM){
            notify_state = false;
            app_ble_hr_tx_timer_stop();
        }
        break;
		
    case BLE_GAP_EVENT_NOTIFY_TX:
        APP_LOG_INFO("notify ok\n");
        break;

    case BLE_GAP_EVENT_MTU:
        APP_LOG_INFO("mtu update event; conn_handle=%d mtu=%d\n",
                     event->mtu.conn_handle,
                     event->mtu.value);
        break;
	
    case BLE_GAP_EVENT_CONN_UPDATE:
    {	
        ble_gap_conn_find(event->conn_update.conn_handle, &out_desc);
        APP_LOG_INFO("conn upd cmpl: conn_handle:%d, itvl:%d us, latency:%d, to:%d ms\n",
                    out_desc.conn_handle, 
                    out_desc.conn_itvl * 1250,
                    out_desc.conn_latency,
                    out_desc.supervision_timeout*10);
        break;
    }
    default:
        break;
    }
    return 0;
}

3 使能PA功能

有些用户希望在RF 天线端外挂PA以增强 RF 距离,这里详细描述在 ble 应用中如何添加PA支持。

3.1 软件接口

为了使用PA功能,用户需要在启动蓝牙功能之前使能PA,使能PA需要调用如下API:

void pan_misc_set_pa_enable(uint8_t en);

具体用法如下:

void app_ble_pre_init_cb(void)
{
 	....   
    // Enable PA 
    pan_misc_set_pa_enable(1);
}

注:

  1. P03 控制 PA 的 TX

  2. P04 控制 PA 的 RX

3.2 硬件接口

image

PA 硬件接线图

4 BLE 常用API简介

4.1 GAP API

以下接口均可在 SDK ble_gap.h中找到,本节主要对一些常用接口 做了简要说明,具体细节用户可以到ble_gap.h中参看函数声明信息,了解函数的具体用法。

4.1.1 ble_gap_adv_start

函数原型:

int ble_gap_adv_start(uint8_t own_addr_type, const ble_addr_t *direct_addr,
                      int32_t duration_ms,
                      const struct ble_gap_adv_params *adv_params,
                      ble_gap_event_fn *cb, void *cb_arg);

功能说明:

该函数用于启动 ble adv, 函数参数的具体用法请参看 SDK ble_gap.h

4.1.2 ble_gap_adv_stop

函数原型:

int ble_gap_adv_stop(void);

功能说明:

该函数用于停止 ble adv。

4.1.3 ble_gap_adv_active

函数原型:

int ble_gap_adv_active(void);

功能说明:

该函数用于判断 ble adv 是否被使能。

4.1.4 ble_gap_adv_set_data

函数原型:

int ble_gap_adv_set_data(const uint8_t *data, int data_len);

功能说明:

该函数用于设置 adv 数据,adv数据格式应该按照蓝牙spec的要求的 LTV 格式和数据类型来。

4.1.5 ble_gap_adv_set_fields

函数原型:

int ble_gap_adv_set_fields(const struct ble_hs_adv_fields *rsp_fields);

功能说明:

该函数用于设置 adv 数据, 它是对ble_gap_adv_set_data() 接口的包装,使用更加方便,函数形参 rsp_fields 是按照蓝牙spec要求列出了大部分支持的数据类型,用户在不需要参看蓝牙spec的情况下也能简单的设置 adv 数据。

4.1.6 ble_gap_adv_rsp_set_data

函数原型:

int ble_gap_adv_rsp_set_data(const uint8_t *data, int data_len);

功能说明:

该函数用于设置scan rsp 数据,数据格式应该按照蓝牙spec的要求的 LTV 格式和数据类型来。

4.1.7 ble_gap_adv_rsp_set_fields

函数原型:

int ble_gap_adv_rsp_set_fields(const struct ble_hs_adv_fields *rsp_fields);

功能说明:

该函数用设置scan rsp 数据,它是对 ble_gap_adv_rsp_set_data() 接口的包装,使用更加方便,函数形参 rsp_fields 是按照蓝牙spec要求列出了大部分支持的数据类型,用户在不需要参看蓝牙spec的情况下也能简单的设置 adv 数据。

4.1.8 ble_gap_disc

函数原型:

int ble_gap_disc(uint8_t own_addr_type, int32_t duration_ms,
                 const struct ble_gap_disc_params *disc_params,
                 ble_gap_event_fn *cb, void *cb_arg);

功能说明:

该函数用于启动 scan 。

4.1.9 ble_gap_disc_cancel

函数原型:

int ble_gap_disc_cancel(void);

功能说明:

该函数用于停止 scan。

4.1.10 ble_gap_disc_active

函数原型:

int ble_gap_disc_active(void);

功能说明:

该函数用于判断scan是否被使能。

4.1.11 ble_gap_connect

函数原型:

int ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
                    int32_t duration_ms,
                    const struct ble_gap_conn_params *params,
                    ble_gap_event_fn *cb, void *cb_arg);

功能说明:

该函数用于 master 设备启动 连接 过程。

4.1.12 ble_gap_conn_cancel

函数原型:

int ble_gap_conn_cancel(void);

功能说明:

该函数用于取消一个正在进行的 连接 过程。

4.1.13 ble_gap_conn_active

函数原型:

int ble_gap_conn_active(void);

功能说明:

该函数用于判断 连接建立过程是否正在进行。

4.1.14 ble_gap_terminate

函数原型:

int ble_gap_terminate(uint16_t conn_handle, uint8_t hci_reason);

功能说明:

该函数用于主动断开一个 BLE 连接。

4.1.15 ble_gap_conn_find

函数原型:

int ble_gap_conn_find(uint16_t handle, struct ble_gap_conn_desc *out_desc);

功能说明:

该函数用于通过 handle 获取某个连接的信息,例如地址,连接参数等。

4.1.16 ble_gap_conn_find_by_addr

函数原型:

int ble_gap_conn_find_by_addr(const ble_addr_t *addr,
                              struct ble_gap_conn_desc *out_desc);

功能说明:

该函数用于通过 addr 获取某个连接的信息,例如地址,连接参数等。

4.1.17 ble_gap_wl_set

函数原型:

int ble_gap_wl_set(const ble_addr_t *addrs, uint8_t white_list_count);

功能说明:

该函数用于设置白名单。

4.1.18 ble_gap_update_params

函数原型:

int ble_gap_update_params(uint16_t conn_handle,
                          const struct ble_gap_upd_params *params);

功能说明:

该函数用于更新某个连接的连接参数。

4.1.19 ble_gap_set_data_len

函数原型:

int ble_gap_set_data_len(uint16_t conn_handle, uint16_t tx_octets, uint16_t tx_time);

功能说明:

该函数用于更新controller data length.

4.1.20 ble_gap_security_initiate

函数原型:

int ble_gap_security_initiate(uint16_t conn_handle);

功能说明:

对于master,该函数用于启动pair过程;对于slave,该函数用于启动安全请求。

4.1.21 ble_gap_conn_rssi

函数原型:

int ble_gap_conn_rssi(uint16_t conn_handle, int8_t *out_rssi);

功能说明:

该函数用于获取连接过程中RF RX型号强度RSSI值。

4.1.22 ble_gap_unpair

函数原型:

int ble_gap_unpair(const ble_addr_t *peer_addr);

功能说明:

该函数用于解配对一个设备,该设备的配对信息将从flash中移除。

4.1.23 ble_gap_unpair_oldest_peer

函数原型:

int ble_gap_unpair_oldest_peer(void);

功能说明:

该接口用于从flash中删除最旧的设备的配对信息。

4.1.24 ble_gap_unpair_oldest_except

函数原型:

int ble_gap_unpair_oldest_except(const ble_addr_t *peer_addr);

功能说明:

该函数用于从flash删除除给定设备外的最旧的设备配对信息。

4.1.25 ble_gap_read_le_phy

函数原型:

int ble_gap_read_le_phy(uint16_t conn_handle, uint8_t *tx_phy, uint8_t *rx_phy);

功能说明:

该函数用于读取某个连接使用的PHY参数。

4.1.26 ble_gap_set_prefered_default_le_phy

函数原型:

int ble_gap_set_prefered_default_le_phy(uint8_t tx_phys_mask,
                                        uint8_t rx_phys_mask);

功能说明:

该函数用于在连接创建之前,设置推荐的默认PHY参数到ble controller。

4.1.27 ble_gap_set_prefered_le_phy

函数原型:

int ble_gap_set_prefered_le_phy(uint16_t conn_handle, uint8_t tx_phys_mask,
                                uint8_t rx_phys_mask, uint16_t phy_opts);

功能说明:

该函数用于设置某个连接的PHY参数。

4.2 GATT API

以下接口均可在 SDK ble_gatt.h中找到,本节主要对一些常用接口 做了简要说明,具体细节用户可以到ble_gatt.h中参看函数声明信息,了解函数的具体用法。

4.2.1 ble_gattc_exchange_mtu

函数原型:

int ble_gattc_exchange_mtu(uint16_t conn_handle,
                           ble_gatt_mtu_fn *cb, void *cb_arg);

功能说明:

该函数用于客户端更新MTU。

4.2.2 ble_gattc_read

函数原型:

int ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
                   ble_gatt_attr_fn *cb, void *cb_arg);

功能说明:

该函数用于客户端读 ATT 数据。

4.2.3 ble_gattc_read_by_uuid

函数原型:

int ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
                           uint16_t end_handle, const ble_uuid_t *uuid,
                           ble_gatt_attr_fn *cb, void *cb_arg);

功能说明:

该函数用于客户端读取指定 uuid 特征的值。

4.2.4 ble_gattc_write_no_rsp_flat

函数原型:

int ble_gattc_write_no_rsp_flat(uint16_t conn_handle, uint16_t attr_handle,
                                const void *data, uint16_t data_len);

功能说明:

该函数用于客户端写ATT数据到特征,并且不需要对端ACK。

4.2.5 ble_gattc_write_flat

函数原型:

int ble_gattc_write_flat(uint16_t conn_handle, uint16_t attr_handle,
                         const void *data, uint16_t data_len,
                         ble_gatt_attr_fn *cb, void *cb_arg);

功能说明:

该函数用于客户端写ATT数据到特征,并且需要对端ACK。

4.2.6 ble_gatts_notify_custom

函数原型:

int ble_gatts_notify_custom(uint16_t conn_handle, uint16_t att_handle,
                            struct os_mbuf *om);

功能说明:

该函数用于服务器写Notify数据到客户端,并且不需要客户端 ACK。

4.2.7 ble_gatts_indicate_custom

函数原型:

int ble_gatts_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle,
                              struct os_mbuf *txom);

功能说明:

该函数用于服务器写Indicate数据到客户端,并且需要客户端 ACK。

4.2.8 ble_gatts_add_svcs

函数原型:

int ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs);

功能说明:

该函数用于添加一个GATT service.

4.2.9 ble_gatts_svc_set_visibility

函数原型:

int ble_gatts_svc_set_visibility(uint16_t handle, int visible);

功能说明:

该函数用于设置一个service是否可被发现。

4.2.10 ble_gatts_count_cfg

函数原型:

int ble_gatts_count_cfg(const struct ble_gatt_svc_def *defs);

功能说明:

该函数用于调整协议栈GATT service相关的计数器,在添加新service时,需要调用。

4.2.11 ble_gatts_find_svc

函数原型:

int ble_gatts_find_svc(const ble_uuid_t *uuid, uint16_t *out_handle);

功能说明:

该函数用于获取本地某个服务的handle信息。

4.2.12 ble_gatts_find_chr

函数原型:

int ble_gatts_find_chr(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid,
                       uint16_t *out_def_handle, uint16_t *out_val_handle);

功能说明:

该函数用于获取本地server中某个服务中的摸个特征的相关handle信息。

4.2.13 ble_gatts_find_dsc

函数原型:

int ble_gatts_find_dsc(const ble_uuid_t **svc_uuid, const ble_uuid_t **chr_uuid,
            const ble_uuid_t **dsc_uuid, uint16_t **out_dsc_handle);

功能说明:

该函数用于获取本地server中某个服务中的摸个特征的某个描述符handle信息。

4.2.14 ble_gattc_disc_all_svcs

函数原型:

int ble_gattc_disc_all_svcs(uint16_t conn_handle,
                            ble_gatt_disc_svc_fn *cb, void *cb_arg);

功能说明:

该函数用于发现所有主服务。

4.2.15 ble_gattc_disc_svc_by_uuid

函数原型:

int ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid,
                               ble_gatt_disc_svc_fn *cb, void *cb_arg);

功能说明:

该函数用于发现特定UUID的主服务。

4.2.16 ble_gattc_find_inc_svcs

函数原型:

int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
                            uint16_t end_handle,
                            ble_gatt_disc_svc_fn *cb, void *cb_arg);

功能说明:

该函数用于发现包含服务。

4.2.17 ble_gattc_disc_all_chrs

函数原型:

int ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
                            uint16_t end_handle, ble_gatt_chr_fn *cb,
                            void *cb_arg);

功能说明:

该函数用于发现某个服务中的所有特征。

4.2.18 ble_gattc_disc_chrs_by_uuid

函数原型:

int ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
                               uint16_t end_handle, const ble_uuid_t *uuid,
                               ble_gatt_chr_fn *cb, void *cb_arg);

功能说明:

该函数用于发现特定UUID的特征。

4.2.19 ble_gattc_disc_all_dscs

函数原型:

int ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle,
                            uint16_t end_handle,
                            ble_gatt_dsc_fn *cb, void *cb_arg);

功能说明:

该函数用于发现所有特征描述符。

4.3 SMP API

以下接口均可在 SDK ble_sm.h中找到,本节主要对一些常用接口 做了简要说明,具体细节用户可以到ble_sm.h中参看函数声明信息,了解函数的具体用法。

4.3.1 ble_sm_inject_io

函数原型:

int ble_sm_inject_io(uint16_t *conn_handle, struct ble_sm_io **pkey);

功能说明:

该函数用于在pair过程中输入 PIN Code、显示PIN Code、确认Number Compare值以及提供 OOB 信息。

4.3.2 ble_sm_set_sc_enable

函数原型:

void ble_sm_set_sc_enable(bool en);

功能说明:

该函数用于设置Auth_Req的 SC bit,以使能 SC pair mode。 默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.3.3 ble_sm_set_io_cap

函数原型:

void ble_sm_set_io_cap(uint8_t iocap);

功能说明:

该函数用于设置IO能力。默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.3.4 ble_sm_set_mitm_enable

函数原型:

void ble_sm_set_mitm_enable(bool en);

功能说明:

该函数用于使能MITM功能。默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.3.5 ble_sm_set_bond_enable

函数原型:

void ble_sm_set_bond_enable(uint8_t bond);

功能说明:

该函数用于使能bond。默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.3.6 ble_sm_set_oob_enable

函数原型:

void ble_sm_set_oob_enable(uint8_t oob_data_flag);

功能说明:

该函数用于使能oob。默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.3.7 ble_sm_set_our_key_dist

函数原型:

void ble_sm_set_our_key_dist(uint8_t key_mask);

功能说明:

该函数用于设置自己分发的key类型。默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.3.8 ble_sm_set_peer_key_dist

函数原型:

void ble_sm_set_peer_key_dist(uint8_t key_mask);

功能说明:

该函数用于设置对端分发的key类型。默认情况下,用户不需要手动调用这个API,可通过sdk_config.h配置。

4.4 Misc API

4.4.1 ble_hs_mbuf_from_flat

函数原型:

struct os_mbuf *ble_hs_mbuf_from_flat(const void **buf, uint16_t *len);

功能说明:

该函数用于将 buf 数组转化成 os_mbuf。

4.4.2 ble_hs_mbuf_to_flat

函数原型:

int ble_hs_mbuf_to_flat(const struct os_mbuf *om, void *flat, uint16_t max_len,
                        uint16_t *out_copy_len);

功能说明:

该函数用于从 os_mbuf 中读取数据到 数组。

5 BLE Lib 说明

SDK 为 pan107x 系列芯片提供了两个 lib 文件,一个带 optimize 后缀,一个不带,这两个 lib 文件可在 SDK 目录下 nimble/lib 中找到。

这两个库的区别:

  • optimize 后缀的库,是优化了 RAM 的 lib,其 RAM 消耗更少,但是功耗相对稍高

  • 不带 optimize 后缀的库,RAM 相对消耗多一些,但是功耗最优

除了上面的区别,这两个 lib 支持的功能一样, 用户可根据实际情况合理选择。