# GB/T + J1939 Debug Flow (CAN ExtId) Документ для ручного дебага обмена EV <-> EVSE по CAN (J1939 TP + short PGN). ## 1) Базовая структура CAN Extended ID (29-bit) В проекте используется формула: - `ExtId = (priority << 26) | (PGN << 8) | (SA << 8) | DA` Где: - `priority` — обычно `6` или `7` - `PGN` — Parameter Group Number - `SA` — Source Address - `DA` — Destination Address Адреса в ваших прошивках: - `EVSE (SE)` = `0x56` - `EV` = `0xF4` Примеры: - `0x181056F4` -> short PGN `0x1000` (BCL), `SA=0x56`, `DA=0xF4` - `0x1CEC56F4` -> TP.CM от `0x56` к `0xF4` - `0x1CECF456` -> TP.CM от `0xF4` к `0x56` - `0x1CEB56F4` -> TP.DT от `0x56` к `0xF4` ## 2) Какие PGN short, какие TP Short (<=8 байт, один CAN кадр): - `0x0900` BRO - `0x0A00` CRO - `0x1000` BCL (5 байт) - `0x1200` CCS - `0x1300` BSM (7 байт) - `0x1A00` CST Через TP (>8 байт): - `0x0200` BRM (49 байт) - `0x0600` BCP (13 байт) - `0x1100` BCS (9 байт) ## 3) Нормальная последовательность (высокоуровнево) 1. Handshake/recognition: - CHM/CRM/BRM/BCP/CML/BRO/CRO 2. Переход в заряд: - EVSE `S8 -> S9` - EV начинает слать BCL/BSM/BCS - EVSE принимает BCL и переходит `S9 -> S10` 3. Во время зарядки: - EV регулярно шлет: - BCL (short) - BSM (short) - BCS (TP, `PGN=0x1100`) - EVSE регулярно шлет CCS ## 4) Нормальная TP-сессия для BCS (`PGN=0x1100`, size=9, packets=2) ### Шаг 1: RTS (originator -> responder) ID: - от EV к EVSE: `1CEC F4 56` (`0x1CECF456`) Data (TP.CM_RTS): - `byte0 = 0x10` (RTS) - `byte1..2 = total_size` (LSB/MSB), для BCS: `0x09 0x00` - `byte3 = total_packets`, для BCS: `0x02` - `byte4 = max_packets_per_CTS` (часто `0x02`) - `byte5..7 = PGN` в little-endian (`00 11 00` для `0x1100`) ### Шаг 2: CTS (responder -> originator) ID: - от EVSE к EV: `1CEC 56 F4` (`0x1CEC56F4`) Data (TP.CM_CTS): - `byte0 = 0x11` (CTS) - `byte1 = allowed_packet_count` - `byte2 = next_packet_number` (обычно `1` для новой сессии) - `byte3..4 = 0xFF` - `byte5..7 = PGN` (`00 11 00`) ### Шаг 3: DT (originator -> responder) ID: - `1CEB F4 56` (EV -> EVSE) Data (TP.DT): - `byte0 = seq` (`1`, потом `2`) - `byte1..7 = payload chunk` Для 9 байт: - DT#1 несет первые 7 байт - DT#2 несет оставшиеся 2 байта + заполнение `0xFF` ### Шаг 4: ACK (responder -> originator) ID: - `1CEC 56 F4` (EVSE -> EV) Data (TP.CM_EndOfMsgACK): - `byte0 = 0x13` (ACK) - `byte1..2 = total_size` (`09 00`) - `byte3 = total_packets` (`02`) - `byte4 = 0xFF` - `byte5..7 = PGN` (`00 11 00`) ## 5) Как понять по логу, что сессия "правильная" Для каждого `RTS(0x1100)` должен быть полный шаблон: - `RTS` -> `CTS` -> `DT #1` -> `DT #2` -> `ACK` Если есть `RTS`, но нет `CTS`: - проблема на стороне responder (EVSE) TX/фильтр/перегрузка Если есть `CTS`, но нет `DT`: - проблема на стороне originator (EV) RX/парсинг/состояние Если есть `DT`, но нет `ACK`: - проблема на стороне responder reassembly/timeout ## 6) Поля основных GB/T пакетов (payload) ### BCL (`PGN 0x1000`, short, 5 bytes) Структура: - `requestedVoltage` (`uint16`, 0.1V/bit) - `requestedCurrent` (`uint16`, 0.1A/bit, в вашем коде может интерпретироваться как `4000 - value`) - `chargingMode` (`uint8`, `0x01` CV, `0x02` CC) ### BCS (`PGN 0x1100`, TP, 9 bytes) Структура: - `measuredChargingVoltage` (`uint16`) - `measuredChargingCurrent` (`uint16`) - `highestVoltageOfBatteryCell` (`uint16`) - `currentChargeState` (`uint8`) - `estimatedRemainingChargingTime` (`uint16`) ### BSM (`PGN 0x1300`, short, 7 bytes) Структура: - max/temperature индексы и статусы: - `singleBatteryHighestVoltageSerNo` - `batteryHighestTemp` - `batteryHighestTempSerNo` - `batteryLowestTemp` - `batteryLowestTempSerNo` - `batteryCellVoltageState` - `batteryStatus` ## 7) Тайминги TP из J1939 (важное для дебага) Ключевые reference значения: - `Tr = 200 ms` - `Th = 500 ms` - `T1 = 750 ms` - `T2 = 1250 ms` - `T3 = 1250 ms` - `T4 = 1050 ms` Практически: - если responder выдал CTS, originator не должен задерживать DT дольше допусков - если originator отправил RTS/DT, responder должен ответить CTS/ACK в окне таймаутов ## 8) Мини-чеклист при "вдруг стопнулось" 1. Найти последний `RTS` по `PGN=0x1100`. 2. Проверить, был ли `CTS` на шине с тем же `PGN`. 3. Проверить наличие `DT#1/#2`. 4. Проверить `ACK`. 5. Если цепочка оборвалась: - зафиксировать на каком шаге; - сопоставить с UART логом state machine (`S9/S10`, `TP timeout`, `BCS timeout`).