You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Adafruit Feather nRF52840 setWriteCallback丢失回调问题如何解决

问题根因
  1. BLE事件队列默认深度不足:Adafruit Bluefruit BLE栈默认的事件队列深度通常为2,同时到达的写事件超过队列容量时,新事件会被直接丢弃。
  2. 回调函数执行效率过低:回调中使用的Serial打印属于阻塞IO操作,若第一个回调的打印逻辑未执行完成,第二个写事件到达时会因栈无法及时响应而丢失。
  3. 传输模式配置问题:如果特征值配置的是无应答写(Write Without Response),链路层本身不保证传输可靠性,两个数据包同时发送时可能出现空中碰撞,数据未到达开发板就已丢失。
解决方案
  • 调大BLE事件队列深度:找到项目中的Bluefruit_config.h配置文件,将CFG_BLE_EVENT_HANDLER_QUEUE_SIZE参数修改为4或更高,预留足够的事件缓存空间。
  • 优化回调函数逻辑,移除阻塞操作:回调中仅做数据存储,将耗时的打印等逻辑移到主循环执行,参考实现如下:
// 定义环形缓冲区缓存触摸事件,可根据需求调整容量
typedef struct {
  uint8_t hand_type; // 0=左手,1=右手
} touch_event_t;
#define EVENT_BUF_SIZE 8
touch_event_t event_buf[EVENT_BUF_SIZE];
volatile uint8_t buf_write_pos = 0, buf_read_pos = 0;

void charact_write_callback(uint16_t conn_hdl, BLECharacteristic* chr, uint8_t *data, uint16_t len)
{
    if(len >= 2 && data[0] == 2){
        // 回调仅存储数据,不执行耗时操作
        event_buf[buf_write_pos].hand_type = data[1];
        buf_write_pos = (buf_write_pos + 1) % EVENT_BUF_SIZE;
    }
}

void loop() {
  // 主循环统一处理事件
  while(buf_read_pos != buf_write_pos) {
    Serial.print(event_buf[buf_read_pos].hand_type == 0 ? "Left" : "Right");
    Serial.println(" Hand Touch occured");
    buf_read_pos = (buf_read_pos + 1) % EVENT_BUF_SIZE;
  }
  // 原有其他业务逻辑
}
  • 修改传输模式为带应答写:配置特征值时添加BLECharacteristic::PROPERTY_WRITE属性,不要仅使用PROPERTY_WRITE_NO_RESPONSE,同时要求发送端使用带应答的写操作,避免传输层丢包。
  • 调整发送端发包间隔:若两个数据包从同一设备发出,设置至少10ms的发包间隔,避免BLE链路层缓存不足导致丢包。

内容的提问来源于stack exchange,提问作者Acimaz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 15:24:04