手机写入之后,字节怎样到达 STM32
从一次 FFE2 写入出发,依次跟过库回调、事件回调、软件队列与串口寄存器。这里不增加新的业务协议,沿用主线的消息格式。
1 · 先问这一层应该处理什么
手机可能发设置时间、用户资料或原型传输命令。CH582M 的桥接层只负责转交收到的字节,不根据 0xAA 去解释业务帧。应用帧的长度、命令和校验由 STM32 与 App 按协议处理。
2 · 库回调已经告诉我们写到了哪个位置
ble_uart_WriteAttrCB 先区分描述符写入与业务值写入。命中接收特征的 handle 后,把指针与长度放入 evt,调用应用回调。这里的 RX 以 CH 的蓝牙服务为观察点,表示从手机收到数据。
服务写入回调中的片段 · 事件名沿用源码拼写
evt.type = BLE_UART_EVT_BLE_DATA_RECIEVED;
evt.status = SUCCESS;
evt.data.length = (uint16_t)len;
evt.data.p_data = pValue;
ble_uart_AppCBs(connHandle, &evt);
status = evt.status;数据指针来自本次调用,回调结束后不能假定仍可长期使用。项目下一步把数据复制进自己的队列,解决了数据需要稍后发送的保存问题。
3 · 回调先交给队列,让串口慢慢发送
on_bleuartServiceEvt 的接收分支
case BLE_UART_EVT_BLE_DATA_RECIEVED:
p_evt->status = app_uart_tx_data(
p_evt->data.p_data, p_evt->data.length);
break;app_uart_tx_data 调用 app_drv_fifo_write_all,要求这一整块都能放入。如果空间不足,它增加拒绝计数并返回资源不足。这样不会只收下半块,却向上层表示整块已接受。已有的字节仍由主循环继续发送。
4 · 发送队列不等于串口硬件缓冲
软件队列在 RAM 数组中,串口硬件还有自己的发送缓冲。app_uart_process 读取 R8_UART1_TFC,确认硬件还能接纳多少字节,然后把对应数量写入 R8_UART1_THR。同一个寄存器被反复写,每次写入一个待发送字节。
因此主循环需要不断执行。长时间堵在蓝牙回调中,会拖慢这一步,软件队列也更容易积压。串口接收方还必须把分次收到的字节持续交给帧解析器,不能把一次中断当作消息边界。
5 · 接受写入与业务执行成功,分开观察
有响应写入可以报告属性写入失败;无响应写入没有同样的属性响应可依靠。即使写入已接受,也只说明某层接收了字节,不说明 STM32 已经执行设置。需要可靠确认的命令仍应按应用协议等待对应响应。