STM32 发出之后,怎样成为蓝牙通知
反向传输多了一项限制:串口随时可能收到字节,蓝牙通知却要满足连接、订阅和发送资源条件。沿着现有发送流程看每个缓冲区为何出现。
1 · 中断先收,事件稍后发
STM32 发来的数据先进入 CH 串口硬件接收缓冲。UART1_IRQHandler 把字节取出,放入 app_uart_rx_fifo,并设置标志。主循环据此安排 UART_TO_BLE_SEND_EVT。到这一刻,字节仍没有发到手机。
2 · 连接和订阅,是发送前的条件
发送分支先调用 ble_uart_notify_is_ready。未订阅时不能按正常路径继续发通知;如果连接已断开,当前逻辑会清理接收软件队列中的积压。它不是可以无限保存离线历史记录的存储模块。
订阅是当前连接的配置。手机重连后要重新开启。观察到 STM32 一直发、手机一直没有通知,应先检查这一条件,再检查应用帧校验。
3 · 一次取多少字节,由实际连接限制
发送事件中的本批上限
read_length = ATT_GetMTU(peripheralConnList.connHandle) - 3;MTU 是这一层约定的最大传输单元。本项目这种普通通知需要留出 3 字节的属性操作开销,剩余部分才用于我们的数据。若协商结果为 23,则本次值最多 20 字节;结果为 247,则最多 244 字节。不能因为数组足够大,就直接发送更长内容。
队列不足一批时,当前代码会等几次事件再发送已有的小批数据,兼顾批量效率与短消息等待。相关延时是库计时单位;应通过测量检查实际等待,而不是把它当成业务超时保证。
4 · 为什么取出来后还要保留一份
队列读出后,数据先存在 to_test_buffer。代码申请蓝牙库发送缓冲,复制本批字节,再调用 ble_uart_notify。申请失败或发送返回失败时,暂存内容和长度仍保留,下一次事件重试这一批,不能先取下一批覆盖它。
提交失败时,项目释放本次申请的缓冲;成功时遵守协议库的所有权约定,不再自行重复释放。这是缓冲生命周期带来的实际需求。读源码时把“队列、暂存数组、库缓冲”依次圈出,理解之后再看状态枚举就有来由。
ble_uart_notify 内部的发送片段 · 定位到 FFE3 属性值
pNoti->handle = ble_uart_ProfileAttrTbl[
RAWPASS_TX_VALUE_HANDLE].handle;
return GATT_Notification(connHandle, pNoti, FALSE);5 · 通知交给库,不等于业务已经收齐
Notify 没有每条通知对应的 GATT 确认;底层链路机制也不能代替跨断连的业务确认。App 仍需持续拼帧、检查长度和校验,需要完整交付的业务还要有事务确认。当前重试分支与断连同时发生时,也应纳入真机压力测试。
用同一条较长消息在不同 MTU 下联调。记录每次通知长度,以及 App 最后组装出的完整帧。只要字节顺序与内容保持正确,分成几次通知可以不同。再关闭订阅、断开并重连,检查当前实现是否满足所需的恢复行为。