汇顶ble-long rang添加

一、简介:

BLE的Long Range(长距离)是一种扩展的蓝牙低功耗技术,旨在提供比传统BLE更远的通信距离。传统BLE主要用于短距离无线通信,而BLE Long Range则通过一系列技术改进和优化,使得蓝牙设备能够在更远的距离上保持可靠的连接和数据传输。那靠什么实现更远距离传输呢?

主要就是靠不同编码的方式,以提高信号的传输效率和稳定性。这种调制方式能够更有效地利用无线频谱资源,降低干扰和误码率,从而实现更远的通信距离那是什么样的编码方式呢?

普通的ble原本在1M速率下,ble每一秒钟可以传输1M个bit,每一个实际的bit就是一个信息位,但是在long range中是可以选择的,因为long range的PHY层为coded,也就是编码使用多个实际的bit位去标识一个信息位,举一个例子:

现在以两个bit位标识一个信息位,那么2bit就有四种可能,00,01,10,11,同时可以规定当接收端接受到的数据位为00和10的时候都表示信息位0,接受数据位为01和11的时候都表示数据1,这样就大大提高了容错率,比如实际发送端要发送一个信息位是1,其编码为01发出,但是受到了干扰,导致 数据被接受后解析出来了11(01中的0变为了1),但是因为我们规定了01和11都是标识信息1,所以虽然受到了干扰导致数据出现看错误,但是由于编码的方式不同,接收端还是正确的解析得到了正确的信息是1。大大提高了抗干扰能力。

当然实际编码会更复杂,在coded中一个信息位由几个码元表示(用一个符号s表示),是可以选择的,S=2表示,一个信息位的码元是2bit,S=8表示一个信息位的码元为8bit。因为coded是基于1M速率修改编码方式得来,所以在S=2的时候,实际的信息速率就是1M/2为500K;S=8的时候,实际的信息速率就是1M/8为125K,这也是coded速率为什么是125K和500K的原因。

总结来说,long range以速率换距离。

二、从机代码

  1. 环境

SDK:GR551x_SDK_V2.0.2

例子:GR551x_SDK_V2.0.2\projects\ble\ble_peripheral\ble_app_uart

2、代码添加

打开工程后再user_app.c中进行修改:

找到gap_params_init函数对广播进行配置,需要配置广播为拓展广播,然后设置PHY为coded,并且设置广播时候的TX功率:

完整修改代码截图如下:

s_adv_data_set中应该设置包含广播名字,作为拓展广播包的数据,可以让主机读取到并进行过滤:

代码如下:

static const uint8_t s_adv_data_set[] =                 /**< Advertising data. */

{

    0x11, // Length of this data

    BLE_GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID,

    GUS_SERVICE_UUID,

0x0e, // Length of this data

    BLE_GAP_AD_TYPE_COMPLETE_NAME,

    'G', 'o', 'o', 'd', 'i', 'x', '_', 'U', 'A', 'R', 'T','_', 'p',

};

static void gap_params_init(void)
{
    sdk_err_t   error_code;
    error_code = ble_gap_device_name_set(BLE_GAP_WRITE_PERM_DISABLE, (uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME));

	#if  coded_test
		ble_gap_ext_adv_param_t m_code_test;
		
		memset(&m_code_test,0,sizeof(m_code_test));
	
		ble_gap_pair_enable(false);
		m_code_test.type  								= BLE_GAP_ADV_TYPE_EXTENDED;
		m_code_test.disc_mode							= BLE_GAP_DISC_MODE_GEN_DISCOVERABLE;
		m_code_test.prop									= BLE_GAP_ADV_PROP_CONNECTABLE_BIT;
		m_code_test.max_tx_pwr   					= 15; //广播功率设置
		m_code_test.filter_pol 						= BLE_GAP_ADV_ALLOW_SCAN_ANY_CON_ANY;
	
		memset(&m_code_test.peer_addr, 0, sizeof(ble_gap_bdaddr_t));
		m_code_test.prim_cfg.adv_intv_max = 64;
		m_code_test.prim_cfg.adv_intv_min =	64;
		m_code_test.prim_cfg.chnl_map			= BLE_GAP_ADV_CHANNEL_37_38_39;
		m_code_test.prim_cfg.phy					= BLE_GAP_PHY_CODED_VALUE;
		m_code_test.second_cfg.max_skip   = 0;
		m_code_test.second_cfg.phy				= BLE_GAP_PHY_CODED_VALUE;
		m_code_test.second_cfg.adv_sid		= 0x00;
		m_code_test.period_cfg.adv_intv_min = 0;
    m_code_test.period_cfg.adv_intv_max = 0;
	
		error_code = ble_gap_ext_adv_param_set(0,BLE_GAP_OWN_ADDR_STATIC,&m_code_test);
		APP_ERROR_CHECK(error_code);
	#endif
		/*拓展包数据设置*/
    error_code = ble_gap_adv_data_set(0, BLE_GAP_ADV_DATA_TYPE_DATA, s_adv_data_set, sizeof(s_adv_data_set));
    APP_ERROR_CHECK(error_code);
    s_gap_adv_time_param.duration    = 0;
    s_gap_adv_time_param.max_adv_evt = 0;

}

然后因为我们为了最求最远的距离,所以设置了TX功率为15dBm,这是基于GR5332的硬件来确定的(RF电路需要使用15dBm的设计),为了使GR5332支持15dBm,软件也需要修改一个宏来启用:

把宏#define RF_TX_PA_SELECT的值设置为3

然后在ble_evt_handler事件回调中改或者添加如下几个事件(没有的就加入)

  1. 在开始事件BLE_GAPM_EVT_ADV_START中确定广播功率是不是初始化时设置的15dBm
if (p_evt->evt_status)
 {
                APP_LOG_DEBUG("Adverting started failed(0X%02X).", p_evt->evt_status);
            }else{
							uint8_t index=p_evt->evt.gapc_evt.index;
							int8_t  txpwr_dbm=0;
							error_code = ble_gap_tx_power_get(BLE_GAP_ACTIVITY_ROLE_ADV,index,&txpwr_dbm);
							APP_ERROR_CHECK(error_code);
							APP_LOG_DEBUG("广播功率:%d  |  %d dBm",index,txpwr_dbm);
							APP_LOG_DEBUG("广播开始");	
}
  1. 在连接事件BLE_GAPC_EVT_CONNECTED中设置连接的TX功耗,确定在连接后RF依然使用15dBm进行数据发送

2、设置更新coded的S为8

{
							uint8_t index = p_evt->evt.gapc_evt.index;
							int8_t  txpwr_dbm = 15;
							int8_t 	txpwr_dbm_reg=0;
							
							error_code = ble_gap_tx_power_get(BLE_GAP_ACTIVITY_ROLE_CON,index,&txpwr_dbm_reg);
							APP_ERROR_CHECK(error_code);
							APP_LOG_INFO("连接功率:index:%d | %d dBm",index,txpwr_dbm_reg);
							if(txpwr_dbm_reg != 15)
							{
								APP_LOG_INFO("设置连接功率为15dBm");
								error_code = ble_gap_tx_power_set(BLE_GAP_ACTIVITY_ROLE_CON,index,txpwr_dbm);
								APP_ERROR_CHECK(error_code);
								
							}
							app_connected_handler(&(p_evt->evt.gapc_evt.params.connected));
							
							break;
						}
static bool phy_set_flag = true;

case BLE_GAPC_EVT_PHY_UPDATED:
						APP_LOG_INFO("PHY 更新完成\n");

						break;
case BLE_GAPC_EVT_CONN_PARAM_UPDATED:
							APP_LOG_INFO("连接参数更新\n");
							if(phy_set_flag)
							{
								if(ble_gap_phy_update(0,BLE_GAP_PHY_CODED_S8,BLE_GAP_PHY_CODED_S8,BLE_GAP_PHY_OPT_S8_CODING) == SDK_SUCCESS)
								{
									APP_LOG_INFO("PHY 设置成功");
									phy_set_flag =false;
								}
							}
							
						break;

至此从机代码修改完毕。

三、主机代码

主机的代码相对复杂,需要实现启动拓展扫描,扫描的PHY为coded,同时对拓展包的过滤,便于找到正确的从机设备(过滤可选方式为名字,UUID,MAC地址),在找到正确的设备后需要使用拓展连接方式去连接从机。

1、环境

SDK:GR551x_SDK_V2.0.2

例子:GR551x_SDK_V2.0.2\projects\ble\ble_central\ble_app_uart_c

2、代码添加

首先修改TX的功率,让其可以支持15dBm,依然是在custom_config中进行修改

在user_app中的参数初始化中,修改gap_params_init中的ble_gap_pref_phy_set函数参数为BLE_GAP_PHY_LE_CODED:

然后重新编写扫描开始函数,让扫描的包为拓展包,并且PHY为coded,本次选择名字过滤,

void ext_connect_start(void)
{
    sdk_err_t            error_code;
		ble_gap_ext_init_param_t ext_conn_param;
		ble_scanner_init_t        scan_init;
    ble_scanner_filter_data_t filter_data;
		ble_gap_ext_scan_param_t s_scan_param;
    memset(&scan_init, 0x00, sizeof(ble_scanner_init_t));
    memset(&filter_data, 0x00, sizeof(ble_scanner_filter_data_t));

		/*扫描初始化*/
    scan_init.connect_auto              = true;
    scan_init.err_handler               = NULL;
    scan_init.evt_handler               = ble_scanner_evt_handler;
		error_code = ble_scanner_init(&scan_init);
    APP_ERROR_CHECK(error_code);
	
		/*拓展包扫描初始化*/
    s_scan_param.type = BLE_GAP_EXT_SCAN_TYPE_OBSERVER;
    s_scan_param.prop = BLE_GAP_EXT_SCAN_PROP_PHY_CODED_BIT | BLE_GAP_EXT_SCAN_PROP_FILT_TRUNC_BIT ;
    s_scan_param.dup_filt_pol = BLE_GAP_EXT_DUP_FILT_DIS;
		s_scan_param.scan_param_coded.scan_intv = APP_SCAN_INTERVAL;
		s_scan_param.scan_param_coded.scan_wd =APP_SCAN_WINDOW;
    s_scan_param.duration= 0;
    s_scan_param.period= 0;

    error_code = ble_gap_ext_scan_param_set(BLE_GAP_OWN_ADDR_STATIC, &s_scan_param);
    APP_ERROR_CHECK(error_code);
	
		/*过滤初始化*/
//	filter_data.svr_uuid.length         = UART_UUID_LEN;
//  filter_data.svr_uuid.p_data         = s_target_uuid;
    filter_data.dev_name.length         = strlen(s_target_name);
    filter_data.dev_name.p_data         = (uint8_t *)s_target_name;
//    filter_data.target_addr.addr_type   = BLE_GAP_ADDR_TYPE_PUBLIC;
//    memcpy(filter_data.target_addr.gap_addr.addr, s_target_addr, SYS_BD_ADDR_LEN);

    ble_scanner_filter_set(BLE_SCANNER_NAME_FILTER, &filter_data);
    ble_scanner_filter_enable(BLE_SCANNER_FILTER_ALL_MATCH);
		    
    error_code = ble_gap_scan_start();
    APP_ERROR_CHECK(error_code);
}

因为设置了名字过滤,所以s_target_name需要填写从机拓展广播包的中的名字,否则无法正确连接,因为名字不正确的话,会被过滤掉。本次测试,名字设置如下。

static const char     s_target_name[] = "Goodix_UART_p";  

同时在ble_evt_handler回调中的BLE_GAPM_EVT_SCAN_START事件中修改TX的功率为15dBm,

case BLE_GAPM_EVT_SCAN_START:
            if (BLE_SUCCESS != p_evt->evt_status)
            {
                APP_LOG_DEBUG("Scan started failed(0X%02X).", p_evt->evt_status);
            }else
						{
							uint8_t index = p_evt->evt.gapm_evt.index;
							int8_t  txpwr_dbm;
							ble_gap_tx_power_get(BLE_GAP_ACTIVITY_ROLE_SCAN_INIT,index,&txpwr_dbm);
							APP_LOG_INFO("扫描开始,功率设置为:%d dBm ( index:%d )\n",txpwr_dbm,index);
						}
            break;

经过上面的设置,已经可以按照名字过滤拓展广播包了,那接下来就是连接了,在ble_scanner.c的on_scanner_adv_report函数中需要记录已经经过过滤的对端从机设备的MAC地址

变量为ble_gap_bdaddr_t类型:

static ble_gap_bdaddr_t m_conn_addr={0};

然后需要在on_scanner_stoped函数中修改连接为拓展包链接,原来为普通广播连接:

修改的连接函数ext_conning需要我们自定义,代码如下:

#define APP_CONNECTION_MIN_INTERVAL          6       /**< The connection min interval (in units of 1.25 ms. This value corresponds to 7.5 ms). */
#define APP_CONNECTION_MAX_INTERVAL          10      /**< The connection max interval (in units of 1.25 ms. This value corresponds to 12.5 ms). */
#define APP_CONNECTION_SLAVE_LATENCY         1       /**< Slave latency. */
#define APP_CONNECTION_MAX_TIMEOUT           100     /**< Link supervision timeout (in unit of 10ms. This value corresponds to 1000 ms). */

uint16_t ext_conning(void)
{
		APP_LOG_INFO("2--ext_conn_event");
		uint16_t error_code;
		ble_gap_ext_init_param_t ext_conn_param;
		
    memset(&ext_conn_param, 0 , sizeof(ext_conn_param));
    ext_conn_param.type                         = BLE_GAP_INIT_TYPE_DIRECT_CONN_EST;
    ext_conn_param.prop                         = BLE_GAP_INIT_PROP_CODED_BIT;
    ext_conn_param.conn_to                      = 0;
    ext_conn_param.scan_param_coded.scan_intv      = 15;
    ext_conn_param.scan_param_coded.scan_wd        = 15;
    ext_conn_param.conn_param_coded.conn_intv_min  = APP_CONNECTION_MIN_INTERVAL;
    ext_conn_param.conn_param_coded.conn_intv_max  = APP_CONNECTION_MAX_INTERVAL;
    ext_conn_param.conn_param_coded.conn_latency   = APP_CONNECTION_SLAVE_LATENCY;
    ext_conn_param.conn_param_coded.supervision_to = APP_CONNECTION_MAX_TIMEOUT;
    ext_conn_param.conn_param_coded.ce_len         = 0;
    ext_conn_param.peer_addr.addr_type          = m_conn_addr.addr_type;
		APP_LOG_INFO("即将连接的拓展广播MAC地址 %02X:%02X:%02X:%02X:%02X:%02X.",
                 ext_conn_param.peer_addr.gap_addr.addr[5],
                 ext_conn_param.peer_addr.gap_addr.addr[4],
                 ext_conn_param.peer_addr.gap_addr.addr[3],
                 ext_conn_param.peer_addr.gap_addr.addr[2],
                 ext_conn_param.peer_addr.gap_addr.addr[1],
                 ext_conn_param.peer_addr.gap_addr.addr[0]);
		
    memcpy(&ext_conn_param.peer_addr.gap_addr.addr,&m_conn_addr.gap_addr, 6);
		
		APP_LOG_INFO("MAC地址 %02X:%02X:%02X:%02X:%02X:%02X.",
                 ext_conn_param.peer_addr.gap_addr.addr[5],
                 ext_conn_param.peer_addr.gap_addr.addr[4],
                 ext_conn_param.peer_addr.gap_addr.addr[3],
                 ext_conn_param.peer_addr.gap_addr.addr[2],
                 ext_conn_param.peer_addr.gap_addr.addr[1],
                 ext_conn_param.peer_addr.gap_addr.addr[0]);
    error_code = ble_gap_ext_connect(BLE_GAP_OWN_ADDR_STATIC, &ext_conn_param);
    return error_code;
}

因为在ble_scanner.c中加入了打印,所以要加入头文件#include "app_log.h",如果不需要打印,可以不加入,代码截图如下:

至此我们已经完成扫描过滤和连接了,但是还需要确定连接后的TX功率为15dBm,需要再ble_evt_handler函数的连接回调事件中进行设置:

case BLE_GAPC_EVT_CONNECTED:
            if (BLE_SUCCESS == p_evt->evt_status)
            {
								uint16_t error_code;
								uint8_t index = p_evt->evt.gapm_evt.index;
								int8_t  txpwr_dbm;
								ble_gap_tx_power_get(BLE_GAP_ACTIVITY_ROLE_CON,index,&txpwr_dbm);
								APP_LOG_DEBUG("连接功率:%d dBm ( index:%d )",index,txpwr_dbm);
								if(txpwr_dbm != 15)
								{
									int8_t  txpwr_dbm_val = 15;
									APP_LOG_INFO("设置连接功率为15dBm");
									error_code = ble_gap_tx_power_set(BLE_GAP_ACTIVITY_ROLE_CON,index,txpwr_dbm_val);
									APP_ERROR_CHECK(error_code);
								}
                APP_LOG_DEBUG("Connected.");
            }
            break; 

至此从机代码添加完毕。

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值