STM32WB BLE5通信循环发送数据丢失问题求助
STM32WB BLE5 循环发送通知丢包问题解决建议
问题根源
- 死循环阻塞系统:在
P2PS_Send_Notification中使用while(1)死循环连续调用发送函数,直接阻塞UTIL_SEQ任务调度,导致BLE协议栈无法处理发送ACK、连接维护等核心事件,最终触发协议栈丢弃未处理的发送请求。 - 异步发送未等待完成:
P2PS_STM_App_Update_Char是向BLE协议栈提交发送请求,而非同步完成发送。连续提交请求会造成队列溢出,协议栈直接丢弃后续请求,这是数据丢失、乱序的直接原因。 - 类型转换隐患:将
int类型变量强转uint8_t*,在32位系统下实际发送的是int的低字节,当前数值巧合正常,但后续ADC多字节数据传输会出现错误。
解决方案
1. 改用事件驱动的分步发送逻辑
移除死循环,利用BLE发送完成回调+UTIL_SEQ任务实现有序发送,确保上一次通知发送完成后再发下一个:
// 全局标志:标记上一次通知是否发送完成 static uint8_t notification_ready = 1; // 标记发送流程是否已启动 static uint8_t send_running = 0; // 重写BLE通知完成的回调函数(需对应你工程中的回调接口) void P2PS_STM_App_Notification_Complete(uint16_t conn_handle, uint16_t attr_handle) { if (attr_handle == P2P_NOTIFY_CHAR_HANDLE) // 确认是目标特征的通知 { notification_ready = 1; // 通知完成后,触发下一次发送任务 UTIL_SEQ_SetTask(1 << CFG_TASK_SEND_BLE_DATA, CFG_SEQ_PRIO_0); } } void P2PS_Send_Notification(void) { // 避免重复触发发送流程 if (send_running) return; send_running = 1; // 重置发送索引 group_idx = 0; data_idx = 0; // 启动第一次发送任务 UTIL_SEQ_SetTask(1 << CFG_TASK_SEND_BLE_DATA, CFG_SEQ_PRIO_0); } // 全局索引:记录当前发送的组和数据位置 static uint8_t group_idx = 0; static uint8_t data_idx = 0; #define TOTAL_GROUPS 5 // 原代码中的i循环次数 #define PER_GROUP_DATA_CNT 4 // 每组4个数据:4,5,5,5 // 分步发送数据的任务函数 static void Send_Next_Data(void) { uint8_t send_data; // 上一次发送未完成,直接退出 if (!notification_ready) return; // 确定当前要发送的数据 if (data_idx == 0) { send_data = 4; } else { send_data = 5; } // 提交发送请求,标记未完成 notification_ready = 0; P2PS_STM_App_Update_Char(P2P_NOTIFY_CHAR_UUID, &send_data); // 更新发送索引 data_idx++; if (data_idx >= PER_GROUP_DATA_CNT) { data_idx = 0; group_idx++; // 完成所有组后停止发送 if (group_idx >= TOTAL_GROUPS) { group_idx = 0; send_running = 0; return; } } } // 在初始化中注册发送任务 void P2PS_APP_Init(void) { UTIL_SEQ_RegTask(1 << CFG_TASK_SW1_BUTTON_PUSHED_ID, UTIL_SEQ_RFU, P2PS_Send_Notification); // 注册分步发送任务 UTIL_SEQ_RegTask(1 << CFG_TASK_SEND_BLE_DATA, UTIL_SEQ_RFU, Send_Next_Data); }
2. 修复数据类型问题
将发送数据的变量改为uint8_t类型,避免跨类型转换的潜在错误:
// 原代码的int改为uint8_t uint8_t start_data = 4; uint8_t local = 5;
3. 优化BLE连接参数(可选)
如果需要更高的发送频率,可调整连接间隔等参数,提升通信效率:
// 示例:设置连接间隔为10ms(单位:0.625ms,16*0.625=10ms) uint16_t conn_interval_min = 16; uint16_t conn_interval_max = 16; uint16_t slave_latency = 0; uint16_t supervision_timeout = 100; // 超时时间1s(100*10ms) aci_gap_set_connection_parameters(conn_interval_min, conn_interval_max, slave_latency, supervision_timeout);
核心注意事项
- 永远不要在UTIL_SEQ任务中写死循环,会阻塞系统调度,导致BLE协议栈无法处理关键事件。
- BLE通知是异步操作,必须等待发送完成回调后再提交下一个请求,否则会出现丢包。
- 按键触发仅作为发送流程的启动信号,而非直接执行发送循环。
内容的提问来源于stack exchange,提问作者dfsdf
相关产品推荐
相关产品推荐

