跳到主要内容
沁恒微 RISC-V 蓝牙应用常用参数设定与修改 | 极客日志
C
沁恒微 RISC-V 蓝牙应用常用参数设定与修改 沁恒微 RISC-V 蓝牙芯片在实际工程中涉及广播、连接及扫描参数的设定与修改。内容包含开启关闭广播、调整发射功率、修改 MAC 地址、设置广播间隔与内容、定义广播类型;处理连接参数协商、MTU 大小交互、PHY 更新及断开连接;配置主机扫描持续时间、间隔与窗口。文中提供具体 API 函数调用示例,并强调修改部分参数前需遵循关闭广播再配置的流程以确保生效。
灰度发布 发布于 2026/3/27 更新于 2026/4/23 1 浏览一、广播相关
1.1 关闭/开启广播
关闭广播:
uint8_t initial_advertising_enable = FALSE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof (uint8_t ), &initial_advertising_enable);
开启广播:
uint8_t adv_status;
GAPRole_GetParameter(GAPROLE_ADVERT_ENABLED, &adv_status);
uint8_t initial_advertising_enable = TRUE;
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof (uint8_t ), &initial_advertising_enable);
注意!对于与广播参数有关的动态修改,需要先关闭广播 -> 修改配置 -> 再开启广播。
此流程的示例如下:
不能直接在设置完以后的代码处直接开启广播,必须按照上面示例,在协议栈回复了状态以后才能再次开启广播。
1.2 发射功率
初始发射功率:
设置默认发射功率,如下操作(如果不设置,EVT 默认发射功率为 LL_TX_POWER_0_DBM):
动态修改发射功率:
如果要在广播期间修改发射功率使用如下函数(此过程需要关闭广播 - 设置 - 再开启广播):
GAP_SetParamValue(TGAP_ADV_TX_POWER, 0x3B );
连接时候的发射功率修改,后期遇到了再来更新。
1.3 MAC 地址
初始 MAC 地址:
芯片上电默认使用芯片本身的公共地址。
如果想修改上电的 MAC 地址用于测试,需要定义一个宏 BLE_MAC == TRUE,便可以在代码中自己设定自定义地址。
动态修改 MAC 地址:
如果要动态修改 MAC 地址使用如下函数(此过程需要关闭广播 - 设置 - 再开启广播):
bStatus_t GAP_ConfigDeviceAddr (uint8_t addrType, uint8_t *pStaticAddr) ;
uint8_t myAddr[6 ] = {0x00 , , , , , };
GAP_ConfigDeviceAddr(ADDRTYPE_STATIC, myAddr);
0xAA
0xBB
0xCC
0xDD
0x00
1.4 广播间隔 BLE 广播间隔的标准范围是 20 ms ~ 10.24 s,设置范围为 32~16348(以 0.625 ms 单位)。
示例默认为 80:
#define DEFAULT_ADVERTISING_INTERVAL 80
修改方式如下(此过程需要关闭广播 - 设置 - 再开启广播):
uint16_t advInt = 100 ;
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
减少广播间隔时,可以使得建立连接速度更快,但是这样也会使得芯片功耗增大。
1.4.1 一次广播时长说明 一次广播事件,就是在 3 个广播信道(37/38/39)上各发一遍广播包,发完就停,直到下一个广播间隔再发一轮,不是持续发射。
如果有扫描响应,就回广播响应,一次广播事件流程如下:
信道 37:发广播 → 看有没有扫描请求 → 有就回扫描响应
信道 38:发广播 → 看有没有扫描请求 → 有就回扫描响应
信道 39:发广播 → 看有没有扫描请求 → 有就回扫描响应
单次广播事件时长是很短的,一般时间最长可连接广播 + 扫描响应的广播时间估算下来 4ms 左右,甚至更少。剩余的时间就可以用来休眠节约功耗,比如 20ms 广播间隔,剩余的 16ms 就可以休眠。
1.5 广播内容 根据示例有两个数组,表示广播包和广播响应的内容 scanRspData[] 和 advertData[]。
修改方式如下(此过程需要关闭广播 - 设置 - 再开启广播):
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof (scanRspData), scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof (advertData), advertData);
bStatus_t GAP_UpdateAdvertisingData (uint8_t taskID, uint8_t adType, uint16_t dataLen, uint8_t *pAdvertData) ;
1.5.1 修改广播名称 广播名称是属于上面广播内容的一部分的,我们使用上面方式二做个示例说明:
if (events & MY_ChangePower_EVT){
PRINT("Set Set...\r\n" );
GAP_UpdateAdvertisingData(Peripheral_TaskID, FALSE, sizeof (my_change_scanRspData), my_change_scanRspData);
return (events ^ MY_ChangePower_EVT);
}
额外说明,在工程里面涉及到名字的地方有两个,一个就是上面的广播包/扫描响应包中,还有一个是需要存在服务特征值中,链接以后通过特征值读取的。
static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Peripheral" ;
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
虽然这两个地方的名字没有明文规定必须一致,但是强烈建议实际产品中保持一致!!苹果 IOS 中如果不一致,会存在一些问题。
1.6 广播类型 广播类型一般不会在使用中更改,在初始化的时候设置,例程并没有设置,默认广播类型为 GAP_ADTYPE_ADV_IND(可连接、非定向广播),设置其他广播类型,如下:
#define GAP_ADTYPE_ADV_IND 0x00
#define GAP_ADTYPE_ADV_HDC_DIRECT_IND 0x01
#define GAP_ADTYPE_ADV_SCAN_IND 0x02
#define GAP_ADTYPE_ADV_NONCONN_IND 0x03
#define GAP_ADTYPE_ADV_LDC_DIRECT_IND 0x04
uint8_t my_test_adv_type = GAP_ADTYPE_ADV_SCAN_IND;
GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, sizeof (uint8_t ), &my_test_adv_type);
二、连接相关
2.1 连接参数
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 6
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 100
#define DEFAULT_DESIRED_SLAVE_LATENCY 0
#define DEFAULT_DESIRED_CONN_TIMEOUT 100
Supervision Timeout > (1 + Slave Latency) × Connection Interval × 2
超时时间 (ms)>(1+延迟次数)×连接间隔 (ms)×2
uint16_t desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
uint16_t desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof (uint16_t ), &desired_min_interval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof (uint16_t ), &desired_max_interval);
这只是从机端希望的连接间隔,主机会在这个范围内,给一个合适的值(由主机决定),如果这个范围主机给不了,主机也会给从机一个连接间隔,从机不会拒绝。
连接上以后从机还能发起协商请求:
if (events & SBP_PARAM_UPDATE_EVT){
GAPRole_PeripheralConnParamUpdateReq(peripheralConnList.connHandle, DEFAULT_DESIRED_MIN_CONN_INTERVAL, DEFAULT_DESIRED_MAX_CONN_INTERVAL, DEFAULT_DESIRED_SLAVE_LATENCY, DEFAULT_DESIRED_CONN_TIMEOUT, Peripheral_TaskID);
return (events ^ SBP_PARAM_UPDATE_EVT);
}
不管协商几次,主机协商还是从机自己协商,协商的结果会在从机回调函数 peripheralParamUpdateCB 里打印,连接间隔以最后一次协商结果为最终结果。
#define DEFAULT_UPDATE_MIN_CONN_INTERVAL 20
#define DEFAULT_UPDATE_MAX_CONN_INTERVAL 100
#define DEFAULT_UPDATE_SLAVE_LATENCY 0
#define DEFAULT_UPDATE_CONN_TIMEOUT 600
if (events & START_PARAM_UPDATE_EVT){
GAPRole_UpdateLink(centralConnHandle, DEFAULT_UPDATE_MIN_CONN_INTERVAL, DEFAULT_UPDATE_MAX_CONN_INTERVAL, DEFAULT_UPDATE_SLAVE_LATENCY, DEFAULT_UPDATE_CONN_TIMEOUT);
return (events ^ START_PARAM_UPDATE_EVT);
}
2.2 MTU 关于 MTU 交互,一些理论知识请参考官方文档或相关技术手册里面 MTU,BLE_BUFF_MAX_LEN 和单包数据长度小节相关说明。
这里举几个例子,先看看最大的情况:
如果 BLE_BUFF_MAX_LEN = 516 字节
那么:MTU 最大为 512 字节
用户一包数据最大为 509 字节,可以定义一个 509 字节大小的数组用于发送
但是因为空中物理帧限制,一包空中数据最大 251 字节,减去 2 字节 LL header,减去 4 字节 L2CAP header,再减去 3 字节 ATT header,用户数据一帧最大发出 244 字节。
所以这种情况它会分成 3 包:244 B + 244 B + 21 B 发送
BLE_BUFF_MAX_LEN = 251
MTU 最大为 247
用户一包数据最大为 244 字节 (通过特征值或者通知数据交互)
BLE_BUFF_MAX_LEN = 27
MTU 最大为 23
用户一包数据最大为 20
设置 MTU,需要主从机均支持修改 MTU,对于应用来说,就是主机从机的 BLE_BUFF_MAX_LEN 要足够,如果我们想协商 512 的 MTU,那么需要 BLE_BUFF_MAX_LEN 至少为 516。
从机端
首先是宏定义 BLE_BUFF_MAX_LEN:
然后通过手机连接从机,手机端发起 MTU 交互,就能够成功。
主机端
主机端同样的,和从机一样的方式先定义 BLE_BUFF_MAX_LEN。
然后再程序需要设置的地方手动调用如下代码:
attExchangeMTUReq_t req = {
.clientRxMTU = BLE_BUFF_MAX_LEN - 4 ,
};
GATT_ExchangeMTU(centralConnHandle, &req, centralTaskId);
从机主动交互 MTU
如果想要从机主动交互 MTU,我们可以使用如下方式:
先定义 BLE_BUFF_MAX_LEN;
从机初始化的地方 Peripheral_Init 加上 GATT_InitClient();;
和主机示例手动调用 MTU 协商一样的方式。
GAPRole_BroadcasterSetCB(&Broadcaster_BroadcasterCBs);
GATT_InitClient();
tmos_set_event(Peripheral_TaskID, SBP_START_DEVICE_EVT);
if (events & MY_ChangePower_EVT){
if (peripheralConnList.connHandle != GAP_CONNHANDLE_INIT)
{
PRINT("Set Set...\r\n" );
attExchangeMTUReq_t req = {
.clientRxMTU = 512 ,
};
GATT_ExchangeMTU(peripheralConnList.connHandle, &req, Peripheral_TaskID);
}
else {
PRINT("no connected...\r\n" );
}
return (events ^ MY_ChangePower_EVT);
}
2.3 PHY
PRINT("PHY Update %x...\n" , GAPRole_UpdatePHY(peripheralConnList.connHandle, 0 , GAP_PHY_BIT_LE_2M, GAP_PHY_BIT_LE_2M, 0 ));
2.4 断开当前连接 bStatus_t GAPRole_TerminateLink (uint16_t connHandle) ;
上面传入的是句柄,这个在主机从机示例里面可以找到,比如主机端使用的句柄变量是 centralConnHandle,从机使用的句柄变量是 peripheralConnList.connHandle。
三、扫描相关
3.1 扫描时间
#define DEFAULT_SCAN_DURATION 2400
GAP_SetParamValue(TGAP_DISC_SCAN, DEFAULT_SCAN_DURATION);
3.2 扫描间隔
GAP_SetParamValue(TGAP_DISC_SCAN_INT, 64 );
3.3 扫描窗口
GAP_SetParamValue(TGAP_DISC_SCAN_WIND, 32 );
上面 3 个参数是主机扫描的核心参数,举几个组合示例:
TGAP_DISC_SCAN = 0 ;
TGAP_DISC_SCAN_INT = 10 ms;
TGAP_DISC_SCAN_WIND = 10 ms;
TGAP_DISC_SCAN = 5000 ms;
TGAP_DISC_SCAN_INT = 100 ms;
TGAP_DISC_SCAN_WIND = 10 ms;
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online