问题背景:有客户反馈6626做主机扫描连接蓝牙从机比较慢。 原理分析:蓝牙主机连接蓝牙从机的逻辑是这样的:主机先扫描周围的广播,发现目标设备后,可以去发扫描请求获取更多的扫描响应信息。也可以直接去发起连接。所以我们要连接一个蓝牙从机要考虑是什么样的应用方式。比如是通过广播字段去扫描连接,还是扫描响应字段去扫描连接,亦或是通过蓝牙地址直接进行直连操作。当然无论通过哪种方式,都离不开扫描这个阶段,因为蓝牙通信是有严格的通信时序要求的,比如主机扫描到从机设备后必须要在150us±2时刻发扫描请求或者连接请求。并不是说主机下发连接请求后,立马就下发空中给从机的。 所以,要想提高连接效率,就得提高扫描效率。提高扫描效率一般是把扫描窗口和扫描间隔设置成一样,这样的话,就相当于是全扫描。有一个注意事项,如果你是通过扫描响应字段来进行连接的,这个建议把这部分数据放在广播字段内。因为考虑到扫描效率,底层并不会对每个可扫描的广播都进行发起扫描请求。如果对端是1M,那么扫描的时候我们可以设置只扫描1M的设备。如果是通过扫描广播字段来连接的话,那么主机扫描的时候,可以关闭扫描响应请求。这样又进一步提高扫描效率。最后一个注意事项是频偏的影响。 解决方案
代码配置如下: // 1M扫描参数配置 static ob_scanning_param_t param_scan_1m = { .scan_type = false, // 关闭扫描响应包的请求, 要是需要获取扫描响应包,这里需要写true .interval = 0x40, // 扫描间隔 .window = 0x40, // 扫描窗口 }; // 1M扫描参数配置 ob_scan_param_t scan_param = { OB_ADV_ADDR_TYPE_PUBLIC, // 扫描地址类型 OB_SCAN_FILTER_BASIC_UNFILTER, // 是否滤波,这个只有白名单的时候才会考虑 timeout * 100, // 扫描超时时间 ¶m_scan_1m, // 扫描1M时的扫描参数配置 NULL, // 这个是2M的,不扫描设置NULL }; void app_connect_dev(uint8_t *address) { ob_gap_addr_t peer_addr; memcpy(&peer_addr, address, 7); memcpy(conn_addr_info, address, 7); ob_conn_phy_param_t conn_phy = { .scan_intv = 0x20, .scan_wind = 0x20, // 30➡️37.5ms 6➡️7.5ms 16➡️20ms .conn_intv_min = 6, .conn_intv_max = 6, .latency_max = 0, .timeout = 500, }; ob_conn_param_t conn_param = { OB_ADV_ADDR_TYPE_PUBLIC, OB_SCAN_FILTER_BASIC_UNFILTER, peer_addr, &conn_phy, NULL, NULL, }; uint32_t res = ob_gap_connect(&conn_param); } 连接之前加上: *(__I0 uint32_t *)0x41300080 = (*(__I0 uint32_t *)0x41300080 & (~(0xFF<<16))) | (82<<16); 扫描之前加上: *(__I0 uint32_t *)0x41300080 = (*(__I0 uint32_t *)0x41300080 & (~(0xFF<<16))) | (62<<16); // 只有在干扰大的时候才有效 // 注意该函数在收到广播后调用 static scan_enhance(void) { uint32_t rd_value=*(uint32_t*)0x41300124; rd_value &= ~((0x1FF<<16)|(0x1FF<<0)); *(uint32_t*)0x41300124 = rd_value; } eg: static void dev_record(const ob_gap_evt_adv_report_t *report) { scan_enhance(); scan_info_filter(report); // 这个是自己做的广播或响应包的处理逻辑 } |
