EMS 知识库
首页 / knowledge/代码解析/midware/inverter/parallel_comm

parallel_can.h

源文件路径:midware/inverter/parallel_comm/parallel_can.h 所属模块:midware/inverter/parallel_comm(并机通信 / CAN 通道) 代码行数:70

1. 文件职责

本文件是 EMS 并机 CAN 通道的协议字典:它把"主机 → 从机"和"从机 → 主机"两个方向上全部使用的 CAN 扩展帧 ID 用宏一一枚举出来,并定义了广播地址(0)与扩展 ID 的通信标识位。业务层(parallel.c)把要下发的功率指令写进 g_t_host_machine_running_info[] 字段;通信层(parallel_can.c)按本文件给出的 ID 逐帧组包发出,并在收帧时用 frame_id & 0xFFFFFF 反查这些 ID 决定拆包到哪个字段。因此本文件是"字段 ↔ CAN ID"映射的唯一权威来源,改任何一个宏都会同时影响发送与接收两侧。本文件只做宏定义与两个函数声明,不含代码,被 parallel.c(包含本头以使用 PARALLEL_MAX_NUM 相关的 CAN 语义)与 parallel_can.c 使用。

2. 关键数据结构与宏

名称类型说明
PARALLEL_BROADCAST_ADDR宏0,并机广播地址。主机占用 0 号地址,因此广播帧也等价于"主机发的、无人应答"的帧
PARALLEL_COMMUNICATION_ADDRESS_OFFSET宏0x10000000,CAN 扩展 ID 的"这是并机报文"标志位(bit 28)。收帧侧用 (frame_id & OFFSET) == FALSE 来过滤非并机帧
PARALLEL_HOST_MACHINE_NETWORKING_0X181宏0x181,主从机组网帧(数据帧):主机下发的"已给你分配地址"答复,也是从机侧的接收对象
PARALLEL_HOST_MACHINE_NETWORKING_0X201宏0x201,主从机组网帧(远程帧):主机周期性广播的"请未分配地址的从机报到";从机收到远程帧后回一个同 ID 的数据帧
PARALLEL_HOST_MACHINE_POWER_CONTROL_0X190宏0x190,从机功率控制指令(控制模式类):顺序控制模式、三相不平衡模式、BB 模式、油机使能、调频使能、逆变器开关机、BMS 关机
PARALLEL_HOST_MACHINE_POWER_CONTROL_0X191宏0x191,从机功率控制指令(DC 侧总量控制):DC 电池/逆变/电网总设定功率
PARALLEL_HOST_MACHINE_POWER_CONTROL_0X192宏0x192,从机功率控制指令(DC 侧三相控制):DC 三相电池功率 + 三相逆变功率
PARALLEL_HOST_MACHINE_POWER_CONTROL_0X195宏0x195,从机功率控制指令(AC 侧控制):AC 逆变总功率、AC 电池充/放总限值、强制充电使能
PARALLEL_HOST_MACHINE_POWER_CONTROL_0X196宏0x196,从机功率控制指令(AC 侧控制):AC 三相逆变功率
PARALLEL_HOST_MACHINE_POWER_CONTROL_0X197宏0x197,从机功率控制指令(AC 侧控制):AC 三相电池充/放限值与强制充电使能
PARALLEL_HOST_MACHINE_SET_CONTROL_PARAMETER_0X19A宏0x19A,设置逆变器控制参数:MPPT 百分比、N-N 短接检测、DRM 模式、备电使能
PARALLEL_HOST_MACHINE_SET_SAFETY_REGULATION_0X19B宏0x19B,设置从机并网参数:安规(safety)与安规子项(safesub)
PARALLEL_HOST_MACHINE_EMS_RUNNING_DATA_0X1C0宏0x1C0,主机 EMS 运行信息:当前只下发 EMS 升级标志字节
PARALLEL_FROM_MACHINE_NETWORKING_0X201宏0x201,主从机组网帧(数据帧):从机对远程帧的应答,携带设备 ID + MAC + 本机地址
PARALLEL_FROM_MACHINE_DATA_CHECK_0X202宏0x202,返回数据出错信息。全工程仅有此定义,parallel_can.c 与任何其它文件均未使用(见第 7 节)
PARALLEL_FROM_MACHINE_INVERTER_SPECIFICATION_0X220宏0x220,从机逆变器规格:额定输出/输入功率、额定电池充/放功率(各 2 字节)
PARALLEL_FROM_MACHINE_SAFETY_REGULATION_0X240宏0x240,从机并网参数。定义了但未被 parallel_can.c 处理(从机安规是主机下发的,见第 7 节)
PARALLEL_FROM_MACHINE_INVERTER_RUNNING_DATA_0X260 ~ 0X26A宏(11 个)从机逆变器运行信息分片:0x260 PV1/PV2 电压功率、0x261 PV3/PV4、0x262 PV 充电器 PV/电池功率(32 位)、0x263 电网 L1/L2 电压功率、0x264 电网 L3+总功率+频率、0x265 备电 L1/L2、0x266 备电 L3+总功率+频率、0x267 定义了但双方都未使用、0x268 逆变三相功率、0x269 逆变总功率+频率+工作模式+电池功率、0x26A 电池电压、电流、馈网标志
PARALLEL_FROM_MACHINE_BATTERY_INFORMATION_0X290宏0x290,从机电池信息:电池额定容量(32 位)
PARALLEL_FROM_MACHINE_BATTERY_RUNNING_DATA_0x2A0 ~ 0x2A2宏(3 个)从机电池运行信息:0x2A0 电池状态位+组数+SOC、0x2A1 母线电压+电流+电池功率(32 位)、0x2A2 电池最大充/放功率(各 32 位)
PARALLEL_FROM_MACHINE_EMS_RUNNING_DATA_0x2C0宏0x2C0,从机 EMS 运行信息:当前只上传从机 EMS 升级标志字节
parallel_can_comm_host_machine_handle函数声明主机角色下 CAN 通信主入口(parallel_can.c:184)
parallel_can_comm_from_machine_handle函数声明从机角色下 CAN 通信主入口(parallel_can.c:564)

3. 函数清单

本文件为纯头文件,不含任何函数定义,仅有 2 个函数声明:

函数名作用域说明
parallel_can_comm_host_machine_handle全局(声明)主机角色 CAN 通信:周期发组网远程帧、广播控制参数、逐机单播功率指令,并收帧解析从机数据、做 15 s 心跳超时判定
parallel_can_comm_from_machine_handle全局(声明)从机角色 CAN 通信:未组网时周期上报组网数据;已组网时应答远程帧并周期上报规格/电池/运行数据;收主机指令并做 15 s 心跳判定

两个函数均由 midware/inverter/parallel.c:1037/1041 在 parallel_can_comm_handle() 内按 u8_parallel_mode 分发调用。

4. 核心逻辑解析

本文件无执行代码,其"逻辑"是CAN 扩展帧 ID 的位域复用规则与收发 ID 的对称/不对称关系。

4.1 扩展 ID 的位域划分

结合 parallel_can.c:57-58(发送)与 parallel_can.c:335-340(接收)可还原出 29 位扩展 ID 的实际用途:

bit28      : 并机报文标志,恒为 1(= PARALLEL_COMMUNICATION_ADDRESS_OFFSET 0x10000000)
bit24-27   : 机器地址(send_id & 0xF),主机发时为 0(广播)或从机地址 i(单播)
bit0-23    : 基础 ID,取本文件定义的 0x181 / 0x190 / ... / 0x2C0

发送侧 parallel_can.c:57-58:

TxMsg->frame_id |= PARALLEL_COMMUNICATION_ADDRESS_OFFSET;   // 置 bit28
TxMsg->frame_id |= (send_id & 0xF) << 24;                   // 置 bit24-27

接收侧 parallel_can.c:335-337:

l_u8_parallel_comm_rx_addr = ((frame_id >> 24) & 0xF);                    // 取位 24-27
if (((frame_id & PARALLEL_COMMUNICATION_ADDRESS_OFFSET) == FALSE) ||      // bit28 必须为 1
    (l_u8_parallel_comm_rx_addr >= PARALLEL_MAX_NUM))  continue;          // 地址必须 < 16

之后用 frame_id & 0xFFFFFF 取基础 ID 做 switch 分派(parallel_can.c:345、parallel_can.c:369、parallel_can.c:776)。注意 & 0xFFFFFF 只保留 bit0-23,因此 bit24-27 的地址与 bit28 的标志被同时剥离,这是位域划分能成立的前提。

4.2 收发 ID 的对称关系

方向基础 ID帧类型周期位置
主机 → 广播0x201远程帧3500 msparallel_can.c:200-202
主机 → 广播0x190、0x19A、0x19B、0x1C0数据帧500 msparallel_can.c:211-255
主机 → 单播(逐台)0x191、0x192、0x195、0x196、0x197数据帧50 msparallel_can.c:273-326
从机 → 主机0x181(组网答复,主机发、从机收)数据帧主机收帧触发parallel_can.c:142-153
从机 → 主机0x201(组网上报)数据帧1000 ms(未组网时)/ 应答远程帧parallel_can.c:519-528、parallel_can.c:785
从机 → 主机0x220、0x290、0x2A0、0x2A1、0x2A2、0x2C0数据帧500 msparallel_can.c:593-657
从机 → 主机0x260、0x261、0x263、0x264、0x265、0x266、0x268、0x269、0x26A数据帧50 msparallel_can.c:664-761

三类不对称/空洞可直接从宏定义与实现对照看出:

  1. 0x201 是双向复用但语义相反:主机侧定义 PARALLEL_HOST_MACHINE_NETWORKING_0X201(远程帧请求),从机侧定义 PARALLEL_FROM_MACHINE_NETWORKING_0X201(数据帧应答),两个宏值相同。接收侧靠 frame_type == CAN_FT_REMOTE 区分(parallel_can.c:352、parallel_can.c:783)。
  2. 0x181 的方向注释是错的:宏名叫 PARALLEL_HOST_MACHINE_NETWORKING_0X181("主机"),但它在 parallel_can.c:779(从机侧接收 switch)和 parallel_can.c:347(主机侧接收 switch,注释写"多主机")里都出现在接收分支。实际方向是"主机 → 从机"的地址分配答复,所以名字里的 HOST 表示"由主机发出",而 0x201 的 HOST/FROM 两个宏则表示"主机请求 / 从机应答"——命名体系不自洽。
  3. 0x202(返回数据出错信息)、0x267(从机逆变器运行信息)、0x240(从机并网参数)三个宏全工程无使用。0x262(PV 充电器 PV/电池功率)主机侧有解析(parallel_can.c:397)但从机侧从不发送。这五处构成"定义了协议但未实现"的空洞。

4.3 载荷格式约定(无长度冗余)

从 parallel_can.c 的组帧可见所有并机 CAN 帧都是固定 8 字节数据域(frame_len = 8),无长度字段、无功能码:字段语义完全由 ID 决定,字段排列为大端(>> 8 高字节在前,>>24/16/8/0 四字节大端)。这一约定由 hardware/can/can1.h 的 CAN_MSG_TYPEDEF_T(frame_id / frame_type / frame_len / frame_data[8])承载,本文件不重复定义结构体。

校验上分两类:

5. 对外接口

5.1 本文件导出

5.2 使用方

使用方用途
midware/inverter/parallel_comm/parallel_can.c:13包含本头,全部 ID 宏的实际使用者(发送组帧 + 接收 switch 分派)
midware/inverter/parallel.c:15包含本头,仅为调用两个 parallel_can_comm_* 函数入口

5.3 本文件依赖

5.4 相关但不在本文件的外部符号

parallel_can.c 使用了以下不在本头文件声明的符号:

符号定义位置
CAN_MSG_TYPEDEF_Thardware/can/can0.h:20-28(parallel_can.c 经 CAN1.h/includes.h 获得)
CAN_FT_DATA / CAN_FT_REMOTEHALLIB/GD32F4xx_standard_peripheral/Include/gd32f4xx_can.h:673-674
can1_send_exten_pack / get_can1_exten_packhardware/can/can1.h:26,30
PARALLEL_MAX_NUM、g_t_host_machine_*、g_t_from_machine_*midware/inverter/parallel.h、midware/inverter/parallel.c
GetCrcCode_8_MAXIMcommon/crc.h

6. 依赖关系

7. 备注与风险点

  1. 三个宏定义后从未使用(死代码):
    • PARALLEL_FROM_MACHINE_DATA_CHECK_0X202(第 37 行)——"返回数据出错信息",全工程仅有此一处定义,无发送方也无接收方。协议层预留但未落地,或已被数据帧的隐式 CRC 取代。
    • PARALLEL_FROM_MACHINE_INVERTER_RUNNING_DATA_0X267(第 50 行)——主机侧接收 switch(parallel_can.c:369-479)中没有 0x267 分支,从机组帧(parallel_can.c:664-761)也不发 0x267。ID 被跳过。
    • PARALLEL_FROM_MACHINE_SAFETY_REGULATION_0X240(第 41 行)——注释是"从机并网参数",但实际方向是主机用 0x19B 下发给从机,从机从不回报安规。这个 ID 的存在会让读者误以为有从机安规上报通道。
  1. 0x262 只收不发,形成"孤儿接收分支":parallel_can.c:397-402 会解析 0x262 帧填充 s32_Ppv_pvcharger / s32_Pbat_pvcharger,但 parallel_can.c:664-761 的从机发送逻辑没有任何一帧使用 0x262。同时 parallel.c:209-210 把本机的这两个字段硬置 0,说明该数据源在 CAN 通道上事实上不可用。
  1. 0x201 双向复用导致头文件命名误导。PARALLEL_HOST_MACHINE_NETWORKING_0X201(第 21 行,注释"主从机组网帧(远程帧)")与 PARALLEL_FROM_MACHINE_NETWORKING_0X201(第 36 行,注释"主从机组网帧(数据帧)")是同一个 ID。任何按名字判断"哪一个 ID 是主机发的"的读者都会误判方向;区分只能靠 frame_type。同理 0x181 被归在"主机 CAN ID"段却由主机发出、从机接收,命名与语义方向不一致。
  1. 缺少"从机数据帧无校验"的一致性说明。组网帧带 CRC8/MAXIM,数据帧不带;本头文件对 ID 的注释只描述内容不描述校验,读者必须读 parallel_can.c 才能发现这个差异。建议在头文件里对两类帧明确标注校验方式。
  1. PARALLEL_COMMUNICATION_ADDRESS_OFFSET 与地址掩码的耦合未文档化。0x10000000 的注释只写"通讯地址偏移",没有说明它是"并机报文标志位"以及"地址在 bit24-27"这一分层。收帧侧如果只写 frame_id & 0xFFFFFF 而不先检查 bit28,就会把其它模块发的 0x190 等 ID 误判为并机帧——parallel_can.c:336 恰好有这个检查,但规则未在头文件中固化,新增收发点容易遗漏。
  1. 头文件包含 chip.h 但自身不需要。本文件通篇只有宏和两个 void f(void) 声明,不依赖 chip.h 的任何类型。该 include 会让任何只想要 ID 宏的文件被迫引入整个 chip.h,增加编译耦合与循环包含风险。
  1. ID 空间未做区间保护。0x1C0(主机 EMS 上报)与 0x2C0(从机 EMS 上报)相距 0x100,看起来是"主机段 0x1xx / 从机段 0x2xx"的划分,但 0x201 同时出现在两段(第 21 行与第 36 行),破坏了这一规律。若将来需要按段批量过滤(例如只接收 0x2xx),会因为 0x201 而被误伤。