初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

View File

@@ -0,0 +1,235 @@
/****************************************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)

View File

@@ -0,0 +1,165 @@
#ifndef BLE_NUS_H__
#define BLE_NUS_H__
#include <stdint.h>
#include <stdbool.h>
#include "sdk_config.h"
#include "ble.h"
#include "ble_srv_common.h"
#include "nrf_sdh_ble.h"
#ifdef __cplusplus
extern "C" {
#endif
//定义串口透传服务实例该实例完成2件事情
//1定义了static类型串口透传服务结构体变量为串口透传服务结构体分配了内存
//2注册了BLE事件监视者这使得串口透传程序模块可以接收BLE协议栈的事件从而可以在ble_uarts_on_ble_evt()事件回调函数中处理自己感兴趣的事件
#define BLE_NUS_DEF(_name) \
static ble_nus_t _name; \
NRF_SDH_BLE_OBSERVER(_name ## _obs, \
BLE_NUS_BLE_OBSERVER_PRIO, \
ble_nus_on_ble_evt, \
&_name)
//定义串口透传服务128位UUID基数
#define NUS_BASE_UUID {{0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
//定义串口透传服务16位UUID
#define BLE_UUID_NUS_SERVICE 0x1000 //串口透传服务16位UUID
#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x1002 //TX特征16位UUID
#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x1001 //RX特征16位UUID
//定义操作码长度
#define OPCODE_LENGTH 1
//定义句柄长度
#define HANDLE_LENGTH 2
//定义最大传输数据长度(字节数)
#if defined(NRF_SDH_BLE_GATT_MAX_MTU_SIZE) && (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 0)
#define BLE_NUS_MAX_DATA_LEN (NRF_SDH_BLE_GATT_MAX_MTU_SIZE - OPCODE_LENGTH - HANDLE_LENGTH)
#else
#define BLE_NUS_MAX_DATA_LEN (BLE_GATT_MTU_SIZE_DEFAULT - OPCODE_LENGTH - HANDLE_LENGTH)
#warning NRF_SDH_BLE_GATT_MAX_MTU_SIZE is not defined.
#endif
//定义串口透传事件类型,这是用户自己定义的,供应用程序使用
typedef enum
{
BLE_NUS_EVT_RX_DATA, //接收到新的数据
BLE_NUS_EVT_TX_RDY, //准备就绪,可以发送新数据
BLE_NUS_EVT_COMM_STARTED, /**< Notification has been enabled. */
BLE_NUS_EVT_COMM_STOPPED, /**< Notification has been disabled. */
} ble_nus_evt_type_t;
/* Forward declaration of the ble_nus_t type. */
typedef struct ble_nus_s ble_nus_t;
//串口透传服务BLE_NUS_EVT_RX_DATA事件数据结构体该结构体用于当BLE_NUS_EVT_RX_DATA产生时将接收的数据信息传递给处理函数
typedef struct
{
uint8_t const * p_data; //指向存放接收数据的缓存
uint16_t length; //接收的数据长度
} ble_nus_evt_rx_data_t;
/**@brief Nordic UART Service client context structure.
*
* @details This structure contains state context related to hosts.
*/
typedef struct
{
bool is_notification_enabled; /**< Variable to indicate if the peer has enabled notification of the RX characteristic.*/
} ble_nus_client_context_t;
//串口透传服务事件结构体
typedef struct
{
ble_nus_evt_type_t type; //事件类型
ble_nus_t * p_nus; //指向串口透传实例的指针
uint16_t conn_handle; //连接句柄
// ble_nus_client_context_t * p_link_ctx; /**< A pointer to the link context. */
union
{
ble_nus_evt_rx_data_t rx_data; //BLE_NUS_EVT_RX_DATA事件数据
} params;
} ble_nus_evt_t;
//定义函数指针类型ble_uarts_data_handler_t
typedef void (* ble_nus_data_handler_t) (ble_nus_evt_t * p_evt);
//串口服务初始化结构体
typedef struct
{
ble_nus_data_handler_t data_handler; //处理接收数据的事件句柄
} ble_nus_init_t;
//串口透传服务结构体,包含所需要的信息
struct ble_nus_s
{
uint8_t uuid_type; //UUID类型
uint16_t service_handle; //串口透传服务句柄(由协议栈提供)
ble_gatts_char_handles_t tx_handles; //TX特征句柄
ble_gatts_char_handles_t rx_handles; //RX特征句柄
// blcm_link_ctx_storage_t * const p_link_ctx_storage; /**< Pointer to link context storage with handles of all current connections and its context. */
ble_nus_data_handler_t data_handler; //处理接收数据的事件句柄
};
/**@brief Function for initializing the Nordic UART Service.
*
* @param[out] p_nus Nordic UART Service structure. This structure must be supplied
* by the application. It is initialized by this function and will
* later be used to identify this particular service instance.
* @param[in] p_nus_init Information needed to initialize the service.
*
* @retval NRF_SUCCESS If the service was successfully initialized. Otherwise, an error code is returned.
* @retval NRF_ERROR_NULL If either of the pointers p_nus or p_nus_init is NULL.
*/
uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init);
/**@brief Function for handling the Nordic UART Service's BLE events.
*
* @details The Nordic UART Service expects the application to call this function each time an
* event is received from the SoftDevice. This function processes the event if it
* is relevant and calls the Nordic UART Service event handler of the
* application if necessary.
*
* @param[in] p_ble_evt Event received from the SoftDevice.
* @param[in] p_context Nordic UART Service structure.
*/
void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context);
/**@brief Function for sending a data to the peer.
*
* @details This function sends the input string as an RX characteristic notification to the
* peer.
*
* @param[in] p_nus Pointer to the Nordic UART Service structure.
* @param[in] p_data String to be sent.
* @param[in,out] p_length Pointer Length of the string. Amount of sent bytes.
* @param[in] conn_handle Connection Handle of the destination client.
*
* @retval NRF_SUCCESS If the string was sent successfully. Otherwise, an error code is returned.
*/
uint32_t ble_nus_data_send(ble_nus_t * p_nus,
uint8_t * p_data,
uint16_t * p_length,
uint16_t conn_handle);
#ifdef __cplusplus
}
#endif
#endif // BLE_NUS_H__
/** @} */