Windows 10 BLE数据传输速率过低,如何提升传输性能?
Windows 10 BLE应用传输速率优化方案
问题背景
我在运行Windows 10的BLE示例应用,连接外设并发送数据。该外设通过Android应用可达到数KB/秒的传输速率,但Windows应用仅能达到约130B/秒。尝试以高速率发送70字节的数据包,期望传输速率至少达到10KB/秒(BLE 4.2理论性能为1Mbps),但未达到预期。目前未找到通过Windows.Devices.Bluetooth库调整BLE传输速率的配置方式,求提升速率的方法。
相关代码
public async void BLE_ConnectionAsync(string ble_name) { bool bleCharacteristicsConnect = false; try { if(!bleCharacteristicsConnect) { if (ble_name != null) { nameBle = ble_name; string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected" }; deviceWatcher = DeviceInformation.CreateWatcher( BluetoothLEDevice.GetDeviceSelectorFromPairingState(false), requestedProperties, DeviceInformationKind.AssociationEndpoint); deviceWatcher.Added += DevicedWatcher_Added; deviceWatcher.Updated += DevicedWatcher_Updated; deviceWatcher.Removed += DevicedWatcher_Removed; deviceWatcher.EnumerationCompleted += DevicedWatcher_EnumerationCompleted; deviceWatcher.Stopped += DevicedWatcher_Stopped; deviceWatcher.Start(); while (true) { if (device == null) { Thread.Sleep(200); } else { bluetoothLEDevice = await BluetoothLEDevice.FromIdAsync(device.Id); result = await bluetoothLEDevice.GetGattServicesAsync(); if (result.Status == GattCommunicationStatus.Success) { var services = result.Services; bool shouldExit = false; foreach (var service in services) { string test = service.Uuid.ToString("N"); string test2 = service.Uuid.ToString("N").Substring(4, 4); Console.WriteLine("Service id: " + test2); if (service.Uuid.ToString("N").Substring(4, 4) == "fe40" || service.Uuid.ToString("N").Substring(4, 4) == HEART_RATE_SERVICE_ID) { GattCharacteristicsResult characteristicsResult = await service.GetCharacteristicsAsync(); if (characteristicsResult.Status == GattCommunicationStatus.Success) { var characteristics = characteristicsResult.Characteristics; foreach (var characteristic in characteristics) { GattCharacteristicProperties properties = characteristic.CharacteristicProperties; try { GattCommunicationStatus status = await characteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify); if (status == GattCommunicationStatus.Success) { characteristic.ValueChanged += Characteristic_ValueChanged; selectedCharacteristic = characteristic; Console.WriteLine("Read char "+characteristic.Uuid.ToString("N")); } else { } } catch (Exception ex) { bleCharacteristicsConnect = true; writeChar = characteristic; Console.WriteLine("Write char " + characteristic.Uuid.ToString("N")); OpenComPort(ble_name); shouldExit = true; break; } } if (shouldExit) { break; } } } } break; } else { break; } } } } } } catch (Exception ex) { log.Error(ex.Message); } } private async void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { try { SerialPort sp = (SerialPort)sender; byte[] data = new byte[sp.BytesToRead]; if(data.Length> MAX_PAYLOAD_SIZE) { sp.Read(data, 0, data.Length); byte[] _data = new byte[MAX_PAYLOAD_SIZE]; int countPackets = (data.Length) / MAX_PAYLOAD_SIZE; int remainder = (data.Length) % MAX_PAYLOAD_SIZE; log.Info(" [COM --> BLE] \t Data Length = " + data.Length + " Data = " + ByteArrayToString(data)); int i = 0; for (i = 0; i < countPackets; i++) { await writeChar.WriteValueAsync(data.AsBuffer(i * MAX_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE)); } if (remainder > 0) { await writeChar.WriteValueAsync(data.AsBuffer(i * MAX_PAYLOAD_SIZE, remainder)); } } else { sp.Read(data, 0, data.Length); await writeChar.WriteValueAsync(data.AsBuffer()); } } catch (Exception ex) { log.Error(ex.Message); } }
优化方案
1. 启用BLE数据长度扩展(DLE)
BLE 4.2支持最大251字节的数据包,Windows默认可能未开启该功能,可通过注册表修改启用:
- 打开注册表编辑器,定位到
HKLM\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters - 添加DWORD值
EnableDataLengthExtension,设置为1 - 重启蓝牙服务或系统生效
2. 批量异步发送数据包
当前代码逐个等待单包写入完成,引入大量延迟。改用批量异步发送,充分利用BLE传输窗口:
// 替换DataReceivedHandler中的循环代码 var tasks = new List<Task>(); for (i = 0; i < countPackets; i++) { tasks.Add(writeChar.WriteValueAsync(data.AsBuffer(i * MAX_PAYLOAD_SIZE, MAX_PAYLOAD_SIZE)).AsTask()); } if (remainder > 0) { tasks.Add(writeChar.WriteValueAsync(data.AsBuffer(i * MAX_PAYLOAD_SIZE, remainder)).AsTask()); } await Task.WhenAll(tasks);
注意:需确认外设支持多包缓存,避免丢包。
3. 使用无响应写入模式
带响应的写入需要等待外设ACK,速率受限。确认特征支持WriteWithoutResponse后,改用无响应写入:
// 在特征选择时检查属性 if ((characteristic.CharacteristicProperties & GattCharacteristicProperties.WriteWithoutResponse) != 0) { writeChar = characteristic; // 写入时指定无响应选项 await writeChar.WriteValueAsync(buffer, GattWriteOption.WriteWithoutResponse); }
无响应写入速率更高,但需自行处理可能的丢包场景。
4. 调整BLE连接参数
Windows默认连接间隔偏保守,可请求更优的参数提升传输效率:
// 在连接成功后添加参数调整逻辑 var currentParams = await bluetoothLEDevice.GetConnectionParametersAsync(); var desiredParams = new BluetoothLEConnectionParameters { MinConnectionInterval = TimeSpan.FromMilliseconds(7.5), // BLE 4.2最小支持7.5ms间隔 MaxConnectionInterval = TimeSpan.FromMilliseconds(15), SlaveLatency = 0, SupervisionTimeout = TimeSpan.FromMilliseconds(2000) }; var result = await bluetoothLEDevice.RequestConnectionParametersAsync(desiredParams);
注意:外设需支持对应参数范围,否则请求可能被拒绝。
5. 替换阻塞式等待
原代码中Thread.Sleep(200)阻塞主线程,改用异步延迟避免影响调度:
// 替换BLE_ConnectionAsync中的循环等待 while (device == null) { await Task.Delay(200); }
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

