Skip to content

读取与解析数据 ​

选择输出 ​

第一个项目先用 HI91。需要增减字段时换 HI83。主机轮询或接入总线时用 Modbus 或 CAN。几种输出可以同时存在,但同一个串口的带宽是共享的,见输出带宽与波特率。出厂时各接口的默认输出见快速上手。

需求选择说明
第一个项目、快速验证HI91定长 82 字节,字段固定:状态、气压、温度、时间、加速度、角速度、磁场、欧拉角、四元数。单位为 G、deg/s,见 HI91
要选字段、要 UTC 和微秒时间戳、要压缩帧长;ROS 的 sensor_msgs/ImuHI83变长帧,字段由 LOG HI83 MAP 选择,每帧自带字段位图,见 HI83 和 HI83 字段选择。加速度单位为 m/s²,角速度单位为 rad/s,与 ROS 一致。四元数顺序为 w、x、y、z,填入 ROS 消息时重排为 x、y、z、w。ROS 轴向见输出数据轴向
主机轮询、多台设备共用 RS-485Modbus 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 校验应通过。

再做两个检查:

  1. 帧前面先喂几个杂乱字节,包括单独的 5A,解码结果应相同。
  2. 改动数据域里任意 1 个字节(CRC 不变),这一帧应被丢弃,紧跟着的好帧仍正常解码。

收不到帧,或解析总是 CRC 错误时,见按现象排查。

时间与时间戳 ​

不同接口、不同帧里的时间戳含义不同。下表是唯一的汇总,其他页面只引用这里。

各接口时间戳的含义 ​

接口与帧时间戳含义
串口周期帧 HI83system_time_us开机累计微秒,不受对时影响。始终落在输出周期的网格上:每帧恰好增加一个周期,改周期或丢帧后重新对齐到当前时刻
串口周期帧 HI91system_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 回绕,是受驯时钟在该帧采样时刻的读数
串口周期帧 HI83utc(bit6)未对时:可能为 0 或粗略值,不是准确时间。已对时:受驯时钟在该帧采样时刻的读数
串口 ONMARK 触发帧帧内全部时间字段处理触发时最新一个样本的时间,不是触发沿的时刻
I2C 读到的 HI83system_time_us、utc最新一个样本的采样时刻
CANFD83SYSTEM_TIME采样时刻
ModbusCPUTIME同一次读取的数据的样本时刻,开机毫秒,不随对时切换

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 最方便。

用时间戳检测丢帧 ​

帧里没有帧计数器,丢帧靠相邻两帧的时间戳间隔判断:

  1. 周期输出(ONTIME)的相邻帧,时间戳之差约等于配置的周期 T(LOG COMCONFIG 读回的 ONTIME,单位 ms),允许 ±1 ms 的抖动。HI83 用 system_time_us,先除以 1000。ONMARK 触发输出没有固定周期,不适用本方法。
  2. 间隔 Δ 大于 max(1.5 T, T + 2 ms) 时判为丢帧,丢了约 Δ/T − 1 帧(取整)。周期只有 1–2 ms 时,偶尔一次时间戳重复或跳变不一定是丢帧。此时统计较长时间窗口内收到的帧数,与应收帧数对比。
  3. system_time 无论是否对时,都在 86 399 999 之后回绕到 0。相减前先处理回绕,例如 (t2 - t1 + 86400000) % 86400000。
  4. 上电、改周期、UTC_UNSYNC 变化前后,时间戳可能不连续。到这些时刻重新开始比较,不判为丢帧。

丢帧的原因有两类:串口带宽不够,模块整帧丢弃;或主机丢字节,导致 CRC 错误。先按输出带宽与波特率核算,再检查主机接收是否及时。

输出带宽与波特率 ​

数据帧能否稳定输出,取决于帧长 × 帧率是否在串口带宽之内。8N1 每字节占 10 bit,因此:

帧率上限 (Hz)=波特率/10单帧字节数

建议占用不超过 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:

帧单帧字节9600115200230400460800921600
HI918211 / 9140 / 112280 / 224561 / 4491000 / 899
HI83 bit0–7989 / 7117 / 94235 / 188470 / 376940 / 752
HI83 bit0–111386 / 583 / 66166 / 133333 / 267667 / 534

例如默认的 HI91 100 Hz 在 115200 下占用 82 × 100 × 10 / 115200 ≈ 71%。改成 200 Hz 需要 164 kbit/s,应选 230400(占用约 71%)。

警告

设置命令返回 OK,只表示命令已接受,不表示带宽够用。超出带宽时数据帧丢失,实际帧率低于设置值,主机往往只看到数据变稀。配置前按上表估算,配置后用相邻帧的时间戳间隔实测。

提高波特率的步骤见 SERIALCONFIG。Modbus 与串口输出共用同一个串口和波特率,见使用前准备。CAN 的吞吐由总线速率决定,不受本表约束。

最后更新:

IMU · AHRS · INS · RTK 技术支持中心