Files
origincar_controller/doc/uart_protocol_v2_timestamp.md
cyy_mac 93ca37e36c 完善阿克曼控制与高速串口遥测
- 校正舵机中位、转向符号和阿克曼后轮差速模型\n- 增加航向角速度辅助及遥控通道调试开关\n- 将速度环提升至 200Hz,并按实际 dt 计算 PI 积分\n- 将 IMU 启动校准缩短为 2 秒\n- 为 USART3 增加 DMA 发送和 MCU 采样时间戳
2026-08-12 18:51:48 +08:00

5.9 KiB
Raw Permalink Blame History

下位机 UART 发送协议 v2带采样时间戳

本文件描述 STM32 下位机通过 USART3ROS 口,波特率 921600 周期发送给上位机的 传感器数据帧格式。v2 在原 24 字节帧的基础上,于帧尾追加了会话 ID 与两个采样 时间戳字段,用于上位机做 IMU / 轮速 / 雷达的时间对齐。

1. 帧总览

项目
帧头 FRAME_HEADER 0x7B
帧尾 FRAME_TAIL 0x7D
帧长 SEND_DATA_SIZE 44 字节v1 为 24 字节)
发送周期 200 Hzdata_taskUSART3 非阻塞 DMA 发送)
字节序 多字节字段一律 大端(高字节在前)
校验 单字节 XOR覆盖 byte 0..41

设计约束byte 0..21 与 v1 完全一致,新增字段全部放在校验位之前的尾部, 使只读取旧字段的解析器仍然兼容。

2. 字节布局

偏移 长度 字段 类型 说明
0 1 Frame_Header u8 帧头 0x7B
1 1 Flag_Stop u8 软件失能标志1=停车)
2 2 X_speed int16 X 轴线速度,单位 mm/s大端
4 2 Y_speed int16 Y 轴线速度,单位 mm/s大端
6 2 Z_speed int16 Z 轴角速度,单位 mm/s等效大端
8 2 Accel_X int16 加速度计 XROS 坐标),大端
10 2 Accel_Y int16 加速度计 YROS 坐标),大端
12 2 Accel_Z int16 加速度计 ZROS 坐标),大端
14 2 Gyro_X int16 陀螺仪 XROS 坐标),大端
16 2 Gyro_Y int16 陀螺仪 YROS 坐标),大端
18 2 Gyro_Z int16 陀螺仪 ZROS 坐标),大端
20 2 Power_Voltage int16 电池电压×1000大端
22 4 session_id uint32 本次 MCU 启动会话 ID大端
26 8 speed_sample_time_us uint64 编码器采样时刻μs大端
34 8 imu_sample_time_us uint64 IMU 采样时刻μs大端
42 1 Checksum u8 byte 0..41 的 XOR
43 1 Frame_Tail u8 帧尾 0x7D

加粗行为 v2 相对 v1 的新增字段。

3. 时间源

时间戳由自由运行的 TIM7 提供,见 HARDWARE/timer.c

  • TIM7 挂在 APB1定时器时钟 84 MHz预分频 84 → 1 MHz 计数1 tick = 1 μs
  • 16 位计数器每 65.536 ms 回绕一次,更新中断把高 32 位软件计数 g_time_high 加一。
  • mcu_time_us() 返回 (g_time_high << 16) | CNT,即自上电以来的单调递增微秒数 可用位宽 48 位(约 8.9 年不回绕)。
  • TIM2~TIM5 被四路编码器占用、TIM8 被航模遥控输入捕获占用,故选空闲的 TIM7。
  • TIM7 更新中断优先级设为 5数值大于 configMAX_SYSCALL_INTERRUPT_PRIORITY 对应的抢占门限ISR 内只做自增,不调用任何 FreeRTOS API。

注意:mcu_time_us() 只增不减,绝不因校时而跳变。上位机负责维护 T_host = a·t_mcu + b 的时钟映射(见 时间戳.md 第 7、8 节)。

4. 两个时间戳分别打在哪里

v1 只有"发送时刻"隐含语义,无法表达 IMU100 Hz与轮速200 Hz异步采集的。 v2 在各自真实采样点打点,写入全局变量,data_transition() 打包时快照:

时间戳 打点位置 采样率
speed_sample_time_us balance.c Get_Velocity_Form_Encoder() 读编码器锁存计数器的瞬间 200 Hz
imu_sample_time_us MPU6050.c MPU6050_task I2C 读取前 100 Hz

因此一帧内同时带两个时间戳:上位机应把加速度/角速度对齐到 imu_sample_time_us 把 X/Y/Z 速度对齐到 speed_sample_time_us,而不是共用一个发送时刻。

IMU 打点在 I2C 突发读取之前,是在没有 DRDY数据就绪中断条件下能取到的、 最接近物理采样的时刻。若日后接入 MPU 的 DRDY 引脚中断,可把打点移到中断里进一步减小抖动。

5. session_id

  • 定义在 usartx.cg_session_id
  • 当前实现为固定值 0xA5A5A5A5
  • 用途:上位机据此判断下位机是否重启过(重启后 mcu_time_us() 从 0 重新计时, 时钟映射 a, b 必须重新拟合)。
  • 待办:如需真正区分每次上电,应在启动时用熵源(如未初始化 RAM、启动 tick 等) 生成一次性随机值。当前固定值只能表明"协议版本一致",不能区分不同启动会话。

6. 校验与解析建议

  • 校验位 buffer[42] = XOR(buffer[0..41]),与 v1 的计算方式相同,只是范围从 22 扩到 42。
  • 上位机解析步骤:
    1. 同步帧头 0x7B
    2. 读满 44 字节;
    3. 校验 buffer[43] == 0x7DXOR(buffer[0..41]) == buffer[42]
    4. 按上表大端解出各字段。
  • 多字节字段务必按大端手动组装,不要直接 memcpy 结构体(编译器填充/对齐/端序差异)。

7. 其他发送通道

通道 现状
USART3ROS 主口DMA 已用 SEND_DATA_SIZE,自动发送完整 44 字节
USART1 / USART5 已改用 SEND_DATA_SIZE,发送完整 44 字节
CAN 当前未被调用;CAN_SEND() 仍按 8×3=24 字节分包,不含时间戳字段。如需经 CAN 传时间戳需另行扩展分包

8. 上位机适配提醒

USART3 收到的帧已从 24 字节变为 44 字节。上位机ROS 端)解析代码必须同步更新: 帧长、校验范围、以及尾部三个新字段的读取。否则会因帧长不符导致解析错位。