读取与解析数据
选择输出
第一个项目先用 HI91。需要增减字段时换 HI83。主机轮询或接入总线时用 Modbus 或 CAN。几种输出可以同时存在,但同一个串口的带宽是共享的,见输出带宽与波特率。出厂时各接口的默认输出见快速上手。
| 需求 | 选择 | 说明 |
|---|---|---|
| 第一个项目、快速验证 | HI91 | 定长 82 字节,字段固定:状态、气压、温度、时间、加速度、角速度、磁场、欧拉角、四元数。单位为 G、deg/s,见 HI91 |
要选字段、要 UTC 和微秒时间戳、要压缩帧长;ROS 的 sensor_msgs/Imu | HI83 | 变长帧,字段由 LOG HI83 MAP 选择,每帧自带字段位图,见 HI83 和 HI83 字段选择。加速度单位为 m/s²,角速度单位为 rad/s,与 ROS 一致。四元数顺序为 w、x、y、z,填入 ROS 消息时重排为 x、y、z、w。ROS 轴向见输出数据轴向 |
| 主机轮询、多台设备共用 RS-485 | Modbus RTU | 寄存器读写,是否提供看型号。作从站前先关闭周期输出,见使用前准备 |
| 车载、机器人总线集成 | CAN(J1939)或 CAN FD 型号的 CANFD83 | 周期发送,见 CAN 概述 |
| -I2C 型号 | I2C 读 HI83 帧 | 见 I2C 适用型号与引脚 |
串口输出的周期、字段和波特率在串口与数据输出里设置。同一物理量在不同协议里的类型、比例和单位不同,以数据字典为准。
解析器
HI91 和 HI83 的帧封装相同,一个解析器处理两者。帧格式见帧格式,CRC 算法见 CRC 校验。
解析规则:
- 在字节流里找
5A A5。 - 读出 LEN,LEN 不得超过 512,否则这不是真正的帧头。
- 收满 6 + LEN 字节后校验 CRC。CRC 覆盖帧头、LEN 和数据域,不含 CRC 字段本身。
- CRC 正确就交给应用,并丢掉整帧。CRC 错误只丢 1 个字节,再从后面的下一个
5A A5重新找。一次错位不会连累后面的好帧。 - 数据域第 1 字节是 tag,
0x91为 HI91,0x83为 HI83。HI83 按每帧的位图取字段,规则见 HI83 解析规则。
解码库和使用示例见官方 SDK:C 语言库的 README 说明了如何把串口收到的字节送入解码器,帧解码和 CRC 实现在 hipnuc_dec.c。自己实现时,字段按偏移用 memcpy 取出,避免未对齐访问;假设主机为小端、float 为 IEEE-754 单精度。
使用时注意:
- 上电初期的帧可能全为 0,直接丢弃,判断方法见上电过程。
- 俯仰接近 ±90° 时欧拉角不连续,需要连续的姿态时用四元数,见姿态表示。
- 解析线程要及时读串口。丢字节、CRC 错误和模块端丢帧在数据上表现相同,都是时间戳出现缺口,见时间与时间戳。
测试向量
先用一帧已知数据验证解析器。帧解析示例给出了默认输出数据轴向(COORD 0)下采集的一帧 82 字节 HI91,附逐字段的解码值。把这 82 字节依次喂给解析器,解码出的值应与该表逐项相等,CRC 校验应通过。
再做两个检查:
- 帧前面先喂几个杂乱字节,包括单独的
5A,解码结果应相同。 - 改动数据域里任意 1 个字节(CRC 不变),这一帧应被丢弃,紧跟着的好帧仍正常解码。
收不到帧,或解析总是 CRC 错误时,见按现象排查。
时间与时间戳
不同接口、不同帧里的时间戳含义不同。下表是唯一的汇总,其他页面只引用这里。
各接口时间戳的含义
| 接口与帧 | 时间戳 | 含义 |
|---|---|---|
| 串口周期帧 HI83 | system_time_us | 开机累计微秒,不受对时影响。始终落在输出周期的网格上:每帧恰好增加一个周期,改周期或丢帧后重新对齐到当前时刻 |
| 串口周期帧 HI91 | system_time | 未对时(UTC_UNSYNC 为 1):开机毫秒计数,落在输出网格上,每 24 h 回绕到 0(0–86 399 999),不表示绝对时间,不能换算日期或钟表时间 |
| 同上 | system_time | 已对时(UTC_UNSYNC 为 0):当日 UTC 毫秒计数,范围 0–86 399 999(00:00:00.000–23:59:59.999),按 24 h 回绕,是受驯时钟在该帧采样时刻的读数 |
| 串口周期帧 HI83 | utc(bit6) | 未对时:可能为 0 或粗略值,不是准确时间。已对时:受驯时钟在该帧采样时刻的读数 |
串口 ONMARK 触发帧 | 帧内全部时间字段 | 处理触发时最新一个样本的时间,不是触发沿的时刻 |
| I2C 读到的 HI83 | system_time_us、utc | 最新一个样本的采样时刻 |
| CANFD83 | SYSTEM_TIME | 采样时刻 |
| Modbus | CPUTIME | 同一次读取的数据的样本时刻,开机毫秒,不随对时切换 |
utc 何时有效,由 MAIN_STATUS 的 UTC_UNSYNC 位判断。已对时时 system_time = 3 661 000 对应 UTC 01:01:01.000。HI91 的 system_time 不含日期;时间不含时区,对时完成后按 UTC+0 解释,本地时间由主机叠加时区偏移。对时方法见 PPS 对时。
表中“落在输出网格上”的时间戳是输出时钟,不是传感器的采样时刻,不能用来反推采样时刻。需要与外部设备对齐采样时间时,用 SYNC_IN 触发或 PPS 对时,见时间同步与 IO。只需要相对时间或检测丢帧时,用 HI83 的 system_time_us 最方便。
用时间戳检测丢帧
帧里没有帧计数器,丢帧靠相邻两帧的时间戳间隔判断:
- 周期输出(
ONTIME)的相邻帧,时间戳之差约等于配置的周期 T(LOG COMCONFIG读回的ONTIME,单位 ms),允许 ±1 ms 的抖动。HI83 用system_time_us,先除以 1000。ONMARK触发输出没有固定周期,不适用本方法。 - 间隔 Δ 大于 max(1.5 T, T + 2 ms) 时判为丢帧,丢了约 Δ/T − 1 帧(取整)。周期只有 1–2 ms 时,偶尔一次时间戳重复或跳变不一定是丢帧。此时统计较长时间窗口内收到的帧数,与应收帧数对比。
system_time无论是否对时,都在 86 399 999 之后回绕到 0。相减前先处理回绕,例如(t2 - t1 + 86400000) % 86400000。- 上电、改周期、
UTC_UNSYNC变化前后,时间戳可能不连续。到这些时刻重新开始比较,不判为丢帧。
丢帧的原因有两类:串口带宽不够,模块整帧丢弃;或主机丢字节,导致 CRC 错误。先按输出带宽与波特率核算,再检查主机接收是否及时。
输出带宽与波特率
数据帧能否稳定输出,取决于帧长 × 帧率是否在串口带宽之内。8N1 每字节占 10 bit,因此:
建议占用不超过 80%。同一串口上所有周期帧的字节数要相加。周期以整毫秒设置,所以帧率是 1000/N Hz,最高 1000 Hz。400 Hz 对应 2.5 ms,不是整毫秒,取整规则见 LOG。可改选 0.002(500 Hz)或 0.005(200 Hz)。
HI91 单帧 82 字节。HI83 的单帧字节数随所选字段变化,算法见帧长示例。下表按两种 HI83 配置计算:98 字节对应选择 bit0–7(加速度、角速度、磁场、欧拉角、四元数、system_time_us、UTC、气压),138 字节对应选满 bit0–11。单元格为“理论上限 / 建议上限(占用 80%)”,单位 Hz:
| 帧 | 单帧字节 | 9600 | 115200 | 230400 | 460800 | 921600 |
|---|---|---|---|---|---|---|
| HI91 | 82 | 11 / 9 | 140 / 112 | 280 / 224 | 561 / 449 | 1000 / 899 |
| HI83 bit0–7 | 98 | 9 / 7 | 117 / 94 | 235 / 188 | 470 / 376 | 940 / 752 |
| HI83 bit0–11 | 138 | 6 / 5 | 83 / 66 | 166 / 133 | 333 / 267 | 667 / 534 |
例如默认的 HI91 100 Hz 在 115200 下占用 82 × 100 × 10 / 115200 ≈ 71%。改成 200 Hz 需要 164 kbit/s,应选 230400(占用约 71%)。
警告
设置命令返回 OK,只表示命令已接受,不表示带宽够用。超出带宽时数据帧丢失,实际帧率低于设置值,主机往往只看到数据变稀。配置前按上表估算,配置后用相邻帧的时间戳间隔实测。
提高波特率的步骤见 SERIALCONFIG。Modbus 与串口输出共用同一个串口和波特率,见使用前准备。CAN 的吞吐由总线速率决定,不受本表约束。
