# GPS/IMU 数据传输协议文档 ## 概述 本协议用于 STM32H7 (割草机MCU) 通过 UART5 向 Python 程序发送 GPS 和 IMU 数据。 - **通信接口**: UART5 (串口5) - **波特率**: 921600 bps - **数据位**: 8 - **停止位**: 1 - **校验**: None - **流控**: None - **DMA**: 发送和接收均使用 DMA ## 数据帧格式 每个数据包采用如下格式: ``` +--------+--------+------+--------+--------+------+--------+--------+ | Header | Header | Type | Length | Length | Data | CRC16 | CRC16 | | 0xAA | 0x55 | | Low | High | ... | Low | High | +--------+--------+------+--------+--------+------+--------+--------+ | Footer | Footer | | 0x0D | 0x0A | +--------+--------+ ``` ### 字段说明 | 字段 | 大小(字节) | 说明 | |------|-----------|------| | Header1 | 1 | 帧头1: 固定为 `0xAA` | | Header2 | 1 | 帧头2: 固定为 `0x55` | | Type | 1 | 数据类型: `0x01`=GPS, `0x02`=IMU | | Length | 2 | 数据长度 (小端序), 不包含帧头、类型、长度、CRC和帧尾 | | Data | N | 数据负载 (结构体二进制) | | CRC16 | 2 | CRC16-MODBUS校验 (小端序), 校验范围: 从Header1到Data末尾 | | Footer1 | 1 | 帧尾1: 固定为 `0x0D` (CR) | | Footer2 | 1 | 帧尾2: 固定为 `0x0A` (LF) | ## 数据类型 ### 1. GPS数据包 (Type = 0x01) **更新频率**: 10 Hz (GPS模块解析成功后立即发送) **数据结构** (56 字节, 小端序): | 字段 | 类型 | 偏移 | 大小 | 单位 | 说明 | |------|------|------|------|------|------| | m_dLatitude | double | 0 | 8 | 度(°) | 纬度, 正数为北纬 | | m_dLongitude | double | 8 | 8 | 度(°) | 经度, 正数为东经 | | m_fHeadingAngle | float | 16 | 4 | 度(°) | 航向角, 0~360, 基于东北速度计算 | | m_fEastVelocity | float | 20 | 4 | m/s | 东方向速度 | | m_fNorthVelocity | float | 24 | 4 | m/s | 北方向速度 | | m_fUpVelocity | float | 28 | 4 | m/s | 天顶方向速度 | | m_fAltitude | float | 32 | 4 | m | 高程 | | m_u32UTCTime | uint32 | 36 | 4 | hhmmss | UTC时间 | | m_u8PositionQuality | uint8 | 40 | 1 | - | 0=无效, 1=单点, 2=差分, 4=固定, 5=浮点 | | m_u8SatelliteCount | uint8 | 41 | 1 | - | 可见卫星数量 | | m_u8Reserved | uint8[2] | 42 | 2 | - | 保留字节(对齐) | **C结构体定义** (见 `FML/PythonLink.h`): ```c typedef struct __attribute__((packed)) { HIDO_DOUBLE m_dLatitude; // 纬度(°) HIDO_DOUBLE m_dLongitude; // 经度(°) HIDO_FLOAT m_fHeadingAngle; // 航向角(°) HIDO_FLOAT m_fEastVelocity; // 东方向速度(m/s) HIDO_FLOAT m_fNorthVelocity; // 北方向速度(m/s) HIDO_FLOAT m_fUpVelocity; // 天顶方向速度(m/s) HIDO_FLOAT m_fAltitude; // 高程(m) HIDO_UINT32 m_u32UTCTime; // UTC时间 HIDO_UINT8 m_u8PositionQuality; // 定位质量 HIDO_UINT8 m_u8SatelliteCount; // 卫星数量 HIDO_UINT8 m_u8Reserved[2]; // 保留字节 } ST_PythonLink_GPS; ``` ### 2. IMU数据包 (Type = 0x02) **更新频率**: 100 Hz (IMU模块解析成功后立即发送) **数据结构** (32 字节, 小端序): | 字段 | 类型 | 偏移 | 大小 | 单位 | 说明 | |------|------|------|------|------|------| | m_fAccelX | float | 0 | 4 | g | X轴加速度 | | m_fAccelY | float | 4 | 4 | g | Y轴加速度 | | m_fAccelZ | float | 8 | 4 | g | Z轴加速度 | | m_fGyroX | float | 12 | 4 | °/s | X轴角速度 | | m_fGyroY | float | 16 | 4 | °/s | Y轴角速度 | | m_fGyroZ | float | 20 | 4 | °/s | Z轴角速度 | | m_fTemperature | float | 24 | 4 | ℃ | 传感器温度 | | m_u32UTCTime | uint32 | 28 | 4 | ms | UTC时间(毫秒) | **C结构体定义** (见 `FML/PythonLink.h`): ```c typedef struct __attribute__((packed)) { HIDO_FLOAT m_fAccelX; // X轴加速度(g) HIDO_FLOAT m_fAccelY; // Y轴加速度(g) HIDO_FLOAT m_fAccelZ; // Z轴加速度(g) HIDO_FLOAT m_fGyroX; // X轴角速度(°/s) HIDO_FLOAT m_fGyroY; // Y轴角速度(°/s) HIDO_FLOAT m_fGyroZ; // Z轴角速度(°/s) HIDO_FLOAT m_fTemperature; // 传感器温度(℃) HIDO_UINT32 m_u32UTCTime; // UTC时间(毫秒) } ST_PythonLink_IMU; ``` ## CRC16-MODBUS 校验 使用标准的 CRC16-MODBUS 算法: - **多项式**: 0x8005 - **初始值**: 0xFFFF - **结果异或值**: 0x0000 - **反射输入**: True - **反射输出**: True **校验范围**: 从帧头 (0xAA) 到数据负载末尾 (不包含CRC和帧尾) ## 数据流向 ``` STM32H7 (UART5 TX) ──────> Python (串口 RX) 921600 bps GPS (10Hz) ──> GPS_ParseGPRMI() ──> PythonLink_SendGPSData() ──> UART5 TX IMU (100Hz) ─> GPS_ParseGPIMU() ──> PythonLink_SendIMUData() ──> UART5 TX ``` ## 触发机制 - **GPS数据**: 当 `GPS_ParseGPRMI()` 解析成功后, 立即调用 `PythonLink_SendGPSData()` 发送 - **IMU数据**: 当 `GPS_ParseGPIMU()` 解析成功后, 立即调用 `PythonLink_SendIMUData()` 发送 这种机制保证了数据的**实时性** (零额外延迟), 适用于后续的电脑控制车辆实际行走场景。 ## Python解析示例 参见 `python/gps_imu_receiver.py` ### 安装依赖 ```bash pip install -r python/requirements.txt ``` ### 运行示例 ```bash python python/gps_imu_receiver.py ``` ### 修改串口配置 编辑 `gps_imu_receiver.py` 中的 `PORT` 和 `BAUDRATE`: ```python # Windows PORT = "COM3" # Linux PORT = "/dev/ttyUSB0" # 波特率 (与STM32配置一致) BAUDRATE = 921600 ``` ## 实现文件清单 ### STM32 固件 | 文件 | 说明 | |------|------| | `FML/PythonLink.h` | PythonLink 模块接口 | | `FML/PythonLink.c` | PythonLink 模块实现 | | `FML/GPS.c` | GPS解析, 添加了立即发送调用 | | `HAL/Uart.h` | 添加了 `UART_ID_PYTHON` 枚举 | | `Core/Src/main.c` | 注册 `UART5` 为 `UART_ID_PYTHON` | | `APL/app.c` | 初始化和轮询 PythonLink | ### Python 解析器 | 文件 | 说明 | |------|------| | `python/gps_imu_receiver.py` | GPS/IMU 数据接收解析器 | | `python/requirements.txt` | Python依赖项 | | `PROTOCOL.md` | 本协议文档 | ## 注意事项 1. **字节对齐**: 所有结构体使用 `__attribute__((packed))` 确保无填充字节 2. **字节序**: 所有多字节数据使用小端序 (Little Endian) 3. **实时性**: GPS 10Hz, IMU 100Hz, 解析成功后立即通过 DMA 发送 4. **DMA队列**: 发送队列深度为8, 避免丢包 5. **错误处理**: Python端需处理CRC校验失败、帧丢失等异常情况 ## 扩展性 协议预留了数据类型字段 (Type), 可方便扩展其他数据类型, 例如: - `0x03`: SBUS 遥控器数据 - `0x04`: 车辆状态数据 (电池、电机等) - `0x05`: 控制命令 (Python -> STM32) ## 版本历史 - **v1.0** (2025-11-13): 初始版本, 支持GPS和IMU数据发送