[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 NUS 透传数据队列发送,提升带宽利用率

编程入门 行业动态 更新时间:2024-10-27 16:25:30

[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 NUS 透传数据<a href=https://www.elefans.com/category/jswz/34/1771257.html style=队列发送,提升带宽利用率"/>

[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 NUS 透传数据队列发送,提升带宽利用率

接上一篇
[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 集合(OTA、透传、电量、设备信息、HID)
[单片机框架] [queue] 实现一个简易的消息队列

文章目录

  • 一、 透传服务,加入队列机制
  • 问题1:为什么会使用消息队列?
  • 问题2:消息队列的优缺点?
  • 问题3:如何增强消息队列使用的稳定性?
  • 二、示例程序

一、 透传服务,加入队列机制

问题1:为什么会使用消息队列?

  1. 由于业务划分有用户层,中间层和系统层。要保证用户层的多个用户对中间层的不同模块之间的访问,以及多个中间层的模块要访问系统层的不同模块,选择client-server模型来满足设计需求。
  2. 要完成client-server之间的通信有多种途径,选择消息队列一方面是为了将系统的耦合性降低,
  3. 另一方面是为了保持模块异步运行,减少阻塞。

问题2:消息队列的优缺点?

  1. 消息队列出问题将会引起整个系统紊乱,因为在client-server模型中通信都是采用的消息队列,所以要是消息队列出问题就会引起整个系统的紊乱。

  2. 消息有可能会丢失,重复使用等问题

问题3:如何增强消息队列使用的稳定性?

  1. 为了防止消息重复使用,一方面不同client有各自的标志,防止特定的消息被其它模块使用;
  2. 另一方面消息在接收完成之后将会被删除。对消息队列的消息长度要多适当调整,避免有些消息过长而被丢弃。
  3. 至于消息队列本身的问题,需要从系统层面去多分析和优化。

二、示例程序

/********************************************************************************
* @file    biz_ble_nus.c
* @author  jianqiang.xue
* @Version V1.0.0
* @Date    2022-03-16
* @brief   [业务] ble数据透传服务(从机)
********************************************************************************/
/* Private Includes ----------------------------------------------------------*/
#include "queue.h"#include "business_function.h"
#include "log.h"
#include "biz_ble_cfg.h"
#include "biz_ble.h"
#include "biz_ble_nus.h"
/* Private Define ------------------------------------------------------------*/
/* External Variables --------------------------------------------------------*/
/* Private Macro -------------------------------------------------------------*/
/* Private Variables ---------------------------------------------------------*/
#if BLE_NUS_ENABLED
ble_nus_t m_nus; /**< Structure to identify the Nordic UART Service. */
typedef void(*ble_rx_event_callback)(uint8_t *data, uint16_t len);
static ble_rx_event_callback g_rx_dispose_callback;/***************消息队列定义**************/// 用于BLE数据发送消息队列总缓存区
static uint8_t m_ble_q_buff[BLE_BUFF_Q_ITEM_CNT * BLE_BUFF_Q_ITEM_SIZE] = {0};
queue_t m_ble_buff_q =
{.pbuff     = m_ble_q_buff,.front     = 0,.rear      = 0,.item_cnt  = BLE_BUFF_Q_ITEM_CNT,.item_size = BLE_BUFF_Q_ITEM_SIZE
};
uint8_t g_ble_single_buff_data[BLE_BUFF_Q_ITEM_SIZE]    = {0}; // 用于单个BLE数据临时缓存区// 如果发送失败,则组合上次数据一并发送。最大程度利用带宽,使数据正常发送。
uint8_t ble_send_buff[BLE_BUFF_SEND_MAX_SIZE] = {0};  // 用于组合多个BLE数据// 记录当前发送长度
uint16_t ble_send_len = 0;
#endif
/* Private Function Prototypes -----------------------------------------------*/
#if BLE_NUS_ENABLED
/*** @brief  [透传数据服务][接收事件] 接收数据事件  [处理通过BLE接收的数据]* @param  p_nus: 透传服务结构体,包含一些回调函数。(本接收事件,没有使用)* @param  p_data: 数据包指针头* @param  length: 数据长度*/
static void nus_data_handler(ble_nus_t * p_nus, uint8_t *p_data, uint16_t length)
{LOG_D("<DEBUG> RX:%02x %02x %02x %02x %02x|%d\r\n", p_data[0], p_data[1], p_data[2], p_data[3], p_data[4], length);// 将数据传给外部[业务层]处理if (g_rx_dispose_callback){g_rx_dispose_callback(p_data, length);}
}
#endif/* Public Function Prototypes ------------------------------------------------*/
#if BLE_NUS_ENABLEDvoid biz_ble_nus_init(void)
{uint32_t err_code;/**** NUS 串口透传服务 ****/ble_nus_init_t nus_init;memset(&nus_init, 0, sizeof(nus_init));nus_init.data_handler = nus_data_handler;err_code = ble_nus_init(&m_nus, &nus_init);LOG_D("<DEBUG> NUS INIT:%x\r\n", err_code);APP_ERROR_CHECK(err_code);queue_init(&m_ble_buff_q, m_ble_q_buff, BLE_BUFF_Q_ITEM_CNT, BLE_BUFF_Q_ITEM_SIZE);memset(m_ble_q_buff, 0, BLE_BUFF_Q_ITEM_CNT * BLE_BUFF_Q_ITEM_SIZE);memset(g_ble_single_buff_data, 0, BLE_BUFF_Q_ITEM_SIZE);
}/*** @brief  [串口透传服务] 注册接收回调* @param  *event: 格式 -- func(uint8_t *data, uint16_t len);* @retval false--失败  true--成功*/
bool biz_ble_nus_rx_reg_callback(void *event)
{if (g_rx_dispose_callback != NULL){return false;}else{g_rx_dispose_callback = (ble_rx_event_callback)event;}return true;
}/*** @brief  [数据透传] 将队列数据依次发送 (本函数建议放在空闲函数使用)* @retval 0--成功 1--失败*/
bool ble_data_send_dispose(void)
{static bool old_send_fail = false;static uint8_t msg_mem_num = 0;if (!old_send_fail){msg_mem_num = queue_get_space(&m_ble_buff_q);if (msg_mem_num != 0){ble_send_len = 0;// 将队列数据,取出进行组合。msg_mem_num = msg_mem_num > (BLE_NUS_MAX_DATA_LEN / BLE_BUFF_Q_ITEM_SIZE) ? (BLE_NUS_MAX_DATA_LEN / BLE_BUFF_Q_ITEM_SIZE) : msg_mem_num;for (uint8_t i = 0; i < msg_mem_num; i++){if (!queue_de(&m_ble_buff_q, g_ble_single_buff_data)){break;}memcpy(ble_send_buff + ble_send_len, g_ble_single_buff_data, m_ble_buff_q.item_size);ble_send_len += m_ble_buff_q.item_size;}}}if (ble_send_len > 0){if (get_ble_conn_state()){ret_code_t ble_send_err_code;
#if NRF51ble_send_err_code = ble_nus_string_send(&m_nus, ble_send_buff, ble_send_len);
#elif NRF52ble_send_err_code = ble_nus_data_send(&m_nus, ble_send_buff, &ble_send_len, m_conn_handle);
#endifif (ble_send_err_code == NRF_SUCCESS){old_send_fail = false;ble_send_len = 0;}else{old_send_fail = true;}return true;}else{// 蓝牙断开,则清除所有队列数据queue_init(&m_ble_buff_q, m_ble_q_buff, BLE_BUFF_Q_ITEM_CNT, BLE_BUFF_Q_ITEM_SIZE);old_send_fail = false;ble_send_len = 0;return false;}}else{return false;}}/*** @brief  [数据透传] 发送数据 (非实时,数据入队列)* @param  *data: 数据头指针* @param  len: 数据长度* @retval 0--成功 1--失败*/
bool biz_ble_data_send(uint8_t *data, uint8_t len)
{if (get_ble_conn_state()){if (len > BLE_NUS_MAX_DATA_LEN){LOG_E("<ERR> [biz_ble_data_send] Len > 20 , Fail\r\n");}if (queue_is_null(&m_ble_buff_q)){ret_code_t ble_send_err_code;
#if NRF51ble_send_err_code = ble_nus_string_send(&m_nus, data, len);
#elif NRF52ble_send_err_code = ble_nus_data_send(&m_nus, data, &len, m_conn_handle);
#endifif (ble_send_err_code == NRF_SUCCESS){return true;}}if (m_conn_handle == BLE_CONN_HANDLE_INVALID){return false;}if (!queue_en(&m_ble_buff_q, data, len)){LOG_D("<DEBUG> [biz_ble_data_send] queue_en fail\r\n");return false;}}return true;
}
#else
void biz_ble_nus_init(void)
{
}
bool biz_ble_nus_rx_reg_callback(void *event)
{return false;
}
bool ble_data_send_dispose(void)
{return false;
}
bool biz_ble_data_send(uint8_t *data, uint8_t len)
{return false;
}
#endif
/********************************************************************************
* @file    biz_ble_nus.h
* @author  jianqiang.xue
* @Version V1.0.0
* @Date    2022-03-16
* @brief   [业务] ble数据透传服务(从机)
********************************************************************************/
#ifndef __BIZ_BLE_NUS_H
#define __BIZ_BLE_NUS_H/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>#include "biz_ble_cfg.h"
#include "ble_nus.h"
/* Define --------------------------------------------------------------------*/
/* External Variables --------------------------------------------------------*/
#if BLE_NUS_ENABLED
extern ble_nus_t m_nus;
#endif
/* Public Function Prototypes ------------------------------------------------*/
void biz_ble_nus_init(void);bool biz_ble_data_send(uint8_t *data, uint8_t len);
bool ble_data_send_dispose(void);bool biz_ble_nus_rx_reg_callback(void *event);
#endif

更多推荐

[嵌入式框架][nrf51822][SDK12.3] BLE分层设计 NUS 透传数据队列发送,提升带宽利用率

本文发布于:2023-06-14 23:47:25,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/716226.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:队列   利用率   嵌入式   框架   带宽

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!