xiaozhengsheng 6df0f7d96e 初始版本
2025-08-19 09:49:41 +08:00

236 lines
8.0 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************Copyright (c)************************************************
**
**--------------File Info-----------------------------------------------------------------------------
** File name:ble_nus.c
** Last modified Date:
** Last Version:
** Descriptions :串口透传服务文件
**---------------------------------------------------------------------------------------------------*/
#include "sdk_common.h"
//这里设置了串口透传服务程序模块的“编译开关”所以要在sdk_config.h中启用BLE_NUS
#if NRF_MODULE_ENABLED(BLE_NUS)
#include "ble.h"
#include "ble_nus.h"
#include "ble_srv_common.h"
#include "nrf_log.h"
#if 0
#define NRF_LOG_MODULE_NAME ble_nus
#if BLE_NUS_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL
#define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR
#else // BLE_NUS_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL 0
#endif // BLE_NUS_CONFIG_LOG_ENABLED
NRF_LOG_MODULE_REGISTER();
#endif
#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN //RX特征最大长度字节数
#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN //TX特征最大长度字节数
//SoftDevice提交的“Write”事件处理函数
static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
{
//定义一个串口透传事件结构体变量,用于执行回调时传递参数
ble_nus_evt_t evt;
//定义write事件结构体指针并指向GATT事件的write
ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
//清空evt结构体
memset(&evt, 0, sizeof(ble_nus_evt_t));
//指向串口透传实例
evt.p_nus = p_nus;
//设置连接句柄
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
//写RX特征值
if ((p_evt_write->handle == p_nus->rx_handles.value_handle) &&
(p_nus->data_handler != NULL))
{
//设置事件类型
evt.type = BLE_NUS_EVT_RX_DATA;
//设置数据
evt.params.rx_data.p_data = p_evt_write->data;
//设置数据长度
evt.params.rx_data.length = p_evt_write->len;
//执行回调
p_nus->data_handler(&evt);
}
else
{
// Do Nothing. This event is not relevant for this service.
}
}
//SoftDevice提交的“BLE_GATTS_EVT_HVN_TX_COMPLETE”事件处理函数
static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt)
{
//定义一个串口透传事件结构体变量evt用于执行回调时传递参数
ble_nus_evt_t evt;
//清零evt
memset(&evt, 0, sizeof(ble_nus_evt_t));
//设置事件类型
evt.type = BLE_NUS_EVT_TX_RDY;
//指向串口透传服务实例
evt.p_nus = p_nus;
//设置连接句柄
evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
//执行回调
p_nus->data_handler(&evt);
}
//串口透传服务BLE事件监视者的事件回调函数
void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
//检查参数是否有效
if ((p_context == NULL) || (p_ble_evt == NULL))
{
return;
}
//定义一个串口透传结构体指针并指向串口透传结构体
ble_nus_t * p_nus = (ble_nus_t *)p_context;
//判断事件类型
switch (p_ble_evt->header.evt_id)
{
//写事件
case BLE_GATTS_EVT_WRITE:
on_write(p_nus, p_ble_evt);
break;
//TX就绪事件
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
on_hvx_tx_complete(p_nus, p_ble_evt);
break;
default:
// No implementation needed.
break;
}
}
//初始化串口透传服务
uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init)
{
ret_code_t err_code;
//定义16位UUID结构体变量
ble_uuid_t ble_uuid;
//定义128位UUID结构体变量并初始化为串口透传服务UUID基数
ble_uuid128_t nus_base_uuid = NUS_BASE_UUID;
//定义特征参数结构体变量
ble_add_char_params_t add_char_params;
//检查指针是否为NULL
VERIFY_PARAM_NOT_NULL(p_nus);
VERIFY_PARAM_NOT_NULL(p_nus_init);
//拷贝串口透传服务初始化结构体中的事件句柄
p_nus->data_handler = p_nus_init->data_handler;
//将自定义UUID基数添加到SoftDevice
err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type);
VERIFY_SUCCESS(err_code);
//UUID类型和数值赋值给ble_uuid变量
ble_uuid.type = BLE_UUID_TYPE_BLE;
ble_uuid.uuid = BLE_UUID_NUS_SERVICE;
//添加串口透传服务
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&ble_uuid,
&p_nus->service_handle);
VERIFY_SUCCESS(err_code);
/*---------------------以下代码添加RX特征--------------------*/
//添加RX特征
//配置参数之前先清零add_char_params
memset(&add_char_params, 0, sizeof(add_char_params));
//RX特征的UUID
add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC;
//RX特征的UUID类型
add_char_params.uuid_type = p_nus->uuid_type;
//设置RX特征值的最大长度
add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN;
//设置RX特征值的初始长度
add_char_params.init_len = sizeof(uint8_t);
//设置RX的特征值长度为可变长度
add_char_params.is_var_len = true;
//设置RX特征的性质支持写
add_char_params.char_props.write = 1;
//设置RX特性的性质支持读
add_char_params.char_props.read = 1;
//设置RX特征的性质支持无响应写
add_char_params.char_props.write_wo_resp = 1;
//设置读/写RX特征值的安全需求无安全性
add_char_params.read_access = SEC_OPEN;
add_char_params.write_access = SEC_OPEN;
//为串口透传服务添加RX特征
err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
/*---------------------添加RX特征-END------------------------*/
/*---------------------以下代码添加TX特征--------------------*/
//添加TX特征
//配置参数之前先清零add_char_params
memset(&add_char_params, 0, sizeof(add_char_params));
//TX特征的UUID
add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC;
//TX特征的UUID类型
add_char_params.uuid_type = p_nus->uuid_type;
//设置TX特征值的最大长度
add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN;
//设置TX特征值的初始长度
add_char_params.init_len = sizeof(uint8_t);
//设置TX的特征值长度为可变长度
add_char_params.is_var_len = true;
//设置TX特征的性质支持通知
add_char_params.char_props.notify = 1;
//设置TX特性的性质支持读
add_char_params.char_props.read = 1;
//设置读/写RX特征值的安全需求无安全性
add_char_params.read_access = SEC_OPEN;
add_char_params.write_access = SEC_OPEN;
add_char_params.cccd_write_access = SEC_OPEN;
//为串口透传服务添加TX特征
return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles);
/*---------------------添加TX特征-END------------------------*/
}
//蓝牙数据上传发送,并进行反馈
uint32_t ble_nus_data_send(ble_nus_t * p_nus,
uint8_t * p_data,
uint16_t * p_length,
uint16_t conn_handle)
{
ble_gatts_hvx_params_t hvx_params;
//验证p_uarts没有指向NULL
VERIFY_PARAM_NOT_NULL(p_nus);
//如果连接句柄无效表示没有和主机建立连接返回NRF_ERROR_NOT_FOUND
if (conn_handle == BLE_CONN_HANDLE_INVALID)
{
return NRF_ERROR_NOT_FOUND;
}
if (*p_length > BLE_NUS_MAX_DATA_LEN)
{
return NRF_ERROR_INVALID_PARAM;
}
//设置之前先清零hvx_params
memset(&hvx_params, 0, sizeof(hvx_params));
//TX特征值句柄
hvx_params.handle = p_nus->tx_handles.value_handle;
//发送的数据
hvx_params.p_data = p_data;
//发送的数据长度
hvx_params.p_len = p_length;
//类型为通知
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
//发送TX特征值通知
return sd_ble_gatts_hvx(conn_handle, &hvx_params);
}
#endif // NRF_MODULE_ENABLED(BLE_NUS)