跳转到内容

Simulate CAN ​

Simulate CAN 是 EcuBus-Pro 的 软件虚拟 CAN 总线。不需要适配器、厂商 DLL 或 USB 设备。可在同一条虚拟网络上开发脚本、UDS 测试仪,以及 PC 端 AUTOSAR MCAL(Can.c)。

对应 ETAS VirtualCan:Peak / Kvaser / Vector 仍是真实硬件;Simulate 是进程内总线。

能力 ​

能力说明
通道64 个句柄:Simulate-0 … Simulate-63
协议CAN 与 CAN-FD
平台Windows、Linux、macOS(无需厂商 SDK)
EcuBus 功能DBC、Interactive、节点脚本、UDS、Trace
PC MCAL至少一个 Simulate 设备已打开时提供 JSON-RPC 2.0 TCP

虚拟总线 ​

每个已打开的 simulate 句柄都是同一条共享总线上的节点。

  • 在 Simulate-0 上发送的帧,会在其他已打开句柄(Simulate-1…)上作为 RX 接收。
  • 节点不会把自己的 TX 看成 RX。
  • 同一进程中同一句柄只能打开一次(BUS ALREADY INIT)。

典型布局:

EcuBus 工程:  Simulate-0   (测试仪 / 脚本 / Trace)
PC Can.c:     Simulate-1 … N   (虚拟 ECU,经 JSON-RPC 打开)
               └── 同一条虚拟总线 ──

Trace ​

EcuBus Trace 只显示工程里的设备。若工程只有 Simulate-0:

事件Simulate-0 上的 Trace
脚本 / Interactive / UDS 发送TX
Can.c 在 Simulate-1 上发送RX

Simulate-1 不是工程硬件节点,不会作为第二条 Trace 通道出现。

在 EcuBus 中使用 ​

  1. 硬件 → Simulate → 添加 CAN 节点。
  2. 选择空闲句柄(从 Simulate-0 开始)。
  3. 与其他厂商一样配置波特率 / CAN-FD。
  4. 按需绑定 DBC、Interactive、节点脚本或 UDS。

工程中两个不同句柄的节点(Simulate-0 与 Simulate-1)也会互相回环,适合两侧都是 EcuBus 脚本的场景。

PC AUTOSAR MCAL(JSON-RPC) ​

C 语言 Can.c 保持 AUTOSAR 签名(Can_Init、Can_Write、Can_MainFunction_Read 等),每次调用对应一次 JSON-RPC 请求。

[CanIf / CanTp / Com]
        |
    [Can.c]  -- TCP JSON-RPC -->  [已打开 Simulate-0 的 EcuBus]
                                        |
                                  Simulate-1 … N  (由 Can.c 打开)

TCP 服务器何时启动 ​

不会在应用启动时监听。

  • GUI: 工程启动且至少有一个 Simulate CAN 设备时开始监听;最后一个工程 simulate 关闭时停止。
  • CLI ecb_cli test: 打开工程里的全部设备。其中至少有一个 Simulate CAN 被打开时,该命令在运行期间监听。
  • CLI ecb_cli seq: 只打开该 tester 的 CAN 设备。仅当这个设备是 Simulate 时才监听。工程里另有 Simulate 节点、但本序列没用到它时,不会监听。

默认绑定:127.0.0.1:17320(主页 → 设置 → SIM-CAN)。监听地址/端口只是绑定配置,不会单独打开服务器。

Peak / Kvaser / Vector 不会出现在此 API 中。

句柄所有权 ​

谁句柄结果
EcuBus(工程)Simulate-0打开并持有
Can.c已被打开的 Simulate-0拒绝(already open)
Can.c空闲的 Simulate-1 … 63在同一进程中打开。controllerId 等于 handle
Can.DeInit只关闭 RPC 打开的句柄,绝不关闭工程的 Simulate-0

上表是常见实验布局:工程占用 Simulate-0。任意空闲句柄都可以。若工程使用 Simulate-5,Can.c 可以打开句柄 0。controllerId 始终等于该句柄。

sys.shutdown 关闭 Can.c 打开的控制器,TCP 监听保持不变。停止工程才会关闭端口。

先启动 EcuBus 工程(或 CLI seq/test),再连接 Can.c。

POSIX 示例见 resources/examples/mcal_can_rpc。它初始化 handle 1(以及可选的 2),而不是 handle 0。

线路格式 ​

  • 传输:TCP。
  • 分帧:NDJSON(一个 JSON 值 + \n)。也接受拼接 JSON 与 LSP Content-Length。
  • 规范:JSON-RPC 2.0,含批处理与通知(无 id)。
  • 仅命名参数(params 为对象)。

Can.Write 的 E_NOT_OK / CAN_BUSY 放在 result 中,不是 JSON-RPC error。

controllerId 就是 simulate 句柄。当 EcuBus 已占用 Simulate-0 时:

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "Can.Init",
  "params": {
    "controllers": [
      { "vendor": "simulate", "handle": 1, "name": "MCU" }
    ]
  }
}

省略 hardwareObjects 时的默认硬件对象:

  • HTH handle * 2 — BASIC 发送
  • HRH handle * 2 + 1 — BASIC 接收,标准 ID,全接收
  • HRH handle * 2 + 1000 — BASIC 接收,扩展 ID,全接收

AUTOSAR API 与 Can.* 方法一一对应(Can_Init → Can.Init,Can_Write → Can.Write,Can_MainFunction_* 等)。完整目录见 rpc.discover。

服务在监听时保持一条 TCP 连接。不要在每次成功的 Can_Write 上重连。

停止与重连 ​

停止工程会关闭 TCP 服务,并关闭 Can.c 打开的 simulate 句柄。这不是 CAN bus-off,也不是控制器模式变化。Can.c 不调用 CanIf_ControllerModeIndication 或 CanIf_ControllerBusOff。驱动保持 CAN_READY。监听未恢复时,Can_Write、Can_SetControllerMode、Can_GetControllerMode 和 Can_MainFunction_* 直接返回,不通知 CanIf。

CanGeneral/CanPcRpc 上的两个预编译参数:

参数默认含义
CanRpcAutoReconnecttrue监听恢复后,下一次 Can API 调用会重新连接
CanRpcReconnectIntervalMs500两次尝试的最小间隔(毫秒)。0 表示每次调用都重试。自动重连关闭时忽略

重连会用相同的句柄和硬件对象再次发送 Can.Init,然后恢复 CAN_CS_STARTED 或 CAN_CS_SLEEP。CAN_CS_STOPPED 已是 Can.Init 之后的状态。不通知 CanIf,因为该模式本来就是 CanIf 当前认为的模式。注入的错误状态不会保留;新会话从 Error Active 开始。Can_DeInit 不会重连。

错误注入 ​

只从节点脚本调用 injectCanError。节点上的 CAN 设备必须是 Simulate,Peak、Kvaser、Vector 等其他厂商会报错。设备就是这条虚拟总线,错误会加到这条总线上所有已打开的 Can.c 控制器。没有单独的 controller 参数。

ts
await injectCanError('BUSOFF')
await injectCanError('ACTIVE', { device: 'SIM0' })
状态默认计数CanIf
ACTIVETEC 0,REC 0无回调;模式不变
PASSIVETEC 128无回调;模式保持 CAN_CS_STARTED;收发仍可用
BUSOFFTEC 256只调用 CanIf_ControllerBusOff。模式不变。Can_Write 返回 E_NOT_OK。can.write 与 can.startPeriodSend 会被拒绝,已经在跑的周期发送也会停发

Bus-off 之后由 Can_SetControllerMode(CAN_CS_STOPPED) 产生 CanIf_ControllerModeIndication(STOPPED)。随后的 CAN_CS_STARTED 把错误状态清回 Active,并把计数清零。

不是什么 ​

  • 不是真实收发器时序、ACK 或错误帧。
  • 不是把 Peak / Kvaser / Vector 接到 RPC 上的网关。那些厂商仍是独立硬件。
  • 不要同时运行两个都会打开 simulate 且占用同一端口的 EcuBus 进程。