Update firmware version to 1.0.10, add hv_tick parameter to PSU control, enhance serial control with response handling, and improve stop button control logic.

This commit is contained in:
2026-04-13 20:01:44 +03:00
parent 14b4f0595f
commit c59d150b23
21 changed files with 25914 additions and 25379 deletions
+3 -3
View File
@@ -41,9 +41,9 @@ extern "C" {
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
#define FW_VERSION_MAJOR 0x01
#define FW_VERSION_MINOR 0x00
#define FW_VERSION_PATCH 0x02
#define FW_VERSION_MAJOR 1
#define FW_VERSION_MINOR 0
#define FW_VERSION_PATCH 10
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
+1
View File
@@ -88,6 +88,7 @@ typedef struct {
// Дополнительные параметры для одного модуля DC30
uint32_t power_limit; // лимит мощности [кВт]
uint8_t hv_mode; // HV-режим (ограничение напряжения)
uint32_t hv_tick; // таймер для задержки входа в HV-режим
uint32_t tempAmbient; // температура окружающего воздуха (из PSU_04)
union { uint8_t raw; PSU_Status0_t bits; } status0; // modularForm0
+7 -5
View File
@@ -11,13 +11,15 @@ void CCS_Init(void);
void CCS_SendEmergencyStop(void);
void CCS_SendStart(void);
void CCS_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size);
void CCS_RxArm(void);
typedef enum {
CCS_DISABLED = 0,
CCS_UNPLUGGED = 1,
CCS_AUTH_REQUIRED = 2,
CCS_CONNECTED = 3,
CCS_REPLUGGING = 4,
CCS_UNKNOWN = 0,
CCS_DISABLED = 1,
CCS_UNPLUGGED = 2,
CCS_AUTH_REQUIRED = 3,
CCS_CONNECTED = 4,
CCS_REPLUGGING = 5,
} CCS_ConnectorState_t;
typedef enum {
+4
View File
@@ -159,6 +159,10 @@ struct SerialControl_t {
// Переменные для передачи команды
volatile ReceivedCommand_t received_command;
volatile uint8_t command_ready;
volatile uint8_t response_pending;
volatile uint8_t response_code;
volatile uint8_t rx_error_pending;
volatile uint32_t rx_error_code;
// Время отправки последнего пакета
volatile uint32_t tx_tick;
+2 -2
View File
@@ -95,8 +95,8 @@ void Init_Peripheral(){
RELAY_Write(RELAY3, 0);
RELAY_Write(RELAY_DC, 0);
RELAY_Write(RELAY_AC, 0);
RELAY_Write(RELAY_CP, 1);
RELAY_Write(RELAY_CC, 1);
RELAY_Write(RELAY_CP, 0);
RELAY_Write(RELAY_CC, 0);
RELAY_Write(RELAY_DC1, 0);
SMAFilter_Init(&conn_temp_adc_filter[0]);
+1 -10
View File
@@ -42,16 +42,7 @@ void CONN_Task(){
/* CCS state machine is handled in serial.c.
* Keep this task lightweight for scheduler compatibility.
*/
if (CONN.chargingError != CONN_NO_ERROR) {
CONN_SetState(Disabled);
return;
}
if (connectorState == Unknown) {
CONN_SetState(Unplugged);
} else if (connectorState == Disabled && CONN.chargingError == CONN_NO_ERROR) {
CONN_SetState(Unplugged);
}
return;
}
void CONN_SetState(CONN_State_t state){
-215
View File
@@ -148,218 +148,3 @@ int log_printf(LogLevel_t level, const char *format, ...)
return result;
}
#ifndef USE_WEB_INTERFACE
extern UART_HandleTypeDef huart2;
uint8_t debug_rx_buffer[256];
uint8_t debug_cmd_received;
uint8_t debug_rx_buffer_size = 0;
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
// if(huart->Instance == USART1){
// mm_rx_interrupt(huart, Size);
// }
if(huart->Instance == USART2){
debug_rx_interrupt(huart, Size);
}
}
void debug_rx_interrupt(UART_HandleTypeDef *huart, uint16_t Size){
debug_rx_buffer[Size] = '\0';
debug_rx_buffer_size = Size;
debug_cmd_received = 1;
}
void debug_init(){
HAL_UARTEx_ReceiveToIdle_IT(&huart2,debug_rx_buffer,255);
}
void parse_command(uint8_t* buffer, size_t length) {
// ignore \r \n symbols
size_t i = 0;
for (i = 0; i < length; i++) {
if (buffer[i] == '\r' || buffer[i] == '\n') {
buffer[i] = '\0';
length = i;
break;
}
}
if (buffer[0] == 0) return;
if (strncmp((const char*)buffer, "reset", length) == 0) {
log_printf(LOG_INFO, "Resetting...\n");
NVIC_SystemReset();
} else if (strncmp((const char*)buffer, "relayaux", length) == 0) {
log_printf(LOG_INFO, "Relaying...\n");
RELAY_Write(RELAY_AUX, 1);
HAL_Delay(2000);
RELAY_Write(RELAY_AUX, 0);
} else if (strncmp((const char*)buffer, "relaycc", length) == 0) {
log_printf(LOG_INFO, "Relaying...\n");
RELAY_Write(RELAY_CC, 1);
HAL_Delay(200);
RELAY_Write(RELAY_CC, 0);
} else if (strncmp((const char*)buffer, "relaydc", length) == 0) {
log_printf(LOG_INFO, "Relaying...\n");
RELAY_Write(RELAY_DC, 1);
HAL_Delay(200);
RELAY_Write(RELAY_DC, 0);
} else if (strncmp((const char*)buffer, "relayac", length) == 0) {
log_printf(LOG_INFO, "Relaying...\n");
RELAY_Write(RELAY_AC, 1);
HAL_Delay(200);
RELAY_Write(RELAY_AC, 0);
} else if (strncmp((const char*)buffer, "adc", length) == 0) {
log_printf(LOG_INFO, "CC1=%.2f\n", CONN_CC_GetAdc());
} else if (strncmp((const char*)buffer, "lock_state", length) == 0) {
log_printf(LOG_INFO, "Lock state=%d\n", GBT_LockGetState());
} else if (strncmp((const char*)buffer, "lock_lock", length) == 0) {
log_printf(LOG_INFO, "Locked\n");
GBT_Lock(1);
} else if (strncmp((const char*)buffer, "lock_unlock", length) == 0) {
log_printf(LOG_INFO, "Unlocked\n");
GBT_Lock(0);
} else if (strncmp((const char*)buffer, "complete", length) == 0) {
CONN_SetState(Finished);
} else if (strncmp((const char*)buffer, "start", length) == 0) {
log_printf(LOG_INFO, "Started\n");
GBT_Start();
} else if (strncmp((const char*)buffer, "stop", length) == 0) {
log_printf(LOG_INFO, "Stopped\n");
GBT_StopEVSE(GBT_CST_SUSPENDS_ARTIFICIALLY);
} else if (strncmp((const char*)buffer, "stop1", length) == 0) {
log_printf(LOG_INFO, "Stopped\n");
GBT_ForceStop();
// } else if (strncmp((const char*)buffer, "force", length) == 0) {
// log_printf(LOG_INFO, "Stopped\n");
// GBT_Lock(1);
// GBT_SwitchState(GBT_S2_LOCKED);
// GBT_Delay(500);
} else if (strncmp((const char*)buffer, "cc_state", length) == 0) {
switch(CONN_CC_GetState()){
case GBT_CC_UNKNOWN:
log_printf(LOG_INFO, "GBT_CC_UNKNOWN\n");
break;
case GBT_CC_12V:
log_printf(LOG_INFO, "GBT_CC_12V\n");
break;
case GBT_CC_6V:
log_printf(LOG_INFO, "GBT_CC_6V\n");
break;
case GBT_CC_4V:
log_printf(LOG_INFO, "GBT_CC_4V\n");
break;
case GBT_CC_2V:
log_printf(LOG_INFO, "GBT_CC_2V\n");
break;
}
} else if (strncmp((const char*)buffer, "temp", length) == 0) {
log_printf(LOG_INFO, "temp1 %d\n",GBT_ReadTemp(0));
log_printf(LOG_INFO, "temp2 %d\n",GBT_ReadTemp(1));
} else if (strncmp((const char*)buffer, "info1", length) == 0) {
log_printf(LOG_INFO, "Battery info:\n");
log_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); // 0.01v/bit
log_printf(LOG_INFO, "maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); // 0.1A/bit
log_printf(LOG_INFO, "totE %dkWh\n",GBT_BATStat.totalEnergy/10); // 0.1kWh
log_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); // 0.1V/ bit
log_printf(LOG_INFO, "maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); // 1C/bit, -50C offset
log_printf(LOG_INFO, "SOC %dp\n",GBT_BATStat.SOC/10); // 0.1%/bit , 0..100%
log_printf(LOG_INFO, "Volt. %dV\n",GBT_BATStat.measVoltage/10); // 0.1V/bit
} else if (strncmp((const char*)buffer, "info2", length) == 0) {
log_printf(LOG_INFO, "EV info:\n");
log_printf(LOG_INFO, "GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]);
log_printf(LOG_INFO, "Battery type: %d\n",GBT_EVInfo.batteryType);
log_printf(LOG_INFO, "Battery capacity: %d\n", GBT_EVInfo.batteryCapacity); // 0.1Ah/bit
log_printf(LOG_INFO, "Battery voltage: %d\n", GBT_EVInfo.batteryVoltage); // 0.1V/bit
log_printf(LOG_INFO, "Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); // Battery vendor (ASCII string)
log_printf(LOG_INFO, "Battery SN: %lu\n", GBT_EVInfo.batterySN); // int
log_printf(LOG_INFO, "Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985); // year (offset 1985)
log_printf(LOG_INFO, "Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t
log_printf(LOG_INFO, "Own auto: %d\n", GBT_EVInfo.ownAuto); // 0 = lizing, 1 = own auto
log_printf(LOG_INFO, "EVIN: %.17s\n", GBT_EVInfo.EVIN); //EVIN
log_printf(LOG_INFO, "EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER);
} else if (strncmp((const char*)buffer, "info3", length) == 0) {
log_printf(LOG_INFO, "GBT_MaxLoad info:\n");
log_printf(LOG_INFO, "Output max current: %d\n",GBT_MaxLoad.maxOutputCurrent);
log_printf(LOG_INFO, "Output min current: %d\n",GBT_MaxLoad.minOutputCurrent);
log_printf(LOG_INFO, "Output max voltage: %d\n",GBT_MaxLoad.maxOutputVoltage);
log_printf(LOG_INFO, "Output min voltage: %d\n",GBT_MaxLoad.minOutputVoltage);
log_printf(LOG_INFO, "\nGBT_ChargerInfo info:\n");
log_printf(LOG_INFO, "BMS Recognized: %d\n",GBT_ChargerInfo.bmsIdentified);
log_printf(LOG_INFO, "Charger location: %.3s\n",GBT_ChargerInfo.chargerLocation);
log_printf(LOG_INFO, "Charger number: %lu\n",GBT_ChargerInfo.chargerNumber);
} else if (strncmp((const char*)buffer, "help", length) == 0) {
log_printf(LOG_INFO, "Command list:\n");
log_printf(LOG_INFO, "reset\n");
log_printf(LOG_INFO, "help\n");
log_printf(LOG_INFO, "cc_state\n");
log_printf(LOG_INFO, "lock_lock\n");
log_printf(LOG_INFO, "lock_unlock\n");
log_printf(LOG_INFO, "lock_state\n");
log_printf(LOG_INFO, "adc\n");
log_printf(LOG_INFO, "relay(cc,aux,ac,dc)\n");
log_printf(LOG_INFO, "start\n");
log_printf(LOG_INFO, "stop\n");
log_printf(LOG_INFO, "stop1\n");
// log_printf(LOG_INFO, "force\n");
log_printf(LOG_INFO, "temp\n");
log_printf(LOG_INFO, "info1\n");
log_printf(LOG_INFO, "info2\n");
log_printf(LOG_INFO, "info3\n");
log_printf(LOG_INFO, "time\n");
log_printf(LOG_INFO, "cantest\n");
//TODO: info commands
} else if (strncmp((const char*)buffer, "time", length) == 0) {
time_t unix_time = (time_t)get_Current_Time();
struct tm *parts = localtime(&unix_time);
log_printf(LOG_INFO, "Year: %d\n", parts->tm_year + 1900);
log_printf(LOG_INFO, "Month: %d\n", parts->tm_mon + 1);
log_printf(LOG_INFO, "Day: %d\n", parts->tm_mday);
log_printf(LOG_INFO, "Hour: %d\n", parts->tm_hour);
log_printf(LOG_INFO, "Minute: %d\n", parts->tm_min);
log_printf(LOG_INFO, "Second: %d\n", parts->tm_sec);
} else if (strncmp((const char*)buffer, "cantest", length) == 0) {
//GBT_SendCHM();
GBT_Error(0xFDF0C0FC); //BRM Timeout
log_printf(LOG_INFO, "can test\n");
} else {
log_printf(LOG_INFO, "Unknown command\n");
}
}
void debug_task(){
if(debug_cmd_received){
parse_command(debug_rx_buffer, debug_rx_buffer_size);
HAL_UARTEx_ReceiveToIdle_IT(&huart2,debug_rx_buffer,255);
debug_cmd_received = 0;
}
}
#else
#endif // USE_WEB_INTERFACE
+36 -5
View File
@@ -96,6 +96,7 @@ void ED_Delay(uint32_t Delay)
while ((HAL_GetTick() - tickstart) < wait){
CCS_SerialLoop();
StopButtonControl();
// CP_Loop();
CONN_Task();
LED_Task();
@@ -104,12 +105,44 @@ void ED_Delay(uint32_t Delay)
}
void StopButtonControl(){
static uint32_t tick;
static uint32_t hold_time;
static uint8_t stop_btn_fault = 1;
uint32_t now = HAL_GetTick();
//Charging do nothing
if(!IN_ReadInput(IN_ESTOP)){
CONN.connControl = CMD_STOP;
/* Run no faster than once per 10 ms. */
if((now - tick) < 10){
return;
}
tick = now;
uint8_t pressed = !IN_ReadInput(IN_ESTOP);
if(!pressed){
stop_btn_fault = 0;
}
if(stop_btn_fault){
return;
}
if(pressed){
if(hold_time == 0){
CONN.connControl = CMD_STOP;
}
hold_time += 10;
if(hold_time == 5000){
CONN.connControl = CMD_FORCE_UNLOCK;
}
if(hold_time > 40000){
SC_SendPacket(NULL, 0, RESP_SUCCESS);
while(huart2.gState == HAL_UART_STATE_BUSY_TX);
HAL_Delay(10);
NVIC_SystemReset();
}
}
else{
hold_time = 0;
}
}
uint8_t temp0, temp1;
@@ -202,8 +235,6 @@ int main(void)
CONN_Loop();
LED_Write();
ED_Delay(10);
StopButtonControl();
ED_Delay(50);
}
/* USER CODE END 3 */
+11 -1
View File
@@ -149,6 +149,7 @@ void PSU_Init(){
PSU0.power_limit = PSU_MAX_POWER; // kW
PSU0.hv_mode = 0;
PSU0.hv_tick = 0;
PSU_Enable(0, 0);
}
@@ -265,7 +266,15 @@ void PSU_ReadWrite(){
if(PSU0.ready){
PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
ED_Delay(CAN_DELAY);
if(CONN.MeasuredVoltage>490) PSU0.hv_mode = 1;
if(CONN.MeasuredVoltage > 490){
if(PSU0.hv_tick == 0){
PSU0.hv_tick = HAL_GetTick();
}else if((HAL_GetTick() - PSU0.hv_tick) >= 10000){
PSU0.hv_mode = 1;
}
}else{
PSU0.hv_tick = 0;
}
}
// PSU_SetHVMode(0, PSU0.hv_mode); // auto set, no need
@@ -339,6 +348,7 @@ void PSU_Task(void){
case PSU_READY:
// модуль готов, но выключен
PSU0.hv_mode = 0;
PSU0.hv_tick = 0;
RELAY_Write(RELAY_DC, 0);
if(!PSU0.ready){
+28 -10
View File
@@ -2,6 +2,7 @@
#include "main.h"
#include "string.h"
#include "charger_control.h"
#include "board.h"
#include "tim.h"
@@ -10,11 +11,20 @@ RGB_Cycle_t LED_Cycle;
RGB_Cycle_t color_estop = {
.Color1 = { .R = 250, .G = 0, .B = 0 },
.Color2 = { .R = 250, .G = 0, .B = 0 },
.Tr = 50,
.Th = 50,
.Tf = 50,
.Tl = 50,
.Color2 = { .R = 0, .G = 0, .B = 0 },
.Tr = 10,
.Th = 5,
.Tf = 10,
.Tl = 5,
};
RGB_Cycle_t color_unlock = {
.Color1 = { .R = 255, .G = 0, .B = 0 },
.Color2 = { .R = 0, .G = 0, .B = 0 },
.Tr = 10,
.Th = 10,
.Tf = 10,
.Tl = 10,
};
RGB_Cycle_t color_unknown = {
@@ -54,12 +64,12 @@ RGB_Cycle_t color_unplugged = {
};
RGB_Cycle_t color_preparing = {
.Color1 = { .R = 0, .G = 0, .B = 250 },
.Color2 = { .R = 0, .G = 0, .B = 250 },
.Tr = 50,
.Color1 = { .R = 0, .G = 0, .B = 255 },
.Color2 = { .R = 0, .G = 0, .B = 0 },
.Tr = 10,
.Th = 10,
.Tf = 50,
.Tl = 0,
.Tf = 10,
.Tl = 10,
};
RGB_Cycle_t color_charging = {
@@ -94,6 +104,14 @@ void LED_Write(){
LED_SetColor(&color_error);
return;
}
if(CONN.connControl == CMD_FORCE_UNLOCK){
LED_SetColor(&color_unlock);
return;
}
if(CONN.connControl == CMD_STOP){
LED_SetColor(&color_estop);
return;
}
switch(CONN.connState){
case Unknown:
LED_SetColor(&color_unknown);
+81 -14
View File
@@ -9,6 +9,7 @@
#include "psu_control.h"
extern UART_HandleTypeDef huart3;
extern uint8_t config_initialized;
static void send_state(void);
static void CCS_SendResetReason(void);
@@ -28,9 +29,13 @@ uint8_t ev_enable_output = 0;
#define MAX_TX_BUFFER_SIZE 256
#define MAX_RX_BUFFER_SIZE 256
/* Everest requests 500 V → БП реально 300 V / 1 A, в STATE отдаём 500 V. */
#define FAKE_EVREQ_VOLTAGE_V 500u
#define FAKE_PSU_VOLTAGE_V 300u
#define FAKE_PSU_CURRENT_0P1A 10u
static uint8_t rx_buffer[MAX_RX_BUFFER_SIZE];
static uint8_t tx_buffer[MAX_TX_BUFFER_SIZE];
static uint8_t rx_armed = 0;
uint8_t ESTOP = 0;
uint8_t REPLUG = 0;
@@ -39,12 +44,13 @@ static uint8_t enabled = 0;
static uint8_t pwm_duty_percent = 100;
uint8_t isolation_enable = 0;
static uint32_t last_host_seen = 0;
static uint8_t fake_500_voltage_mode = 0;
static CP_State_t cp_state_buffer = EV_STATE_ACQUIRING;
CCS_State_t CCS_State;
CCS_EvInfo_t CCS_EvInfo;
CONN_State_t CCS_EvseState;
CCS_ConnectorState_t CCS_ConnectorState = CCS_UNPLUGGED;
CCS_ConnectorState_t CCS_ConnectorState = CCS_UNKNOWN;
static uint8_t process_received_packet(const uint8_t* packet, uint16_t packet_len);
@@ -52,27 +58,52 @@ void CCS_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size) {
if (huart != &huart3) {
return;
}
rx_armed = 0;
if (size > 0 && size <= sizeof(rx_buffer)) {
process_received_packet(rx_buffer, size);
}
}
void CCS_RxArm(void) {
if ((&huart3)->RxState == HAL_UART_STATE_READY) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart3, rx_buffer, sizeof(rx_buffer));
}
}
void CCS_SerialLoop(void) {
static uint32_t replug_tick = 0;
static uint32_t replug_watchdog_tick = 0;
static uint32_t replug_watchdog1_tick = 0;
static uint32_t last_state_sent = 0;
static uint32_t force_unlock_tick = 0;
static uint32_t stop_tick = 0;
if (!rx_armed && HAL_UART_GetState(&huart3) == HAL_UART_STATE_READY) {
if (HAL_UARTEx_ReceiveToIdle_IT(&huart3, rx_buffer, sizeof(rx_buffer)) == HAL_OK) {
rx_armed = 1;
}
}
CCS_RxArm();
/* Read CP once per loop and use buffered value below. */
cp_state_buffer = CP_GetState();
if (CONN.connControl == CMD_FORCE_UNLOCK) {
if (force_unlock_tick == 0) {
force_unlock_tick = HAL_GetTick();
} else if ((HAL_GetTick() - force_unlock_tick) >= 10000) {
CONN.connControl = CMD_NONE;
force_unlock_tick = 0;
}
} else {
force_unlock_tick = 0;
}
if (CONN.connControl == CMD_STOP) {
if (stop_tick == 0) {
stop_tick = HAL_GetTick();
} else if ((HAL_GetTick() - stop_tick) >= 1000) {
CONN.connControl = CMD_NONE;
stop_tick = 0;
}
} else {
stop_tick = 0;
}
if (CONN.connControl != CMD_NONE) {
last_cmd = CONN.connControl;
}
@@ -90,10 +121,14 @@ void CCS_SerialLoop(void) {
}
if (((CONN.connControl == CMD_STOP) ||
(CONN.connControl == CMD_FORCE_UNLOCK) ||
(CONN.chargingError != CONN_NO_ERROR)) &&
((HAL_GetTick() - last_stop_sent) > 1000)) {
last_stop_sent = HAL_GetTick();
log_printf(LOG_WARN, "Stopping charging...\n");
if (CONN.connControl == CMD_FORCE_UNLOCK) {
CP_SetDuty(100);
}
CCS_SendEmergencyStop();
}
@@ -108,11 +143,21 @@ void CCS_SerialLoop(void) {
(void)replug_watchdog_tick;
(void)replug_watchdog1_tick;
uint8_t host_timed_out = (last_host_seen > 0 && (HAL_GetTick() - last_host_seen) > 5000u);
uint8_t has_charging_error = 0;//(CONN.chargingError != CONN_NO_ERROR);
switch(CCS_ConnectorState){
case CCS_UNKNOWN:
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Unknown);
if (config_initialized && !host_timed_out) {
CCS_ConnectorState = CCS_UNPLUGGED;
}
break;
case CCS_DISABLED:
RELAY_Write(RELAY_CP, 0);
CONN_SetState(Disabled);
if (CONN.chargingError == CONN_NO_ERROR){
if ((CONN.chargingError == CONN_NO_ERROR) && !host_timed_out){
CCS_ConnectorState = CCS_UNPLUGGED;
}
break;
@@ -178,11 +223,21 @@ void CCS_SerialLoop(void) {
break;
}
if (last_host_seen > 0 && (HAL_GetTick() - last_host_seen) > 500) {
if (has_charging_error &&
CCS_ConnectorState != CCS_DISABLED &&
CCS_ConnectorState != CCS_UNKNOWN) {
log_printf(LOG_ERR, "Charging error %d, state -> disabled\n", CONN.chargingError);
CCS_ConnectorState = CCS_DISABLED;
}
if (host_timed_out) {
CONN.EnableOutput = 0;
CCS_EvseState = Unknown;
CP_SetDuty(100);
log_printf(LOG_ERR, "Everest timeout\n");
if (CCS_ConnectorState != CCS_DISABLED && CCS_ConnectorState != CCS_UNKNOWN) {
log_printf(LOG_ERR, "Everest timeout\n");
CCS_ConnectorState = CCS_DISABLED;
}
} else {
if (last_cmd == CMD_STOP) {
CONN.EnableOutput = 0;
@@ -287,6 +342,9 @@ static void send_state(void) {
CCS_State.DutyCycle = CP_GetDuty();
CCS_State.OutputEnabled = PSU0.CONT_enabled;
CCS_State.MeasuredVoltage = (uint16_t)CONN.MeasuredVoltage;
if (fake_500_voltage_mode) {
CCS_State.MeasuredVoltage = FAKE_EVREQ_VOLTAGE_V;
}
CCS_State.MeasuredCurrent = (uint16_t)CONN.MeasuredCurrent;
CCS_State.Power = CCS_Power;
CCS_State.Energy = CCS_Energy;
@@ -333,7 +391,9 @@ static void apply_command(uint8_t cmd, const uint8_t* payload, uint16_t payload_
uint8_t duty = p->pwm_duty_percent;
if (duty > 100) duty = 100;
pwm_duty_percent = duty;
CP_SetDuty(duty);
if (CONN.connControl != CMD_FORCE_UNLOCK) {
CP_SetDuty(duty);
}
break;
}
case CMD_E2M_ENABLE_OUTPUT: {
@@ -359,8 +419,15 @@ static void apply_command(uint8_t cmd, const uint8_t* payload, uint16_t payload_
}
case CMD_E2M_SET_OUTPUT_VOLTAGE: {
const e2m_set_output_t* p = (const e2m_set_output_t*)payload;
CONN.RequestedVoltage = p->voltage_V;
CONN.WantedCurrent = p->current_0p1A;
if (p->voltage_V == FAKE_EVREQ_VOLTAGE_V) {
fake_500_voltage_mode = 1u;
CONN.RequestedVoltage = FAKE_PSU_VOLTAGE_V;
CONN.WantedCurrent = FAKE_PSU_CURRENT_0P1A;
} else {
fake_500_voltage_mode = 0u;
CONN.RequestedVoltage = p->voltage_V;
CONN.WantedCurrent = p->current_0p1A;
}
break;
}
case CMD_E2M_ISOLATION_CONTROL: {
+53 -12
View File
@@ -2,12 +2,15 @@
#include "usart.h"
#include "board.h"
#include "serial.h"
#include "debug.h"
// Приватные функции
static uint32_t calculate_crc32(const uint8_t* data, uint16_t length);
static uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code);
static uint8_t parse_packet(const uint8_t* packet_data, uint16_t packet_len, ReceivedCommand_t* out_cmd);
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t* packet_data, uint16_t packet_len);
static void SC_ArmUart2Rx(void);
static void SC_ArmUart5Rx(void);
uint8_t test_crc_invalid = 0;
@@ -76,8 +79,8 @@ void SC_Init() {
void SC_Task() {
// Запуск приема в режиме прерывания с ожиданием idle
if((huart2.RxState == HAL_UART_STATE_READY) && (serial_control.command_ready == 0)) HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
if((huart5.RxState == HAL_UART_STATE_READY)) HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
SC_ArmUart2Rx();
SC_ArmUart5Rx();
// Проверка таймаута отправки пакета (больше 100 мс)
if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0) {
@@ -92,31 +95,57 @@ void SC_Task() {
// Проверка наличия принятой команды для обработки
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
// HAL_Delay(2);
g_sc_command_source = SC_SOURCE_UART2;
SC_CommandHandler(&serial_control.received_command);
HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
serial_control.command_ready = 0; // Сбрасываем флаг
SC_ArmUart2Rx();
}
if (serial_control.response_pending && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
SC_SendPacket(NULL, 0, serial_control.response_code);
serial_control.response_pending = 0;
}
if (serial_iso.command_ready) {
g_sc_command_source = SC_SOURCE_UART5;
SC_CommandHandler((ReceivedCommand_t*)&serial_iso.received_command);
serial_iso.command_ready = 0;
SC_ArmUart5Rx();
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart->Instance == huart2.Instance) {
if(!process_received_packet(&serial_control, serial_control.rx_buffer, Size)){
SC_SendPacket(NULL, 0, RESP_INVALID);
if (!process_received_packet(&serial_control, serial_control.rx_buffer, Size)) {
serial_control.response_pending = 1;
serial_control.response_code = RESP_INVALID;
SC_ArmUart2Rx();
}
g_sc_command_source = SC_SOURCE_UART2;
HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
} else if (huart->Instance == huart5.Instance) {
if (process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
g_sc_command_source = SC_SOURCE_UART5;
SC_CommandHandler((ReceivedCommand_t*)&serial_iso.received_command);
if (!process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
SC_ArmUart5Rx();
}
HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
} else if (huart->Instance == huart3.Instance) {
CCS_RxEventCallback(huart, Size);
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == huart2.Instance) {
uint32_t uart_error = HAL_UART_GetError(huart);
log_printf(LOG_WARN, "USART2 rx error: 0x%08lx\n", uart_error);
SC_ArmUart2Rx();
} else if (huart->Instance == huart5.Instance) {
uint32_t uart_error = HAL_UART_GetError(huart);
log_printf(LOG_WARN, "UART5 rx error: 0x%08lx\n", uart_error);
SC_ArmUart5Rx();
} else if (huart->Instance == huart3.Instance) {
uint32_t uart_error = HAL_UART_GetError(huart);
log_printf(LOG_WARN, "USART3 rx error: 0x%08lx\n", uart_error);
CCS_RxArm();
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == huart2.Instance) {
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
@@ -124,6 +153,18 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
}
}
static void SC_ArmUart2Rx(void) {
if ((&huart2)->RxState == HAL_UART_STATE_READY && serial_control.command_ready == 0) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
}
}
static void SC_ArmUart5Rx(void) {
if ((&huart5)->RxState == HAL_UART_STATE_READY && serial_iso.command_ready == 0) {
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
}
}
// Приватные функции реализации
// Полностью программная реализация CRC-32 (полином CRC32_POLYNOMIAL, порядок little-endian)