CAN系列 — (3) Radar Object List 在 MCU 内部是如何被拼装、校验并最终被消费的?

本文统一使用 MCU(Microcontroller Unit) 表示雷达 CAN FD 报文的接收与处理节点。

在系统架构语境中,该 MCU 可能承担域控制器(DCU)的角色,但在本文讨论的 CAN 接收、AUTOSAR 链路与 Object List 拼装问题上,两者指代同一执行实体。


1. 从 CAN 报文进入 MCU 开始,问题才真正出现

在系统设计评审中,经常会看到一种"错觉":只要 CAN FD 带宽算够、报文能收到,雷达数据就算接进来了。

但在真实工程中,CAN 报文进入 MCU 只是物理层和驱动层的完成,离"可被感知算法使用"还隔着一整套软件语义重建过程。

一次完整的雷达 Object 更新周期,在 MCU 内部通常会经历如下路径:
CAN FD Rx ISR
CanIf
PduR
COM / Decode
Object List Assembler
Consistency Check
Validated Object Buffer
Perception / Fusion

这里存在一个非常重要但容易被忽略的事实:

CAN 报文是"帧级事件",
Radar Object List 是"周期级结果"。

MCU 的职责,不是"尽快处理每一帧 CAN 报文",

而是在正确的时间点,向上层提供一个完整、一致、可信的 Object List 快照。


2. MCU 为什么必须先知道"这一周期应该有多少 Object"

在 Object List 拼装逻辑中,expected_obj_num 是一个绕不开的变量。它的存在,解决的是一个问题:

MCU 如何判断"这一轮雷达数据是否已经收全"?

2.1 expected_obj_num 的来源

工程上的共识:

Object 数量只能由雷达声明,不能由 MCU 推测。

在主流量产设计中,雷达会在 Object List Header 报文中明确给出:

Header 字段 含义
Measurement Cycle Counter 本次感知周期编号
Object Count 本周期有效 Object 数
Timestamp 雷达时间基准
Alive Counter 功能安全
CRC 报文完整性

当 MCU 接收到 Header 后,会立即建立本周期的"期望模型":

c 复制代码
current_cycle_id   = header.cycle_counter;
expected_obj_num   = header.object_count;
received_obj_num   = 0;

从这一刻开始,MCU 不再是"被动接收 CAN 帧",

而是进入一种验证雷达声明是否成立的状态。


3. Object List 在 MCU 内部是如何被逐步拼装的

3.1 拼装的基本原则

MCU 内部的 Object List 拼装遵循三个非常工程化的原则:

  1. 以 Header 为周期起点
  2. 以 Object Count 作为完成条件
  3. 以周期一致性作为第一优先级

一个典型的拼装缓冲区如下:

c 复制代码
struct ObjectListBuffer {
    uint16_t cycle_id;
    uint8_t  expected_obj_num;
    uint8_t  received_obj_num;
    Object   objects[MAX_OBJ];
};

3.2 Object 数据如何进入缓冲区

每当 MCU 收到一帧 Object 数据 CAN FD 报文时,并不会立刻"处理 Object",而是:

  1. 校验该帧的 Cycle Counter 是否与当前周期一致
  2. 解析 Object Index / Slot
  3. 将 Object 数据写入对应位置
  4. 累加 received_obj_num

这一阶段的代码特征通常是:

  • 不做融合
  • 不做决策
  • 不触发算法

它的唯一目标是: 在 MCU 内部还原出雷达"本周期完整结果"的原始形态。


4. 一致性校验:为什么 MCU 宁可丢一个周期

received_obj_num == expected_obj_num 时,

很多新手会认为"Object List 已经完成了"。

但在工程上,这只是进入一致性校验的起点

4.1 常见校验项

校验项 工程意义
Cycle Counter 连续 防止周期交叉
Object Index 唯一 防止重复或覆盖
数量匹配 防止丢帧
周期超时 防止雷达或总线异常

4.2 为什么不能"部分使用"

假设雷达声明本周期有 20 个 Object,但 MCU 实际只收到了 18 个:

  • 这 2 个缺失目标,可能正好是前车或行人
  • 对 Fusion / Tracking 来说,这是语义错误,而不是精度下降

因此,量产系统中普遍采用的策略是:

只要 Object List 不完整,整个周期直接作废。

这是系统稳定性的底线,而不是保守设计。


5. Object List 是如何被 MCU 提供给上层消费的

当 Object List 通过一致性校验后,MCU 才会将其提交到"可消费区域"。
Fusion / Tracking Validated Buffer Assembler Fusion / Tracking Validated Buffer Assembler Commit Object List Read (周期触发) Stable Snapshot

这里有两个非常重要的工程设计选择:

5.1 消费是"周期驱动",而不是"CAN 驱动"

  • CAN 接收中断:高频、短路径
  • Object List 提交:低频、强语义

因此,MCU 通常会通过:

  • OS Task
  • Runnable
  • Event Flag

来触发上层算法,而不是在 CAN ISR 或 Rx 回调中直接调用

5.2 双缓冲几乎是标配

机制 目的
Double Buffer 避免读写冲突
Ring Buffer 支持延迟消费

这一步,决定了系统在高 CAN 负载和算法高耗时场景下是否还能稳定运行。


总结(工程视角)

可以用一句话总结整个流程:

CAN 帧只是进入 MCU 的数据碎片,
Object List 才是 MCU 向上层交付的"感知事实"。

雷达负责"声明世界",

MCU 负责"验证声明是否成立",

算法只面对稳定、完整、同一时刻的世界快照

相关推荐
yuanmenghao17 小时前
CAN系列 — (4) Radar Header 报文:为什么它是 MCU 感知周期的“锚点”
网络·单片机·自动驾驶·信息与通信
爱思德学术17 小时前
中国计算机学会(CCF)推荐学术会议-A(计算机网络):SIGCOMM 2026
计算机网络·信息与通信
飞睿科技17 小时前
乐鑫ESP32-S3-BOX-3,面向AIoT与边缘智能的新一代开发套件
人工智能·嵌入式硬件·esp32·智能家居·乐鑫科技
Y1rong17 小时前
STM32之SPI
stm32·单片机·嵌入式硬件
p666666666817 小时前
STM32(基于 ARM Cortex-M 内核)中函数调用栈帧的开辟 销毁过程
arm开发·stm32·嵌入式硬件
码咔吧咔17 小时前
DMA1和DMA2是什么?DMA总线与Dcode总线有区别?SDIO又是干嘛的,system干嘛的?总线矩阵干嘛的?
stm32·单片机·嵌入式硬件
WX1316951899817 小时前
音频分析仪APX525 APX515 APX528 APX526测试参数
科技·音视频·信息与通信
小郭团队17 小时前
未来PLC会消失吗?会被嵌入式系统取代吗?
c语言·人工智能·python·嵌入式硬件·架构
Aaron158817 小时前
全频段SDR干扰源模块设计
人工智能·嵌入式硬件·算法·fpga开发·硬件架构·信息与通信·基带工程