BLE 开发指南
简介
Quectel FCM242D 和 FGM842D 系列模块支持 QuecOpen® 解决方案。QuecOpen® 是基于 RTOS 系统的嵌入式开发平台。它旨在简化物联网应用的开发和设计。有关 QuecOpen® 的更多信息,请参见 快速入门指南。
本文档适用于基于 SDK 构建环境的 QuecOpen® 解决方案。它介绍了 FCM242D 和 FGM842D 系列模块的 BLE API 和开发示例。
BLE API
头文件
ql_ble.h,BLE API 的头文件,在 SDK 的 ql_components/api 目录中。除非另有说明,本文档中提到的所有头文件都在此目录中。
API 概述
API 概述:
| 函数 | 描述 |
|---|---|
ql_ble_address_get() |
获取模块的 BLE MAC 地址。 |
ql_ble_set_notice_cb() |
注册 BLE 事件回调函数。 |
ql_ble_set_adv_param() |
设置广播参数。 |
ql_ble_set_adv_data() |
设置广播数据。 |
ql_ble_set_scan_rsp_data() |
设置扫描响应数据。 |
ql_ble_create_db() |
初始化 BLE 并自定义 BLE 服务。 |
ql_ble_start_advertising() |
开始 BLE 广播。 |
ql_ble_stop_advertising() |
停止 BLE 广播。 |
ql_ble_update_param() |
更新连接参数。 |
ql_ble_set_dev_name() |
设置 BLE 设备名称。 |
ql_ble_start_scaning() |
开始 BLE 扫描。 |
ql_ble_stop_scaning() |
停止 BLE 扫描。 |
ql_ble_set_connect_dev_addr() |
设置要连接的 BLE 外围设备 MAC 地址。 |
ql_ble_start_conn() |
发起 BLE 连接。 |
ql_ble_stop_conn() |
停止 BLE 连接。 |
ql_ble_disconnect() |
中央设备或外围设备主动断开与对等设备的连接。 |
ql_ble_gatt_init() |
初始化 GATT 服务并注册 GATT 事件回调函数。 |
ql_ble_gatts_send_ntf_value() |
外围设备通过通知向中央设备发送数据。 |
ql_ble_gatts_send_ind_value() |
外围设备通过指示向中央设备发送数据。 |
ql_ble_gattc_all_service_discovery() |
中央设备发现外围设备的所有服务。 |
ql_ble_gattc_ntf_ind_enable() |
中央设备启用外围设备的通知或指示功能。 |
ql_ble_gattc_write_data_req_with_handle() |
中央设备向外围设备的指定特征值句柄写入数据,并需要外围设备的响应。 |
ql_ble_gattc_write_data_cmd_with_handle() |
中央设备通过命令向外围设备的指定特征值句柄写入数据。 |
ql_ble_gattc_read_data() |
中央设备从外围设备的指定特征值句柄读取数据。 |
ql_ble_gatt_mtu_changes() |
更改 MTU 大小。 |
API 描述
ql_ble_address_get
此函数获取模块的 BLE MAC 地址。
原型:
ql_ble_errcode_e ql_ble_address_get(uint8_t *mac_addr)
参数:
mac_addr:[出] 模块的 BLE MAC 地址。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_errcode_e
函数执行结果代码的枚举:
typedef enum
{
QL_BLE_SUCCESS = 0,
QL_BLE_ERR_PROFILE,
QL_BLE_ERR_CREATE_DB,
QL_BLE_ERR_CMD_NOT_SUPPORT,
QL_BLE_ERR_UNKNOW_IDX,
QL_BLE_ERR_BLE_STATUS,
QL_BLE_ERR_BLE_PARAM,
QL_BLE_ERR_ADV_DATA,
QL_BLE_ERR_CMD_RUN,
QL_BLE_ERR_NO_MEM,
QL_BLE_ERR_INIT_CREATE,
QL_BLE_ERR_INIT_STATE,
QL_BLE_ERR_ATTC_WRITE,
QL_BLE_ERR_ATTC_WRITE_UNREGISTER,
} ql_ble_errcode_e
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_SUCCESS |
执行成功。 |
QL_BLE_ERR_PROFILE |
配置文件错误。 |
QL_BLE_ERR_CREATE_DB |
添加 BLE 服务失败。 |
QL_BLE_ERR_CMD_NOT_SUPPORT |
不支持命令。 |
QL_BLE_ERR_UNKNOW_IDX |
未知 BLE 活动索引。 |
QL_BLE_ERR_BLE_STATUS |
BLE 状态错误。 |
QL_BLE_ERR_BLE_PARAM |
参数无效。 |
QL_BLE_ERR_ADV_DATA |
广播数据格式无效。 |
QL_BLE_ERR_CMD_RUN |
执行命令失败。 |
QL_BLE_ERR_NO_MEM |
内存不足。 |
QL_BLE_ERR_INIT_CREATE |
创建连接任务失败。 |
QL_BLE_ERR_INIT_STATE |
连接状态错误。 |
QL_BLE_ERR_ATTC_WRITE |
写入数据失败。 |
QL_BLE_ERR_ATTC_WRITE_UNREGISTER |
要写入数据的 BLE 服务未注册。 |
ql_ble_set_notice_cb
此函数注册 BLE 事件回调函数。
原型:
ql_ble_errcode_e ql_ble_set_notice_cb(ql_ble_notice_cb callback)
参数:
callback:[入] BLE 事件回调函数。有关详细信息,请参见 ql_ble_notice_cb。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_notice_cb
此函数是 BLE 事件回调函数。
原型:
typedef void (*ql_ble_notice_cb)(ql_ble_notify_e notice, void *param)
参数:
notice:[入] BLE 事件类型。有关详细信息,请参见 ql_ble_notify_e。
param:[入] BLE 事件参数。
返回值:
无
ql_ble_notify_e
BLE 事件类型的枚举:
typedef enum
{
QL_BLE_STACK_OK = 0,
QL_BLE_REPORT_ADV_EVENT,
QL_BLE_MTU_CHANGE_EVENT,
QL_BLE_CONNECT_EVENT,
QL_BLE_DISCONNECT_EVENT,
QL_BLE_INIT_CONNECT_EVENT,
QL_BLE_ADV_STOP_EVENT,
QL_BLE_SCAN_STOP_EVENT,
QL_BLE_CONN_PARAM_UPDATE_EVENT,
QL_BLE_LINK_RSSI_EVENT,
QL_BLE_SEC_MASTER_AUTH_REQ,
QL_BLE_SEC_MASTER_ENCRYPT,
QL_BLE_SEC_SLAVE_ENCRYPT,
QL_BLE_BOND_START_EVENT,
QL_BLE_SEC_PEER_IDENTITY_ADDR,
QL_BLE_BOND_FAIL_EVENT,
} ql_ble_notify_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_STACK_OK |
BLE 协议栈已准备就绪。 |
QL_BLE_REPORT_ADV_EVENT |
返回扫描结果。 |
QL_BLE_MTU_CHANGE_EVENT |
MTU 已更改。 |
QL_BLE_CONNECT_EVENT |
模块作为外围设备与中央设备建立连接。 |
QL_BLE_DISCONNECT_EVENT |
断开连接事件。 |
QL_BLE_INIT_CONNECT_EVENT |
模块作为中央设备与外围设备建立连接。 |
QL_BLE_ADV_STOP_EVENT |
广播已停止。 |
QL_BLE_SCAN_STOP_EVENT |
扫描已停止。 |
QL_BLE_CONN_PARAM_UPDATE_EVENT |
连接参数已更新。 |
QL_BLE_LINK_RSSI_EVENT |
获取连接链路的 RSSI 值。 |
QL_BLE_SEC_MASTER_AUTH_REQ |
中央设备收到外围设备的认证请求。 |
QL_BLE_SEC_MASTER_ENCRYPT |
中央设备的链路加密。 |
QL_BLE_SEC_SLAVE_ENCRYPT |
外围设备的链路加密。 |
QL_BLE_BOND_START_EVENT |
绑定已开始。 |
QL_BLE_SEC_PEER_IDENTITY_ADDR |
获取对等设备信息。 |
QL_BLE_BOND_FAIL_EVENT |
绑定失败。 |
ql_ble_set_adv_param
此函数设置广播参数。
原型:
ql_ble_errcode_e ql_ble_set_adv_param(ql_ble_adv_param_t adv_param)
参数:
adv_param:
[入] 广播参数。有关详细信息,请参见 ql_ble_adv_param_t。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_adv_param_t
广播参数的结构:
typedef struct
{
ql_ble_adv_mode_e mode;
ql_ble_addr_type_e addr_type;
ql_ble_adv_mac_addr_t peer_addr;
ql_ble_phy_e phy;
uint16_t adv_intv_min;
uint16_t adv_intv_max;
ql_ble_adv_channel_e channel;
ql_ble_adv_filter_e filter;
uint8_t adv_sid;
uint16_t per_adv_intv_min;
uint16_t per_adv_intv_max;
ql_ble_adv_disc_mode_e disc_mode;
} ql_ble_adv_param_t;
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
ql_ble_adv_mode_e |
mode |
广播模式。有关详细信息,请参见 ql_ble_adv_mode_e。(目前不支持) |
ql_ble_addr_type_e |
addr_type |
广播地址类型。有关详细信息,请参见 ql_ble_addr_type_e。(目前不支持) |
ql_ble_adv_mac_addr_t |
peer_addr |
外围设备 MAC 地址。有关详细信息,请参见 ql_ble_adv_mac_addr_t。(目前不支持) |
ql_ble_phy_e |
phy |
广播的物理层类型。有关详细信息,请参见 ql_ble_phy_e。(目前不支持) |
| uint16_t | adv_intv_min |
最小广播间隔。范围:32–16384。单位:0.625 ms。时间范围:20 ms–10.24 s。 |
| uint16_t | adv_intv_max |
最大广播间隔。范围:32–16384。单位:0.625 ms。时间范围:20 ms–10.24 s。 |
ql_ble_adv_channel_e |
channel |
广播通道。有关详细信息,请参见 ql_ble_adv_channel_e。 |
ql_ble_adv_filter_e |
filter |
广播过滤策略。有关详细信息,请参见 ql_ble_adv_filter_e。(目前不支持) |
| uint8_t | adv_sid |
广播索引。它仅适用于扩展广播和周期广播。范围:0–0xF。(目前不支持) |
| uint16_t | per_adv_intv_min |
外围设备的周期广播最小间隔。范围:32–16384。单位:0.625 ms。时间范围:20 ms–10.24 s。(目前不支持) |
| uint16_t | per_adv_intv_max |
外围设备的周期广播最大间隔。范围:32–16384。单位:0.625 ms。时间范围:20 ms–10.24 s。(目前不支持) |
ql_ble_adv_disc_mode_e |
disc_mode |
广播发现模式。有关详细信息,请参见 ql_ble_adv_disc_mode_e。(目前不支持) |
ql_ble_adv_mode_e
广播模式的枚举:
typedef enum
{
QL_BLE_ADV_MODE_UNDIRECT = 0x01,
QL_BLE_ADV_MODE_DIRECT = 0x02,
QL_BLE_ADV_MODE_NON_CONN_NON_SCAN = 0x03,
QL_BLE_ADV_MODE_NON_CONN_SCAN = 0x04,
QL_BLE_ADV_MODE_HDC_DIRECT = 0x05,
QL_BLE_ADV_MODE_BEACON = 0x06,
QL_BLE_ADV_MODE_CUSTOM = 0x07,
QL_BLE_ADV_MODE_EXTEND_CONN_UNDIRECT = 0x11,
QL_BLE_ADV_MODE_EXTEND_CONN_DIRECT = 0x12,
QL_BLE_ADV_MODE_EXTEND_NON_CONN_SCAN = 0x13,
QL_BLE_ADV_MODE_EXTEND_NON_CONN_SCAN_DIRECT = 0x14,
QL_BLE_ADV_MODE_EXTEND_NON_CONN_NON_SCAN = 0x15,
QL_BLE_ADV_MODE_EXTEND_NON_CONN_NON_SCAN_DIRECT = 0x16,
QL_BLE_ADV_MODE_PER_ADV_UNDIRECT = 0x21,
QL_BLE_ADV_MODE_PER_ADV_DIRECT = 0x22,
} ql_ble_adv_mode_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_ADV_MODE_UNDIRECT |
可连接且可扫描的未定向广播。 |
QL_BLE_ADV_MODE_DIRECT |
定向广播。 |
QL_BLE_ADV_MODE_NON_CONN_NON_SCAN |
不可连接且不可扫描的广播。 |
QL_BLE_ADV_MODE_NON_CONN_SCAN |
不可连接但可扫描的广播。 |
QL_BLE_ADV_MODE_HDC_DIRECT |
高占空比可连接定向广播。 |
QL_BLE_ADV_MODE_BEACON |
信标广播。 |
QL_BLE_ADV_MODE_CUSTOM |
自定义类型。 |
QL_BLE_ADV_MODE_EXTEND_CONN_UNDIRECT |
扩展广播模式:可连接且可扫描的未定向广播。 |
QL_BLE_ADV_MODE_EXTEND_CONN_DIRECT |
扩展广播模式:可连接定向广播。 |
QL_BLE_ADV_MODE_EXTEND_NON_CONN_SCAN |
扩展广播模式:不可连接但可扫描的广播。 |
QL_BLE_ADV_MODE_EXTEND_NON_CONN_SCAN_DIRECT |
扩展模式:不可连接且可扫描的定向广播。 |
QL_BLE_ADV_MODE_EXTEND_NON_CONN_NON_SCAN |
扩展广播模式:不可连接且不可扫描的广播。 |
QL_BLE_ADV_MODE_EXTEND_NON_CONN_NON_SCAN_DIRECT |
扩展广播模式:不可连接且不可扫描的定向广播。 |
QL_BLE_ADV_MODE_PER_ADV_UNDIRECT |
周期广播模式:未定向广播。 |
QL_BLE_ADV_MODE_PER_ADV_DIRECT |
周期广播模式:定向广播。 |
ql_ble_addr_type_e
广播地址类型的枚举:
typedef enum
{
QL_BLE_ADDR_TYPE_PUBLIC = 0,
QL_BLE_ADDR_TYPE_PRIVATE,
QL_BLE_ADDR_TYPE_RANDOM_RESOVABLE,
QL_BLE_ADDR_TYPE_RANDOM_NONE_RESOVABLE,
} ql_ble_addr_type_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_ADDR_TYPE_PUBLIC |
公共地址。 |
QL_BLE_ADDR_TYPE_PRIVATE |
私有地址。 |
QL_BLE_ADDR_TYPE_RANDOM_RESOVABLE |
可解析随机地址。 |
QL_BLE_ADDR_TYPE_RANDOM_NONE_RESOVABLE |
不可解析随机地址。 |
ql_ble_adv_mac_addr_t
外围设备 MAC 地址的结构:
typedef struct
{
uint8_t addr[6];
uint8_t addr_type;
} ql_ble_adv_mac_addr_t;
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | addr |
地址。6 字节数组。 |
| uint8_t | addr_type |
地址类型。0 公共地址 1 私有随机地址 |
ql_ble_phy_e
广播物理层类型的枚举:
typedef enum
{
QL_BLE_PHY_ANY = 0,
QL_BLE_PHY_1MBPS = 1,
QL_BLE_PHY_2MBPS = 2,
QL_BLE_PHY_CODED = 3,
} ql_ble_phy_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_PHY_ANY |
任意类型。 |
QL_BLE_PHY_1MBPS |
1 Mbps 传输速率。 |
QL_BLE_PHY_2MBPS |
2 Mbps 传输速率。 |
QL_BLE_PHY_CODED |
编码类型。 |
ql_ble_adv_channel_e
广播通道的枚举:
typedef enum
{
QL_BLE_ADV_CHAN_37 = 0x01,
QL_BLE_ADV_CHAN_38 = 0x02,
QL_BLE_ADV_CHAN_39 = 0x04,
QL_BLE_ADV_CHAN_ALL = 0X07,
} ql_ble_adv_channel_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_ADV_CHAN_37 |
通道 37。 |
QL_BLE_ADV_CHAN_38 |
通道 38。 |
QL_BLE_ADV_CHAN_39 |
通道 39。 |
QL_BLE_ADV_CHAN_ALL |
所有通道。 |
ql_ble_adv_filter_e
广播过滤策略的枚举:
typedef enum
{
QL_BLE_ADV_ALLOW_SCAN_ANY_CON_ANY = 0x00,
QL_BLE_ADV_ALLOW_SCAN_WLST_CON_ANY = 0x01,
QL_BLE_ADV_ALLOW_SCAN_ANY_CON_WLST = 0x02,
QL_BLE_ADV_ALLOW_SCAN_WLST_CON_WLST = 0x03,
} ql_ble_adv_filter_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_ADV_ALLOW_SCAN_ANY_CON_ANY |
任何设备都可以扫描和连接本地设备。 |
QL_BLE_ADV_ALLOW_SCAN_WLST_CON_ANY |
任何设备都可以连接本地设备,但只有白名单中的设备可以扫描本地设备。 |
QL_BLE_ADV_ALLOW_SCAN_ANY_CON_WLST |
任何设备都可以扫描本地设备,但只有白名单中的设备可以连接本地设备。 |
QL_BLE_ADV_ALLOW_SCAN_WLST_CON_WLST |
只有白名单中的设备可以扫描和连接本地设备。 |
ql_ble_adv_disc_mode_e
广播发现模式的枚举:
typedef enum
{
QL_BLE_ADV_DISC_MODE_GEN_DISC = 0,
QL_BLE_ADV_DISC_MODE_LIM_DISC = 1,
QL_BLE_ADV_DISC_MODE_NON_DISC = 2,
QL_BLE_ADV_DISC_MODE_MAX = 3,
} ql_ble_adv_disc_mode_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_ADV_DISC_MODE_GEN_DISC |
通用发现模式。 |
QL_BLE_ADV_DISC_MODE_LIM_DISC |
有限发现模式。 |
QL_BLE_ADV_DISC_MODE_NON_DISC |
非发现模式。 |
ql_ble_set_adv_data
此函数设置广播数据。
原型:
ql_ble_errcode_e ql_ble_set_adv_data(uint8_t *adv_buff, uint16_t adv_len)
参数:
adv_buff:
[入] 广播数据,应根据 BLE 广播数据规则编写。
adv_len:
[入] 广播数据的长度。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_set_scan_rsp_data
此函数设置扫描响应数据。
原型:
ql_ble_errcode_e ql_ble_set_scan_rsp_data(uint8_t *scan_rsp, uint16_t scan_rsp_len)
参数:
scan_rsp:
[入] 扫描响应数据,应根据 BLE 广播数据规则编写。
scan_rsp_len:
[入] 扫描响应数据的长度。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_create_db
此函数初始化 BLE 并自定义 BLE 服务。
原型:
ql_ble_errcode_e ql_ble_create_db(ql_ble_gatt_service_t *service, uint8_t *svc_id)
参数:
service:
[入] BLE 服务列表。有关详细信息,请参见 ql_ble_gatt_service_t。
svc_id:
[入] BLE 服务 ID。(目前不支持)
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gatt_service_t
BLE 服务列表的结构:
typedef struct
{
uint16_t prf_task_id;
uint8_t uuid[16];
uint8_t att_db_nb;
uint16_t start_hdl;
ql_ble_attm_desc_t* att_db;
uint8_t svc_perm;
}ql_ble_gatt_service_t;
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint16_t | prf_task_id |
BLE 服务 ID。 |
| uint8_t | uuid |
BLE 服务 UUID。 |
| uint8_t | att_db_nb |
属性数据库数量。 |
| uint16_t | start_hdl |
服务起始句柄。 |
ql_ble_attm_desc_t |
att_db |
BLE 服务属性数据库。有关详细信息,请参见 ql_ble_attm_desc_t。 |
| uint8_t | svc_perm |
BLE 服务配置。 |
ql_ble_attm_desc_t
BLE 服务属性数据库的结构:
typedef struct
{
uint8_t uuid[16];
uint16_t info;
uint16_t ext_info;
}ql_ble_attm_desc_t
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | uuid |
属性 UUID。 |
| uint16_t | info |
属性信息。 |
| uint16_t | ext_info |
扩展属性信息。 |
ql_ble_start_advertising
此函数开始 BLE 广播。
原型:
ql_ble_errcode_e ql_ble_start_advertising(uint16_t duration)
参数:
duration:
[入] 广播持续时间。单位:10 ms。0 表示不主动停止广播。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_stop_advertising
此函数停止 BLE 广播。
原型:
ql_ble_errcode_e ql_ble_stop_advertising(void)
参数:
无
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_update_param
此函数更新连接参数。
原型:
ql_ble_errcode_e ql_ble_update_param(uint8_t conn_idx, uint16_t intv_min, uint16_t intv_max, uint16_t latency, uint16_t sup_to)
参数:
conn_idx:
[入] 连接索引。
intv_min:
[入] 最小连接间隔。范围:6–3200。单位:1.25 ms。时间范围:7.5 ms–4 s。
intv_max:
[入] 最大连接间隔。范围:6–3200。单位:1.25 ms。时间范围:7.5 ms–4 s。
latency:
[入] 外围设备上可忽略的连接间隔数量。它必须符合 (1 + latency) × intv_max × 2 × 1.25 < sup_to × 10。
sup_to:
[入] 连接超时周期。范围:10–3200。单位:10 ms。时间范围:100 ms–32 s。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_set_dev_name
此函数设置 BLE 设备名称。
原型:
ql_ble_errcode_e ql_ble_set_dev_name(uint8_t *name , uint8_t name_len)
参数:
name:
[入] BLE 设备名称。
name_len:
[入] BLE 设备名称的长度。最大值:18 字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_start_scaning
此函数开始 BLE 扫描。
原型:
ql_ble_errcode_e ql_ble_start_scaning(ql_ble_scan_param_t scan_param)
参数:
scan_param:
[入] 扫描参数。有关详细信息,请参见 ql_ble_scan_param_t。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_scan_param_t
扫描参数的结构:
typedef struct
{
ql_ble_scan_mode_e scan_mode;
ql_ble_phy_e phy;
uint8_t dup_filt;
uint16_t scan_intv;
uint16_t scan_wd;
}ql_ble_scan_param_t
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
ql_ble_scan_mode_e |
scan_mode |
扫描模式。有关详细信息,请参见 ql_ble_scan_mode_e。 |
ql_ble_phy_e |
phy |
广播的物理层类型。有关详细信息,请参见 ql_ble_phy_e。 |
| uint8_t | dup_filt |
重复数据包过滤策略。 |
| uint16_t | scan_intv |
扫描间隔。单位:0.626 ms。 |
| uint16_t | scan_wd |
扫描窗口。单位:0.626 ms。 |
ql_ble_scan_mode_e
扫描模式的枚举:
typedef enum
{
QL_BLE_SCAN_MODE_GEN_DISC = 0,
QL_BLE_SCAN_MODE_OBSERVER = 1,
QL_BLE_SCAN_MODE_MAX = 3,
} ql_ble_scan_mode_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_SCAN_MODE_GEN_DISC |
通用发现模式。 |
QL_BLE_SCAN_MODE_OBSERVER |
观察者模式。 |
ql_ble_stop_scaning
此函数停止 BLE 扫描。
原型:
ql_ble_errcode_e ql_ble_stop_scaning(void)
参数:
无
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_set_connect_dev_addr
此函数设置要连接的 BLE 外围设备 MAC 地址。
原型:
ql_ble_errcode_e ql_ble_set_connect_dev_addr(ql_ble_adv_mac_addr_t *addr)
参数:
addr:
[入] 要连接的外围设备 MAC 地址。有关详细信息,请参见 ql_ble_adv_mac_addr_t。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_start_conn
此函数发起 BLE 连接。
原型:
ql_ble_errcode_e ql_ble_start_conn(uint16_t intv_min,uint16_t intv_max,uint16_t latency, uint16_t sup_to)
参数:
intv_min:
[入] 最小连接间隔。范围:6–3200。单位:1.25 ms。时间范围:7.5 ms–4 s。
intv_max:
[入] 最大连接间隔。范围:6–3200。单位:1.25 ms。时间范围:7.5 ms–4 s。
latency:
[入] 外围设备上可忽略的连接间隔数量。它必须符合 (1 + latency) × intv_max × 2 × 1.25 < sup_to × 10。
sup_to:
[入] 连接超时周期。范围:10–3200。单位:10 ms。时间范围:100 ms–32 s。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_stop_conn
此函数停止 BLE 连接。
原型:
ql_ble_errcode_e ql_ble_stop_conn(void)
参数:
无
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_disconnect
此函数由中央设备或外围设备主动断开与对等设备的连接。
原型:
ql_ble_errcode_e ql_ble_disconnect(uint8_t conn_idx)
参数:
conn_idx:
[入] 连接索引。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gatt_init
此函数初始化 GATT 服务并注册 GATT 事件回调函数。
原型:
ql_ble_errcode_e ql_ble_gatt_init(ql_ble_gatt_msg_handler_t gatt_evt)
参数:
gatt_evt:
[入] GATT 事件回调函数。有关详细信息,请参见 ql_ble_gatt_msg_handler_t。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gatt_msg_handler_t
此函数是 GATT 事件回调函数。
原型:
typedef uint16_t (*ql_ble_gatt_msg_handler_t)(ql_ble_gatt_msg_t *p_msg)
参数:
p_msg:
[入] GATT 事件。有关详细信息,请参见 ql_ble_gatt_msg_t。
返回值:
返回 uint16 类型的值,目前没有具体含义。
ql_ble_gatt_msg_t
GATT 事件的结构:
typedef struct
{
ql_ble_gatt_msg_evt_t msg_evt;
uint8_t conn_idx;
union
{
ql_ble_gatt_data_report report;
ql_ble_gatt_op_cmp_t op;
ql_ble_gatt_svc_disc_s svc_disc;
ql_ble_gatt_svc_inc_s svc_inc;
ql_ble_gatt_char_disc_s char_disc;
ql_ble_gatt_desc_disc_s desc_disc;
} param;
}ql_ble_gatt_msg_t
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
ql_ble_gatt_msg_evt_t |
msg_evt |
GATT 事件类型。有关详细信息,请参见 ql_ble_gatt_msg_evt_t。 |
| uint8_t | conn_idx |
连接索引。 |
ql_ble_gatt_data_report |
report |
GATT 数据报告。有关详细信息,请参见 ql_ble_gatt_data_report。 |
ql_ble_gatt_op_cmp_t |
op |
GATT 操作类型,包括读取、写入、通知和指示。有关详细信息,请参见 ql_ble_gatt_op_cmp_t。 |
ql_ble_gatt_svc_disc_s |
svc_disc |
发现所有服务。有关详细信息,请参见 ql_ble_gatt_svc_disc_s。 |
ql_ble_gatt_svc_inc_s |
svc_inc |
根据 UUID 发现包含的服务。有关详细信息,请参见 ql_ble_gatt_svc_inc_s。 |
ql_ble_gatt_char_disc_s |
char_disc |
特征发现。有关详细信息,请参见 ql_ble_gatt_char_disc_s。 |
ql_ble_gatt_desc_disc_s |
desc_disc |
特征描述符发现。有关详细信息,请参见 ql_ble_gatt_desc_disc_s。 |
ql_ble_gatt_msg_evt_t
GATT 事件类型的枚举:
typedef enum
{
QL_BLE_GATT_MSG_READ_REQ,
QL_BLE_GATT_MSG_WRITE_REQ,
QL_BLE_GATT_MSG_ATT_INFO_REQ,
QL_BLE_GATT_MSG_NTF_REQ,
QL_BLE_GATT_MSG_IND_REQ,
QL_BLE_GATT_MSG_READ_IND,
QL_BLE_GATT_MSG_CMP_EVT,
QL_BLE_GATT_MSG_LINK_CREATE,
QL_BLE_GATT_MSG_LINK_LOST,
QL_BLE_GATT_MSG_DISC_SVC,
QL_BLE_GATT_MSG_DISC_SVC_INC,
QL_BLE_GATT_MSG_DISC_CHAR,
QL_BLE_GATT_MSG_DISC_CHAR_DESC,
QL_BLE_GATT_MSG_HANDLE_ERROR = 0x80,
} ql_ble_gatt_msg_evt_t;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_GATT_MSG_READ_REQ |
读取数据请求。 |
QL_BLE_GATT_MSG_WRITE_REQ |
写入数据请求。 |
QL_BLE_GATT_MSG_ATT_INFO_REQ |
属性信息请求。 |
QL_BLE_GATT_MSG_NTF_REQ |
从 GATT 外围设备接收的通知数据。 |
QL_BLE_GATT_MSG_IND_REQ |
从 GATT 外围设备接收的指示数据。 |
QL_BLE_GATT_MSG_READ_IND |
读取请求响应。 |
QL_BLE_GATT_MSG_CMP_EVT |
操作完成事件。 |
QL_BLE_GATT_MSG_LINK_CREATE |
链路已创建。 |
QL_BLE_GATT_MSG_LINK_LOST |
链路已丢失。 |
QL_BLE_GATT_MSG_DISC_SVC |
所有服务已发现。 |
QL_BLE_GATT_MSG_DISC_SVC_INC |
包含的服务已发现。 |
QL_BLE_GATT_MSG_DISC_CHAR |
特征已发现。 |
QL_BLE_GATT_MSG_DISC_CHAR_DESC |
特征描述符已发现。 |
QL_BLE_GATT_MSG_HANDLE_ERROR |
GATT 消息处理错误。 |
ql_ble_gatt_data_report
GATT 数据报告的结构:
typedef struct
{
uint8_t svc_id;
uint16_t att_idx;
uint16_t char_handle;
ql_ble_data_t data;
} ql_ble_gatt_data_report
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | svc_id |
BLE 服务 ID。 |
| uint16_t | att_idx |
服务表中的属性索引。 |
| uint16_t | char_handle |
外围设备服务中的属性句柄号。 |
ql_ble_data_t |
data |
数据。有关详细信息,请参见 ql_ble_data_t。 |
ql_ble_data_t
数据结构定义如下:
typedef struct
{
uint16_t len;
uint8_t *data;
} ql_ble_data_t
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint16_t | len |
数据长度。单位:字节。 |
| uint8_t | data |
数据内容。 |
ql_ble_gatt_op_cmp_t
GATT 操作类型的结构:
typedef struct
{
ql_ble_gatt_operation operation;
uint8_t status;
void *arg;
}ql_ble_gatt_op_cmp_t
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
ql_ble_gatt_operation |
operation |
GATT 操作类型。有关详细信息,请参见 ql_ble_gatt_operation。 |
| uint8_t | status |
操作状态。 |
| void | *arg | 参数指针。 |
ql_ble_gatt_operation
GATT 操作类型的枚举:
typedef enum
{
QL_BLE_GATT_OP_NONE,
QL_BLE_GATT_OP_NOTIFY,
QL_BLE_GATT_OP_INDICATION,
QL_BLE_GATT_OP_WRITE_REQ,
QL_BLE_GATT_OP_WRITE_CMD,
QL_BLE_GATT_OP_READ,
QL_BLE_GATT_OP_PEER_SVC_DISC_END,
} ql_ble_gatt_operation;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_GATT_OP_NONE |
无操作 |
QL_BLE_GATT_OP_NOTIFY |
通知 |
QL_BLE_GATT_OP_INDICATION |
指示 |
QL_BLE_GATT_OP_WRITE_REQ |
写入请求 |
QL_BLE_GATT_OP_WRITE_CMD |
写入命令 |
QL_BLE_GATT_OP_READ |
读取 |
QL_BLE_GATT_OP_PEER_SVC_DISC_END |
完成对等设备服务的发现 |
ql_ble_gatt_svc_disc_s
所有服务发现的结构:
typedef struct
{
uint8_t uuid_len;
uint8_t uuid[16];
uint16_t start_hdl;
uint16_t end_hdl;
}ql_ble_gatt_svc_disc_s
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | uuid_len |
服务 UUID 长度。单位:字节。 |
| uint8_t | uuid |
服务 UUID。 |
| uint16_t | start_hdl |
服务起始句柄。 |
| uint16_t | end_hdl |
服务结束句柄。 |
ql_ble_gatt_svc_inc_s
根据 UUID 发现包含服务的结构:
typedef struct
{
uint8_t uuid_len;
uint8_t uuid[16];
uint16_t start_hdl;
uint16_t end_hdl;
}ql_ble_gatt_svc_inc_s
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | uuid_len |
服务 UUID 长度。单位:字节。 |
| uint8_t | uuid |
服务 UUID。 |
| uint16_t | start_hdl |
服务起始句柄。 |
| uint16_t | end_hdl |
服务结束句柄。 |
ql_ble_gatt_char_disc_s
特征发现的结构:
typedef struct
{
uint8_t uuid_len;
uint8_t uuid[16];
uint16_t handle;
ql_ble_gatt_prop_e prop;
}ql_ble_gatt_char_disc_s
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | uuid_len |
特征 UUID 长度。单位:字节。 |
| uint8_t | uuid |
特征 UUID。 |
| uint16_t | handle |
特征值句柄。 |
ql_ble_gatt_prop_e |
prop |
GATT 特征属性。有关详细信息,请参见 ql_ble_gatt_prop_e。 |
ql_ble_gatt_prop_e
GATT 特征属性的枚举:
typedef enum
{
QL_BLE_GATT_PROP_BROADCAST = 0x01,
QL_BLE_GATT_PROP_READ = 0x02,
QL_BLE_GATT_PROP_WRITE_CMD = 0x04,
QL_BLE_GATT_PROP_WRITE = 0x08,
QL_BLE_GATT_PROP_NOTIFY = 0x10,
QL_BLE_GATT_PROP_INDICATE = 0x20,
QL_BLE_GATT_PROP_WRITE_SIGNED = 0x40,
QL_BLE_GATT_PROP_EXTENDED = 0x80,
} ql_ble_gatt_prop_e;
成员:
| 成员 | 描述 |
|---|---|
QL_BLE_GATT_PROP_BROADCAST |
广播属性 |
QL_BLE_GATT_PROP_READ |
读取属性 |
QL_BLE_GATT_PROP_WRITE_CMD |
无响应写入 |
QL_BLE_GATT_PROP_WRITE |
写入 |
QL_BLE_GATT_PROP_NOTIFY |
通知 |
QL_BLE_GATT_PROP_INDICATE |
指示 |
QL_BLE_GATT_PROP_WRITE_SIGNED |
认证签名写入 |
QL_BLE_GATT_PROP_EXTENDED |
扩展属性 |
ql_ble_gatt_desc_disc_s
特征描述符发现的结构:
typedef struct
{
uint8_t uuid_len;
uint8_t uuid[16];
uint16_t handle;
} ql_ble_gatt_desc_disc_s;
参数:
| 类型 | 参数 | 描述 |
|---|---|---|
| uint8_t | uuid_len |
特征描述符 UUID 长度。单位:字节。 |
| uint8_t | uuid |
特征描述符 UUID。 |
| uint16_t | handle |
句柄。 |
ql_ble_gatts_send_ntf_value
此函数由外围设备(即模块)通过通知向中央设备发送数据。
原型:
ql_ble_errcode_e ql_ble_gatts_send_ntf_value(uint8_t conn_idx, uint8_t svc_id, uint8_t att_idx, uint8_t *data, uint16_t len)
参数:
conn_idx:
[入] 连接索引。
svc_id:
[入] BLE 服务 ID。
att_idx:
[入] 服务列表中的属性索引。
data:
[入] 要发送的数据。
len:
[入] 数据长度。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gatts_send_ind_value
此函数由外围设备(即模块)通过指示向中央设备发送数据。
原型:
ql_ble_errcode_e ql_ble_gatts_send_ind_value(uint8_t conn_idx, uint8_t svc_id, uint8_t att_idx, uint8_t *data, uint16_t len)
参数:
conn_idx:
[入] 连接索引。
svc_id:
[入] BLE 服务 ID。
att_idx:
[入] 服务列表中的属性索引。
data:
[入] 要发送的数据。
len:
[入] 数据长度。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gattc_all_service_discovery
此函数由中央设备(即模块)发现外围设备的所有服务。
原型:
ql_ble_errcode_e ql_ble_gattc_all_service_discovery( uint8_t conn_idx)
参数:
conn_idx:
[入] 连接索引。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gattc_ntf_ind_enable
此函数由中央设备(即模块)启用外围设备的通知或指示功能。
原型:
ql_ble_errcode_e ql_ble_gattc_ntf_ind_enable(uint8_t conn_idx , uint16_t handle , bool ntf , bool ind)
参数:
conn_idx:
[入] 连接索引。
handle:
[入] 服务列表中的属性句柄。
ntf:
[入] 是否启用通知。
0 禁用
1 启用
ind:
[入] 是否启用指示。
0 禁用
1 启用
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gattc_write_data_req_with_handle
此函数由中央设备(即模块)向外围设备的指定特征值句柄写入数据,并需要外围设备的响应。
原型:
ql_ble_errcode_e ql_ble_gattc_write_data_req_with_handle(uint8_t conn_idx,uint16_t handle,uint8_t *data,uint16_t data_len)
参数:
conn_idx:
[入] 连接索引。
handle:
[入] 外围设备特征值句柄。
data:
[入] 要写入的数据。
data_len:
[入] 数据长度。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gattc_write_data_cmd_with_handle
此函数由中央设备(即模块)通过命令向外围设备的指定特征值句柄写入数据。
原型:
ql_ble_errcode_e ql_ble_gattc_write_data_cmd_with_handle(uint8_t conn_idx,uint16_t handle, uint8_t *data,uint16_t data_len)
参数:
conn_idx:
[入] 连接索引。
handle:
[入] 外围设备特征值句柄。
data:
[入] 要写入的数据。
data_len:
[入] 数据长度。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gattc_read_data
此函数由中央设备(即模块)从外围设备的指定特征值句柄读取数据。
原型:
ql_ble_errcode_e ql_ble_gattc_read_data(uint8_t conn_idx, uint16_t handle)
参数:
conn_idx:
[入] 连接索引。
handle:
[入] 外围设备特征值句柄。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
ql_ble_gatt_mtu_changes
此函数更改 MTU 大小。
原型:
ql_ble_errcode_e ql_ble_gatt_mtu_changes(uint8_t conn_idx, uint16_t mtu_size)
参数:
conn_idx:
[入] 连接索引。
mtu_size:
[入] 更新的 MTU 值。最大值:512。单位:字节。
返回值:
函数执行结果代码。有关详细信息,请参见 ql_ble_errcode_e。
示例
本章描述如何使用上述 BLE API 以及如何调试应用程序的 BLE 数据发送和接收功能示例。
BLE API 的外围设备和中央设备功能示例位于 ql_applicationexampleble_demoql_ble_demo.c 目录中,您可以在其中查看 BLE API 的完整示例。
模块作为 BLE 外围设备
初始化 BLE 外围设备。示例代码如下:
// ... static void ql_ble_demo_entry(void *arg) { ql_ble_demo_msg ble_demo_msg; uint8_t ble_mac[6] = {0}; ql_ble_address_get(ble_mac); os_printf("ble_mac: [%02x:%02x:%02x:%02x:%02x:%02x] rn", ble_mac[0], ble_mac[1], ble_mac[2], ble_mac[3], ble_mac[4], ble_mac[5]); /* 设置 ble 事件回调 */ ql_ble_set_notice_cb(ql_ble_demo_gap_cb); ql_ble_gatt_init(ql_ble_demo_gatt_cb); while (1) { os_memset((void *)&ble_demo_msg, 0x00, sizeof(ql_ble_demo_msg)); if (ql_rtos_queue_wait(ql_ble_demo_q, (uint8 *)&ble_demo_msg, sizeof(ble_demo_msg), QL_WAIT_FOREVER) == 0) { ql_ble_demo_msg_process(&ble_demo_msg); } } }添加 BLE 服务并设置广播参数。示例代码如下:
uint8_t svc_uuid[16] = {0x36, 0xF5, 0, 0, 0x34, 0x56, 0, 0, 0, 0, 0x28, 0x37, 0, 0, 0, 0}; ql_ble_gatt_service_t service = {0}; service.prf_task_id = 0; service.att_db_nb = QL_BLE_DEMO_IDX_NB; service.start_hdl = 0; service.att_db = ql_ble_demo_profile_db; service.svc_perm = QL_PERM_SET(SVC_UUID_LEN, UUID_128); memcpy((void *)&service.uuid[0], (const void *)&svc_uuid[0], 16); ret = ql_ble_create_db(&service, 0); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_create_db, ret: [%d] rn", ret); return; } ql_ble_adv_param_t adv_param = {0}; adv_param.adv_intv_min = 160; adv_param.adv_intv_max = 160; adv_param.channel = QL_BLE_ADV_CHAN_ALL; ret = ql_ble_set_adv_param(adv_param); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_set_adv_param, ret: [%d] rn", ret); return; }配置广播数据、扫描响应数据并开始广播。示例代码如下:
uint8_t adv_data[31] = {0}; adv_data[0] = 0x03; adv_data[1] = 0xFF; adv_data[2] = 0x31; adv_data[3] = 0x32; ret = ql_ble_set_adv_data(&adv_data[0], 4); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_set_adv_data, ret: [%d] rn", ret); return; } uint8_t scan_rsp_data[31] = {0}; uint8_t len = 0; len = snprintf((char *)&scan_rsp_data[2], sizeof(scan_rsp_data) - 1, "FGM842D"); scan_rsp_data[0] = len + 1; scan_rsp_data[1] = 0x09; ret = ql_ble_set_scan_rsp_data(&scan_rsp_data[0], len + 2); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_set_scan_rsp_data, ret: [%d] rn", ret); return; } ret = ql_ble_start_advertising(0); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_start_advertising, ret: [%d] rn", ret); return; }打开手机上的 nRF Connect 应用程序。点击“SCAN”以扫描外围设备,在扫描结果中选择“FGM842D”,然后点击“CONNECT”。

模块成功连接后,“CLIENT”中会显示以下信息:

- 通过 nRF Connect 应用程序向模块发送数据。模块接收数据并将数据发送回 nRF Connect 应用程序。
i. 选择可编辑的特征值,然后单击上箭头。

ii. 以文本格式输入要发送的数据,然后单击“SEND”。

iii. 模块接收数据后,将数据发送回 nRF Connect,如下图所示。

接收和发送回数据的代码示例如下:
uint16_t ql_ble_demo_gatt_cb(ql_ble_gatt_msg_t *p_msg) { os_printf("%s, msg_evt: [%d], conn_idx: [%d] rn", __func__, p_msg->msg_evt, p_msg->conn_idx); uint8_t idx = 0; switch (p_msg->msg_evt) { case QL_BLE_GATT_MSG_WRITE_REQ: { os_printf("conn_idx: [%d], svc_id: [%d], att_idx: [%d], handle: [%d], len: [%d], data: [%s] rn", p_msg->conn_idx, p_msg->param.report.svc_id, p_msg->param.report.att_idx, p_msg->param.report.char_handle, p_msg->param.report.data.len, p_msg->param.report.data.data); ql_ble_demo_msg ble_demo_msg = {0}; ble_demo_msg.msg_id = QL_BLE_DEMO_PER_GATT_SEND_NTF; ble_demo_msg.msg_param.send_ntf.con_idx = p_msg->conn_idx; ble_demo_msg.msg_param.send_ntf.svc_id = p_msg->param.report.svc_id; ble_demo_msg.msg_param.send_ntf.att_idx = p_msg->param.report.att_idx; ble_demo_msg.msg_param.send_ntf.len = p_msg->param.report.data.len; ble_demo_msg.msg_param.send_ntf.data = malloc(p_msg->param.report.data.len); memset((void *)ble_demo_msg.msg_param.send_ntf.data, 0x00, p_msg->param.report.data.len); memcpy((void *)ble_demo_msg.msg_param.send_ntf.data, (const void *)p_msg->param.report.data.data, p_msg->param.report.data.len); ql_ble_demo_msg_send(&ble_demo_msg); break; } } } // ... static void ql_ble_demo_msg_process(ql_ble_demo_msg *ble_msg) { os_printf("msg_id: %d rn", ble_msg->msg_id); switch (ble_msg->msg_id) { case QL_BLE_DEMO_PER_GATT_SEND_NTF: { ql_ble_gatts_send_ntf_value(ble_msg->msg_param.send_ntf.con_idx, ble_msg->msg_param.send_ntf.svc_id, ble_msg->msg_param.send_ntf.att_idx, ble_msg->msg_param.send_ntf.data, ble_msg->msg_param.send_ntf.len); if (ble_msg->msg_param.send_ntf.data != NULL) { free(ble_msg->msg_param.send_ntf.data); ble_demo_msg.msg_param.send_ntf.data = NULL; } break; } } }
模块作为 BLE中央设备
在此示例中,nRF Connect 应用程序用作外围设备进行测试。
初始化 BLE 中央设备。代码示例如下:
// ... static void ql_ble_demo_entry(void *arg) { ql_ble_demo_msg ble_demo_msg; uint8_t ble_mac[6] = {0}; ql_ble_address_get(ble_mac); os_printf("ble_mac: [%02x:%02x:%02x:%02x:%02x:%02x] rn", ble_mac[0], ble_mac[1], ble_mac[2], ble_mac[3], ble_mac[4], ble_mac[5]); /* 设置 ble 事件回调 */ ql_ble_set_notice_cb(ql_ble_demo_gap_cb); ql_ble_gatt_init(ql_ble_demo_gatt_cb); while (1) { os_memset((void *)&ble_demo_msg, 0x00, sizeof(ql_ble_demo_msg)); if (ql_rtos_queue_wait(ql_ble_demo_q, (uint8 *)&ble_demo_msg, sizeof(ble_demo_msg), QL_WAIT_FOREVER) == 0) { ql_ble_demo_msg_process(&ble_demo_msg); } } }设置扫描参数并开始扫描。代码示例如下:
// ... case QL_BLE_DEMO_START_SCAN: { ql_ble_scan_param_t scan_param = {0}; scan_param.scan_intv = 0x50; scan_param.scan_wd = 0x20; ret = ql_ble_start_scaning(scan_param); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_start_scaning, ret: [%d] rn", ret); return; } break; }扫描开始后,将生成 QL_BLE_REPORT_ADV_EVENT 事件以选择要连接的外围设备。
// ... case QL_BLE_REPORT_ADV_EVENT: { ql_ble_recv_adv_t *recv_adv = (ql_ble_recv_adv_t *)param; os_printf("adv_type: [%d], adv_addr_type: [%d], adv_addr:[%02x:%02x:%02x:%02x:%02x:%02x], rssi: [%d] rn", recv_adv->adv_type, recv_adv->adv_addr_type, recv_adv->adv_addr[0], recv_adv->adv_addr[1], recv_adv->adv_addr[2], recv_adv->adv_addr[3], recv_adv->adv_addr[4], recv_adv->adv_addr[5], recv_adv->rssi); #if CFG_ENABLE_QUECTEL_BLE_CENTRAL ql_ble_demo_report_adv_deal(recv_adv); #endif break; } // ... void ql_ble_demo_report_adv_deal(ql_ble_recv_adv_t *p_adv_report) { uint8_t index = 0; while (index < p_adv_report->data_len) { gapAdStructure_t adElement; adElement.length = p_adv_report->data[index]; adElement.adType = p_adv_report->data[index + 1]; adElement.aData = (uint8_t *)&p_adv_report->data[index + 2]; if ((adElement.adType = 0x08) || (adElement.adType = 0x09)) { if (!memcmp(adElement.aData, "phone_server", strlen("phone_server"))) // check adv name { os_printf("Found Device NAME, RSSI:%ddBm, mac:", p_adv_report->rssi); for (uint8_t i = 0; i < 6; i++) { os_printf("%02X ", p_adv_report->adv_addr[i]); } os_printf("rn"); memcpy(&peer_addr.addr[0], p_adv_report->adv_addr, 6); peer_addr.addr_type = p_adv_report->adv_addr_type; ql_ble_demo_msg ble_demo_msg = {0}; ble_demo_msg.msg_id = QL_BLE_DEMO_STOP_SCAN; ql_ble_demo_msg_send(&ble_demo_msg); return; } } /* Move on to the next AD element type */ index += adElement.length + sizeof(uint8_t); } }连接外围设备后,将生成 QL_BLE_INIT_CONNECT_EVENT 事件以发现外围设备的服务。
// ... case QL_BLE_DEMO_STOP_SCAN: { ret = ql_ble_stop_scaning(); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_stop_scaning, ret: [%d] rn", ret); return; } if (ql_ble_demo_sem) { ql_rtos_semaphore_wait(ql_ble_demo_sem, QL_BLE_DEMO_TIMEOUT_MS); } ql_ble_set_connect_dev_addr(&peer_addr); ret = ql_ble_start_conn(0x30, 0x30, 0, 500); if (ret != QL_BLE_SUCCESS) { os_printf("ql_ble_start_conn, ret: [%d] rn", ret); return; } break; } // ... case QL_BLE_INIT_CONNECT_EVENT: { ql_ble_conn_ind_t *conn_ind = (ql_ble_conn_ind_t *)param; os_printf("conn_idx: [%d], addr_type: [%d], peer_addr: [%02x:%02x:%02x:%02x:%02x:%02x] rn", conn_ind->conn_idx, conn_ind->peer_addr_type, conn_ind->peer_addr[0], conn_ind->peer_addr[1], conn_ind->peer_addr[2], conn_ind->peer_addr[3], conn_ind->peer_addr[4], conn_ind->peer_addr[5]); conn_hdl = conn_ind->conn_idx; #if CFG_ENABLE_QUECTEL_BLE_CENTRAL ql_ble_demo_msg ble_demo_msg = {0}; ble_demo_msg.msg_id = QL_BLE_DEMO_CENTRAL_EXCHANGE_MTU; ql_ble_demo_msg_send(&ble_demo_msg); #endif break; } // ... case QL_BLE_MTU_CHANGE_EVENT: { ql_ble_mtu_change_t *mtu_change = (ql_ble_mtu_change_t *)param; os_printf("conn_idx: [%d], mtu_size: [%d] rn", mtu_change->conn_idx, mtu_change->mtu); #if CFG_ENABLE_QUECTEL_BLE_CENTRAL ql_ble_demo_msg ble_demo_msg = {0}; ble_demo_msg.msg_id = QL_BLE_DEMO_CEN_GATT_DISV_ALL_SRV; ql_ble_demo_msg_send(&ble_demo_msg); #endif break; } // ... case QL_BLE_DEMO_CEN_GATT_DISV_ALL_SRV: { ql_ble_gattc_all_service_discovery(conn_hdl); break; }发现外围设备的服务后,将生成 QL_BLE_GATT_MSG_CMP_EVT 事件,操作项为 QL_BLE_GATT_OP_PEER_SVC_DISC_END。
// ... case QL_BLE_GATT_MSG_CMP_EVT: { os_printf("QL_BLE_GATT_MSG_CMP_EVT, operation: [%d], status: [%d] rn", p_msg->param.op.operation, p_msg->param.op.status); if ((p_msg->param.op.operation == QL_BLE_GATT_OP_PEER_SVC_DISC_END) && (cen_chara_hdl != 0)) { #if CFG_ENABLE_QUECTEL_BLE_CENTRAL ql_ble_demo_msg ble_demo_msg = {0}; ble_demo_msg.msg_id = QL_BLE_DEMO_CEN_GATT_NTFCFG; ql_ble_demo_msg_send(&ble_demo_msg); #endif } break; }数据成功写入外围设备后,外围设备将向中央设备发送 "123456" 数据,然后生成 QL_BLE_GATT_MSG_NTF_REQ 事件。
// ... case QL_BLE_GATT_MSG_NTF_REQ: { os_printf("conn_idx: [%d], svc_id: [%d], att_idx: [%d], handle: [%d], len: [%d], data: [%s] rn", p_msg->conn_idx, p_msg->param.report.svc_id, p_msg->param.report.att_idx, p_msg->param.report.char_handle, p_msg->param.report.data.len, p_msg->param.report.data.data); #if CFG_ENABLE_QUECTEL_BLE_CENTRAL ql_ble_demo_msg ble_demo_msg = {0}; ble_demo_msg.msg_id = QL_BLE_DEMO_CEN_GATT_WRREQ; ql_ble_demo_msg_send(&ble_demo_msg); #endif break; }
附录参考
相关文档:
| 文档名称 |
|---|
| [1]: Quectel_FCM242D&FGM842D_Series_QuecOpen(SDK)_Quick_Start_Guide |
术语和缩略语
术语和缩略语:
| 缩略语 | 描述 |
|---|---|
| API | 应用程序编程接口 |
| BLE | 低功耗蓝牙 |
| GATT | 通用属性配置文件 |
| ID | 标识符 |
| IoT | 物联网 |
| MAC | 媒体访问控制 |
| MTU | 最大传输单元 |
| RSSI | 接收信号强度指示 |
| SDK | 软件开发工具包 |
| UUID | 通用唯一标识符 |