Nordic芯片如何达到最快的蓝牙传输速率

本文介绍使用Nordic芯片时,在1主对1从情况下,如何配置以达到蓝牙最快传输速度。阐述了相关基础概念,给出Nordic官方协议栈理论速度,还分别对nRF51和nRF52系列进行代码实例测试,通过配置参数可接近理论极限传输速率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

目前BLE已经发布到BLE5.2的标准,而蓝牙的传输速率,在BLE4.2和BLE5.0版本上分别进行了提升,这里介绍下使用Noridc芯片时,如何进行配置,以达到最快的传输速度(只讨论1主对1从的情况)。

基础概念介绍

这里对一些后面用到的名词做一下简单介绍,如果要详细了解,可以自行进行查找。

在BLE中,作为Client端,可以通过write commandwrite request方式进行发送数据,参考蓝牙规范Vol3.Part F.3.4.5章节。
write command : client向server发送命令,不需要server给应答。
write request : clien向server发送请求,需要server给出ack。

作为server端,可以通过Notificationindication方式发送数据给client端,参考蓝牙规范Vol3.Part F.3.4.7章节。
Notification:server向client发送通知,不需要client应答。
Indication : server向client发送通知,需要client应答。

ATT_MTU : MAXIMUM TRANSMISSION UNIT,即在一个传输单元中的最大有效数据传输量,mtu的格式为1字节op_code,2字节attr handle,因此实际一帧传输的用户数据为ATT_MTU-3。在BLE4.0中,只支持23的ATT_MTU,在BLE4.2以后,ATT_MTU最大可以是247字节。

DLE: dat length extension,一般建议设置为ATT_MTU+4,如果低于ATT_MTU,ATT data会被分包,这里记得就行,后面会单独开一个章节介绍一下。

CLE :connection event length extension,链接事件长度扩展,在BLE4.0中,单个连接间隔,最多只能发送4(IOS)或者6(Android)个数据包,当打开CLE功能时,协议栈会判断链接间隔剩下的时间是否还支持发送数据包,如果还有时间,那么会继续进行数据发送,而不是受限于6个包。

connection interval :链接间隔,主从机建立连接以后,每隔多久交互一次数据,IOS要求连接间隔最小时15ms,最大最小之间的时间差值最低15ms,因此IOS支持的最快连接间隔最小最大分别是15ms-30ms,安卓端最低7.5ms。

官方理论值

Nordic官方公布的协议栈理论速度如下,这里只讨论最快速度,所以只看没有ack的NotificationIndication方式参考协议栈手册BLE data throughput章节:

nRF51

nRF51不支持ATT_MTU扩展,也不支持DLECLELE 2M PHY,因此,使用最快的7.5ms的连接间隔,23字节的ATT_MTU,BW Config配置为HIGH时,Notificationwrite command方式速率为149.2kbpsIndicationwrite request方式速率为10.6kbps
在这里插入图片描述

nRF52

nRF52系列支持上面所有的特性。
ATT_MTU=23,其他特性都不打开的情况下,也就是BLE4.0的标准特性下,传输速率如下图所示:

对比上面的51系列,可以看到,同样的LE 1M PHY条件下,52的速率为192kbps,速度提高了53kbps左右,而LE 2M PHY情况下,速率为256kbps。

ATT_MTU=158,其他特性都不打开的情况下,传输速率如下图所示:
在这里插入图片描述

可以看到,在2M PHY的情况下,速率为330kbps。

ATT_MTU = 247,DLE=251,CLE = conn interval情况下,传输速率如下:
在这里插入图片描述

在打开CLE的情况下,传输速率最快达到1376kbps这个就是目前我们所能达到的最快的速率

可以看到,影响蓝牙传输速率的因素有:

  • 连接间隔
  • ATT_MTU SIZE
  • DLE
  • LE PHY
  • CLE

代码实例测试

以下代码测试均以Nordic SDK中的ble_app_uart为基础,手机端使用安卓一加6进行测试,手机支持上面提到的所有特性。:

nRF51

目前nordic支持51的最后一个版本sdk为SDK12.3,以该版本sdk为例进行测试,开发环境为keil。
由于nRF51在传输速率方面只支持BLE4.0,所以我们需要配置的参数只有连接间隔BW Config选项。

对于链接间隔,理论上是越小越好,但是IOS要求最低是15ms-30ms,因此,使用这个范围,可以达到最快的传输速度,但是考虑到手机兼容性,可以适当的将这个最大值调高一点。

还有就是协议栈初始化时,配置BW Config为high。

ble_common_opt_conn_bw_t opt_conn_bw;
opt_conn_bw.role = role; 
opt_conn_bw.conn_bw.conn_bw_tx = BLE_CONN_BW_HIGH;
opt_conn_bw.conn_bw.conn_bw_rx = BLE_CONN_BW_HIGH;
return sd_ble_opt_set(BLE_COMMON_OPT_CONN_BW, (ble_opt_t const *)&opt_conn_bw); 

role的角色定义如下,根据自己需要配置。

/**@defgroup BLE_GAP_ROLES GAP Roles
 * @note Not explicitly used in peripheral API, but will be relevant for central API.
 * @{ */
#define BLE_GAP_ROLE_INVALID     0x0            /**< Invalid Role. */
#define BLE_GAP_ROLE_PERIPH      0x1            /**< Peripheral Role. */
#define BLE_GAP_ROLE_CENTRAL     0x2            /**< Central Role. */

51的配置部分比较少,需要注意的是,在发送数据的时候,只要api的返回值不是
NRF_ERROR_RESOURCES或者在更早的sdk中,应该是NRF_ERROR_NO_TX_BUFFER,就连续调用发送的api进行发送数据。
如果发生了上面的error,那么就等触发一个tx_complete事件,再继续发送。

nRF52系列

github测试demo:https://github.com/faithlm/ble_app_uart_throughout_test

目前最新版本SDK为sdk17.02,以该版本sdk进行测试,以该版本sdk为例进行测试,开发环境为ses。
从上面协议栈参数配置可知,如果要达到最快的速率,需要配置如下参数:

增大ATT_MTU

目前协议栈支持的最大 att_mtu 为247,如果要修改,可以更改sdk_config中的如下选项:

// <o> NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. 
#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE
#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247
#endif
增大DLE

目前版本协议栈支持最大的DLE为 251,可以通过sdk_config.h 的如下选项进行配置:

// <i> Requested BLE GAP data length to be negotiated.
#ifndef NRF_SDH_BLE_GAP_DATA_LENGTH
#define NRF_SDH_BLE_GAP_DATA_LENGTH 251
#endif
打开CLE

连接事件长度扩展,可以通过下面接口进行配置,配置放在协议栈初始化后面:

//status 为true时,打开CLE
void conn_evt_len_ext_set(bool status)
{
    ret_code_t err_code;
    ble_opt_t  opt;

    memset(&opt, 0x00, sizeof(opt));
    opt.common_opt.conn_evt_ext.enable = status ? 1 : 0;

    err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
    APP_ERROR_CHECK(err_code);
}

这里还有一个参数需要注意,NRF_SDH_BLE_GAP_EVENT_LENGTH,这个定义了连接事件的长度,单位是1.25ms,在sdk_config.h中配置,一般情况下,这个值可以等于连接间隔

// <o> NRF_SDH_BLE_GAP_EVENT_LENGTH - GAP event length. 
// <i> The time set aside for this connection on every connection interval in 1.25 ms units.
#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH
#define NRF_SDH_BLE_GAP_EVENT_LENGTH 400
#endif
使用LE 2M PHY:

目前支持3中LE PHY,分别是LE 1M PHYLE 2M PHYLE CODED PHY,其中LE 2M PHY用于高速率,,而理论距离是LE 1M PHY的一半,而LE CODED PHY用于长距离模式,LE 1M PHY兼顾了距离和速率,可以根据自己实际需要进行选择,如果对传输距离有要求,需要谨慎选择。
LE PHY 可以通过调用sd_ble_gap_phy_update(uint16_t conn_handle, ble_gap_phys_t const *p_gap_phys)接口发起更新,一般在peripheral端,收到ble_evt_connected事件的时候进行请求更新。如下所示,即可配置为只支持2M 的PHY:

static test_params_t m_test_params =
{
    .phys.tx_phys             = BLE_GAP_PHY_2MBPS,
    .phys.rx_phys             = BLE_GAP_PHY_2MBPS,
};
static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
{
    uint32_t              err_code;
    ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
            //这里只写phy更新部分,其他的省略
             err_code = sd_ble_gap_phy_update(p_gap_evt->conn_handle, &m_test_params.phys);
             APP_ERROR_CHECK(err_code);
            break;
    }
 }
调整连接间隔

由于启用了CLE功能,所以这里不需要根据nRF51的方式,使用最小的连接间隔,调整一个比较大的就可以,注意,需要保持NRF_SDH_BLE_GAP_EVENT_LENGTH大于等于连接间隔,协议栈给出的参考值是50ms或者400ms,对应的速率分别是1328kbps和1376kbps。

#define CONN_INTERVAL_MIN               (uint16_t)(MSEC_TO_UNITS(50, UNIT_1_25_MS))    /**< Minimum acceptable connection interval, in units of 1.25 ms. */
#define CONN_INTERVAL_MAX               (uint16_t)(MSEC_TO_UNITS(60, UNIT_1_25_MS))    /**< Maximum acceptable connection interval, in units of 1.25 ms. */

增大协议栈发送buff

在ram空间有剩余的情况下,可以给协议栈配置更大的queue大小,增大缓存,默认值是1,根据实际情况配置。
下面的给协议栈配置了长度为7的队列缓冲区。

memset(&ble_cfg, 0, sizeof(ble_cfg));
ble_cfg.conn_cfg.conn_cfg_tag = APP_BLE_CONN_CFG_TAG;
ble_cfg.conn_cfg.params.gattc_conn_cfg.write_cmd_tx_queue_size = 7;
ble_cfg.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = 7;
err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTC, &ble_cfg, ram_start);

注意,经过上面的修改以后,在协议栈初始化时,会报NO_MEM的错误,,如下图所示,这个时候log会提示需要将ram修改为多大,根据需要进行调整即可:
在这里插入图片描述

经过上面修改,即可达到最大的传输速率,理论值是1376.2 kbps

github上的demo,增加了数据发送及时间记录,可以进行验证,测试结果如下图,8s时间,发送1220*1000 Byte数据,相当于传输速率为1220kbps,已经接近理论极限值。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值