- CanBms: bcuCtrlCanId(0x10XX81FF) + buildBcuRelayCtrlData(02 00 总正 总负 FF*4) - SystemData: BcuCtrlCmd 下行队列(Web线程入队->Iterate/MOOS线程出队Notify) + 下发统计 - CCU: /api/bcu_ctrl(addr/action 或 pos/neg, 校验地址01h~36h) + Iterate 经 MOOS CAN_TX_0x* 下发 - pCanBridge 变双向透传: 订阅 CAN_TX_0x*,CanEndpoint::sendFrame(13字节CANET帧,TCP写,互斥保护) - 网页: 每BCU节点断路器闭合/断开按钮(confirm确认) + 下发统计卡片 - 测试: pccuTest 控制帧编码用例(183项);集成测试新增假CANET服务器验证完整下行链路(闭合/断开/非法地址)
176 lines
7.8 KiB
C++
176 lines
7.8 KiB
C++
#ifndef PCCU_CAN_BMS_H
|
||
#define PCCU_CAN_BMS_H
|
||
|
||
#include <cstdint>
|
||
|
||
namespace ccu {
|
||
|
||
//============================================================================
|
||
// 锂电池 BCU-MBMS CAN 协议(docs/04KT38电池BCU-MBMS通信(CAN)定义.docx)
|
||
//
|
||
// 数据来源:pCanBridge 透传的 MOOS 消息
|
||
// 变量名 CAN_0x%08X = CAN ID(扩展帧),m_sVal = 二进制数据域,
|
||
// m_dfVal2 = 原始帧信息字节。本模块只负责按报文 ID 解析数据域字段。
|
||
//
|
||
// 【节点地址】一个 MBMS 下最多挂 54 个 BCU,CAN ID 中间的 XX(01h~36h)
|
||
// 为 BCU 节点地址编号,其余位固定:
|
||
// 0x10XX00YY BCU 主动上报消息(YY=功能码 00/01/02/03/06/10)
|
||
// 0x10XX81FF MBMS 下发指令(继电器控制,经 MOOS CAN_TX_0x* 下行)
|
||
//
|
||
// 【下发指令 0x10XX81FF】数据域 8 字节(BYTE1~8 = byte0~7):
|
||
// byte0 = 0x02(索引号) byte1 = 0x00(索引号)
|
||
// byte2 = 总正继电器控制(1 闭合 / 0 断开)
|
||
// byte3 = 总负继电器控制(1 闭合 / 0 断开)
|
||
// byte4~7 = Reserve(填充 0xFF)
|
||
//
|
||
// 【上报报文】均为扩展帧,字段大端,BYTE1~8 对应数据域 byte0~7:
|
||
// 0x10XX0000 (200ms) 累加电压 u16@0 ÷10 V
|
||
// 回路电流 s16@2 ÷10-600 A(偏移 -600A,放电为正)
|
||
// SOC u16@4 ÷10 %
|
||
// 告警码 u8 @6(循环上报,协议未附码表,原样显示)
|
||
// 自检状态 u8 @7
|
||
// 0x10XX0001 (200ms) 最高单体电压 u16@0 mV,编号 u8@2
|
||
// 最低单体电压 u16@3 mV,编号 u8@5
|
||
// 单体平均电压 u16@6 mV
|
||
// 0x10XX0002 (1000ms) 最高单体温度 s8@0(偏移 -40℃),编号 u8@1
|
||
// 最低单体温度 s8@2(偏移 -40℃),编号 u8@3
|
||
// 单体平均温度 s8@4(偏移 -40℃,协议文档写"偏移0"
|
||
// 有误:实测原始值减 40 后才落在最低~最高区间内)
|
||
// 0x10XX0003 (200ms) 正极继电器状态 u8@0(1 闭合 / 0 断开)
|
||
// 负极继电器状态 u8@1(1 闭合 / 0 断开)
|
||
// 0x10XX0006 (200ms) 正极绝缘阻抗 u16@0 kΩ
|
||
// 负极绝缘阻抗 u16@2 kΩ
|
||
// 正负极端口电压 u16@4 ÷10 V
|
||
// 正极继电器外侧电压 u16@6 ÷10 V
|
||
// 0x10XX0010 (200ms) byte0~5 告警位(bit 定义见附录1,
|
||
// kBcuAlarmTable,可经 bcuAlarmTexts() 取告警描述)
|
||
// 0x10XX0004/0005 Reserve(调试预留,不解析)
|
||
//============================================================================
|
||
|
||
// BCU 节点地址范围:01h~36h(1~54)
|
||
static const int kBcuAddrMin = 0x01;
|
||
static const int kBcuAddrMax = 0x36;
|
||
static const int kBcuNodeCount = kBcuAddrMax - kBcuAddrMin + 1;
|
||
|
||
// BCU 上报报文功能码(CAN ID 低字节 YY)
|
||
enum BcuFunc : uint8_t {
|
||
BCU_FUNC_BASE = 0x00, // 0x10XX0000 电压 / 电流 / SOC / 告警码 / 自检
|
||
BCU_FUNC_CELL_V = 0x01, // 0x10XX0001 单体电压
|
||
BCU_FUNC_CELL_T = 0x02, // 0x10XX0002 单体温度
|
||
BCU_FUNC_RELAY = 0x03, // 0x10XX0003 继电器状态
|
||
BCU_FUNC_ISU = 0x06, // 0x10XX0006 绝缘阻值 / 端口电压
|
||
BCU_FUNC_ALARM = 0x10, // 0x10XX0010 告警位(附录1)
|
||
};
|
||
|
||
// 从 CAN ID 提取 BCU 节点地址(0x10XX00YY -> XX);非 BCU 报文格式返回 0
|
||
inline uint8_t bcuAddrOf(uint32_t canId) {
|
||
if ((canId & 0xFF00FF00u) != 0x10000000u) return 0;
|
||
uint8_t addr = static_cast<uint8_t>((canId >> 16) & 0xFF);
|
||
return (addr >= kBcuAddrMin && addr <= kBcuAddrMax) ? addr : 0;
|
||
}
|
||
|
||
// 从 CAN ID 提取功能码(0x10XX00YY -> YY)
|
||
inline uint8_t bcuFuncOf(uint32_t canId) {
|
||
return static_cast<uint8_t>(canId & 0xFF);
|
||
}
|
||
|
||
//--------------------------------------------------------------------------
|
||
// BCU 断路器(总正/总负继电器)下行控制
|
||
//--------------------------------------------------------------------------
|
||
|
||
// BCU 节点继电器控制指令 CAN ID(0x10XX81FF,XX=节点地址 01h~36h)
|
||
inline uint32_t bcuCtrlCanId(uint8_t addr) {
|
||
return 0x10000000u | (static_cast<uint32_t>(addr) << 16) | 0x81FFu;
|
||
}
|
||
|
||
// 编码继电器控制数据域(8 字节,经 MOOS CAN_TX_0x%08X 下发,pCanBridge 发送):
|
||
// [0]=0x02 [1]=0x00 [2]=总正(1闭合/0断开) [3]=总负 [4..7]=0xFF
|
||
// pos/neg 非 0 值均视为闭合(1)。
|
||
inline void buildBcuRelayCtrlData(int pos, int neg, uint8_t out[8]) {
|
||
out[0] = 0x02;
|
||
out[1] = 0x00;
|
||
out[2] = pos ? 0x01 : 0x00;
|
||
out[3] = neg ? 0x01 : 0x00;
|
||
out[4] = 0xFF;
|
||
out[5] = 0xFF;
|
||
out[6] = 0xFF;
|
||
out[7] = 0xFF;
|
||
}
|
||
|
||
// 是否为 BCU 主动上报报文 ID(0x10XX00YY,YY 为已定义功能码)
|
||
inline bool isCanBcuId(uint32_t canId) {
|
||
uint8_t addr = bcuAddrOf(canId);
|
||
if (!addr) return false;
|
||
switch (bcuFuncOf(canId)) {
|
||
case BCU_FUNC_BASE:
|
||
case BCU_FUNC_CELL_V:
|
||
case BCU_FUNC_CELL_T:
|
||
case BCU_FUNC_RELAY:
|
||
case BCU_FUNC_ISU:
|
||
case BCU_FUNC_ALARM:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// 单个 BCU 节点最新状态(各报文字段按功能码部分更新,最终合成完整快照)
|
||
struct BcuNodeStatus {
|
||
// 0x10XX0000 基本信息
|
||
double totalVoltage = 0; // 累加电压 V
|
||
double current = 0; // 回路电流 A(放电为正,偏移 -600A 已折算)
|
||
double soc = 0; // SOC %
|
||
int alarmCode = 0; // 告警码(原始值,协议未附码表)
|
||
int selfCheck = 0; // 自检状态(原始值)
|
||
// 0x10XX0001 单体电压
|
||
double maxCellVoltage = 0; // 最高单体电压 V
|
||
int maxCellVoltageNo = 0; // 最高单体电压编号
|
||
double minCellVoltage = 0; // 最低单体电压 V
|
||
int minCellVoltageNo = 0; // 最低单体电压编号
|
||
double avgCellVoltage = 0; // 单体平均电压 V
|
||
// 0x10XX0002 单体温度
|
||
double maxCellTemp = 0; // 最高单体温度 ℃
|
||
int maxCellTempNo = 0; // 最高单体温度编号
|
||
double minCellTemp = 0; // 最低单体温度 ℃
|
||
int minCellTempNo = 0; // 最低单体温度编号
|
||
double avgCellTemp = 0; // 单体平均温度 ℃
|
||
// 0x10XX0003 继电器(1 闭合 / 0 断开)
|
||
int posRelay = 0;
|
||
int negRelay = 0;
|
||
// 0x10XX0006 绝缘 / 端口电压
|
||
double posInsulationKohm = 0; // 正极绝缘阻抗 kΩ
|
||
double negInsulationKohm = 0; // 负极绝缘阻抗 kΩ
|
||
double portVoltage = 0; // 正负极端口电压 V
|
||
double posRelayOuterVoltage = 0; // 正极继电器外侧电压 V
|
||
// 0x10XX0010 告警位(附录1,byte0~5)
|
||
uint8_t alarmBits[6] = {0, 0, 0, 0, 0, 0};
|
||
// 0x10XX0010 附加字节(协议未详列,原样保留)
|
||
int alarmExtraByte6 = 0;
|
||
int alarmExtraByte7 = 0;
|
||
|
||
// 元数据
|
||
uint32_t rxMask = 0; // 收到过的功能码位图(bit = BcuFunc)
|
||
double lastRxTime = 0; // 最近收到该节点任一报文的时刻(MOOSTime)
|
||
bool valid = false; // 是否收到过该节点报文
|
||
};
|
||
|
||
// 解析一帧 CAN 数据域;命中 BCU 上报报文返回 true,nodeAddr 为节点地址(1~54),
|
||
// 字段按功能码部分更新合并进 node。data/dlc 非法或非 BCU 报文返回 false。
|
||
bool decodeCanBcuFrame(uint32_t canId, const uint8_t* data, int dlc,
|
||
uint8_t& nodeAddr, BcuNodeStatus& node);
|
||
|
||
// 附录1:0x10XX0010 告警位定义表(byteIdx/bitIdx -> 告警描述),表尾以 byteIdx=0xFF 结束
|
||
struct BcuAlarmDesc {
|
||
uint8_t byteIdx;
|
||
uint8_t bitIdx;
|
||
const char* text;
|
||
};
|
||
extern const BcuAlarmDesc kBcuAlarmTable[];
|
||
|
||
// 收集节点当前置位的告警描述;返回条数(不超过 cap,texts 填描述指针)
|
||
int bcuAlarmTexts(const BcuNodeStatus& node, const char* texts[], int cap);
|
||
|
||
} // namespace ccu
|
||
|
||
#endif // PCCU_CAN_BMS_H
|