latest version

This commit is contained in:
2026-03-10 13:17:00 +03:00
parent 5ea401f34d
commit f410ea90aa
179 changed files with 151928 additions and 110001 deletions

BIN
Core/.DS_Store vendored

Binary file not shown.

BIN
Core/Inc/.DS_Store vendored

Binary file not shown.

View File

@@ -11,10 +11,16 @@
void GBT_Lock(uint8_t state);
typedef enum{
RELAY_AUX,
RELAY_AUX0 = 0,
RELAY_AUX1,
RELAY3,
RELAY_DC,
RELAY_AC,
RELAY_CC,
}relay_t;
RELAY_DC1,
//
RELAY_COUNT
} relay_t;
void RELAY_Write(relay_t num, uint8_t state);
void Init_Peripheral();
@@ -24,5 +30,30 @@ uint8_t SW_GetAddr();
void ADC_Select_Channel(uint32_t ch);
int16_t GBT_ReadTemp(uint8_t ch);
typedef enum{
IN_SW0 = 0,
IN_SW1,
IN0,
IN_ESTOP,
IN_FB1,
IN_CONT_FB_DC,
ISO_IN,
} inputNum_t;
uint8_t IN_ReadInput(inputNum_t input_n);
// Версия устройства
#define VERSION_OFFSET (0x1E4)
typedef struct __attribute__((packed)) {
uint32_t serialNumber; // Байты 0-3: серийный номер станции (little-endian)
uint8_t stationType; // Байт 4: тип станции
uint8_t boardVersion; // Байт 5: версия платы
uint8_t addrEdcan; // Байт 6: адрес EDCAN
uint8_t reserved[57]; // Байты 7-63: зарезервированы
} InfoBlock_t;
extern InfoBlock_t *InfoBlock;
#endif /* SRC_BOARD_H_ */

13
Core/Inc/charger_config.h Executable file
View File

@@ -0,0 +1,13 @@
#pragma once
#include "main.h"
#define PSU_MAX_VOLTAGE 1000 //1V/bit
#define PSU_MIN_VOLTAGE 150 //1V/bit
#define PSU_MAX_CURRENT 100 //1A/bit
#define PSU_MIN_CURRENT 1 //1A/bit
#define PSU_MAX_POWER 30000 //1W/bit
#define PSU_NUM 1
#define GBT_CH_VER_MAJOR 1
#define GBT_CH_VER_MINOR 0

98
Core/Inc/charger_control.h Executable file
View File

@@ -0,0 +1,98 @@
/*
* charger_control.h
*
* Created on: Jul 29, 2024
* Author: colorbass
*/
#ifndef INC_CHARGER_CONTROL_H_
#define INC_CHARGER_CONTROL_H_
#include "main.h"
#pragma pack(push, 1)
// Статус
// статус подключения к автомобилю
typedef enum __attribute__((packed)) {
Unknown,
Unplugged,
Disabled,
Preparing,
AuthRequired,
WaitingForEnergy,
ChargingPausedEV,
ChargingPausedEVSE,
Charging,
AuthTimeout,
Finished,
FinishedEVSE,
FinishedEV,
Replugging
} CONN_State_t;
// Управление
// Разрешение на зарядку
typedef enum __attribute__((packed)){
CMD_NONE = 0,
CMD_STOP = 1,
CMD_START = 2,
CMD_FORCE_UNLOCK = 3,
CMD_REPLUG = 4,
} CONN_Control_t;
typedef enum __attribute__((packed)){
CONN_NO_ERROR = 0,
CONN_ERR_INSULATION = 1, // Утечка тока
CONN_ERR_EMERGENCY = 2, // Нажата кнопка аварийной остановки
CONN_ERR_DOOR_OPEN = 3, // Открыта дверь
CONN_ERR_LOCK = 4, // Ошибка замка
CONN_ERR_CONN_TEMP = 5, // Перегрев коннектора
CONN_ERR_AC_FAULT = 6, // Нет напряжения сети
CONN_ERR_CONTACTOR = 7, // Контактор неисправен
CONN_ERR_HOTPLUG = 8, // Коннектор неожиданно отключился
CONN_ERR_EV_COMM = 9, // Ошибка протокола связи с электромобилем
CONN_ERR_PSU_FAULT = 10, // Ошибка PSU
}CONN_Error_t;
typedef struct{
CONN_Control_t connControl; //0
CONN_State_t connState; //1
uint8_t SOC; // State of charge [%] //2
uint32_t Power; // Power [W] //3..6
uint32_t Energy; // Energy [Wh] //7..10
uint32_t RequestedPower; //1W/bit
uint16_t RequestedVoltage; //1V/bit
uint16_t RequestedCurrent; //0.1A/bit
uint16_t MeasuredVoltage; //1V/bit
uint16_t MeasuredCurrent; //0.1A/bit
uint8_t EnableOutput;
uint8_t outputEnabled;
int16_t UnmetDemand;
uint16_t WantedCurrent; //0.1A/bit
CONN_Error_t chargingError; // 0 if okay
uint8_t EvConnected;
} ChargingConnector_t;
#pragma pack(pop)
extern ChargingConnector_t CONN;
//информация о зарядке
//база данных с хранением инфы
//главный блок хранит в себе инфу о конфиге возможно во флеше
//либо в charger_config.h
//OCPP - универсальный блок типа
void CONN_Init();
void CONN_Loop();
void CONN_PrintChargingTotal();
#endif /* INC_CHARGER_CONTROL_H_ */

View File

@@ -7,8 +7,11 @@
#ifndef INC_CHARGER_GBT_H_
#define INC_CHARGER_GBT_H_
#include "main.h"
#include "connector.h"
#include "charger_control.h"
#define GBT_CST_NO_REASON 0x0000F0F0 // Без причины
#define GBT_CST_CONDITION_REACHED 0x0100F0F0 // Заряд завершен
@@ -23,6 +26,13 @@
#define GBT_CST_CURRENT_MISMATCH 0x0000F0F1 // Неправильный ток
#define GBT_CST_ABNORMALVOLTAGEERROR 0x0000F0F4 // Ненормальное напряжение
typedef enum {
GBT_STOP_EVSE = 0,
GBT_STOP_EV = 1,
GBT_STOP_OCPP = 2,
}GBT_StopSource_t;
typedef enum{
GBT_CC_UNKNOWN,
@@ -40,26 +50,23 @@ typedef enum{
// GBT_S2_LOCKED = 0x12, //
GBT_S3_STARTED = 0x13, // 12V AUX
GBT_S31_WAIT_BHM = 0x14, // testing isolation, send CHM receive BHM
GBT_S4_ISOTEST = 0x15, // testing isolation, send CHM receive BHM
GBT_S5_BAT_INFO = 0x16, // identifying BMS, send CRM receive BRM (long)
GBT_S6_BAT_STAT = 0x17, // send CRM(AA), receive BCP (long)
GBT_S7_BMS_WAIT = 0x18, // wait for BMS, send CTS+CML receive BRO(00), next BRO(AA)
GBT_S8_INIT_CHARGER = 0x19,// starting power modules, send CRO(00)
GBT_S9_WAIT_BCL = 0x20, // waiting for BCL (requested voltage), send CRO(00)
GBT_S10_CHARGING = 0x21, // charging, contactor ON, send CCS, receiving BCL+BCS+BSM
GBT_STOP = 0x22, // normal stop
GBT_STOP_CSD = 0x23, // normal stop
GBT_ERROR = 0x24, // Error
GBT_COMPLETE = 0x25,
GBT_S4_WAIT_PSU_READY = 0x15, // wait for PSU to be ready
GBT_S4_WAIT_PSU_ON = 0x16, // PSU is on, wait for isolation test
GBT_S4_ISOTEST = 0x17, // testing isolation, send CHM receive BHM
GBT_S4_WAIT_PSU_OFF = 0x18, // PSU is off, wait for battery info
GBT_S5_BAT_INFO = 0x19, // identifying BMS, send CRM receive BRM (long)
GBT_S6_BAT_STAT = 0x1A, // send CRM(AA), receive BCP (long)
GBT_S7_BMS_WAIT = 0x1B, // wait for BMS, send CTS+CML receive BRO(00), next BRO(AA)
GBT_S8_INIT_CHARGER = 0x1C,// starting power modules, send CRO(00)
GBT_S9_WAIT_BCL = 0x1D, // waiting for BCL (requested voltage), send CRO(00)
GBT_S10_CHARGING = 0x1E, // charging, contactor ON, send CCS, receiving BCL+BCS+BSM
GBT_STOP = 0x1F, // normal stop
GBT_STOP_CSD = 0x20, // normal stop
GBT_ERROR = 0x21, // Error
GBT_COMPLETE = 0x22,
}gbtState_t;
typedef enum __attribute__((packed)){
GBT_ERR_OKAY = 0,
GBT_ERR_INSULATION = 1,
}GBT_Error_t;
#pragma pack(push, 1)
typedef struct {
@@ -154,32 +161,6 @@ typedef struct {
}GBT_CSD_t;
typedef struct {
uint8_t enablePSU;
uint16_t requestedVoltage; // 0.1V/bit
uint16_t requestedCurrent; // 0.1A/bit
uint8_t chargingMode; // 0x01 - CV, 0x02 - CC
uint8_t chargingPercentage; //
uint16_t chargingRemainingTimeMin; //
uint16_t chargingElapsedTimeMin; //
uint8_t chargingElapsedTimeSec; //
CONN_State_t connectorState;
}GBT_EDCAN_Output_t;
typedef struct {
uint8_t PSU_Status;
uint16_t measuredVoltage; // 0.1V/bit
uint16_t measuredCurrent; // 0.1A/bit
CONN_Control_t chargeControl;
GBT_Error_t chargingError; // 0 if okay
}GBT_EDCAN_Input_t;
/* 500 - Power Supply
TX
* PSU_ENABLE
@@ -223,10 +204,15 @@ extern uint8_t GBT_BRO;
extern uint8_t GBT_Charger_Enable;
extern GBT_StopSource_t GBT_StopSource;
void GBT_Init();
void GBT_Start();
void GBT_Reset();
void GBT_Stop(uint32_t causecode);
//void GBT_Stop(uint32_t causecode);
void GBT_StopEV(uint32_t causecode);
void GBT_StopEVSE(uint32_t causecode);
void GBT_StopOCPP(uint32_t causecode);
void GBT_ForceStop();
void GBT_ChargerTask();
void GBT_Error(uint32_t errorcode);
@@ -249,6 +235,4 @@ void GBT_SendCHM();
void GBT_SendCRM(uint8_t state);
void GBT_SendCSD();
void GBT_SendCEM(uint32_t ErrorCode);
#endif /* INC_CHARGER_GBT_H_ */

View File

@@ -10,33 +10,8 @@
#include "main.h"
// Статус
// статус подключения к автомобилю
typedef enum __attribute__((packed)) {
CONN_Initializing = 1,
CONN_Faulted = 2,
CONN_Available = 3,
CONN_Preparing = 4,// to charge
CONN_Charging = 5,
CONN_Finishing = 6,//, waiting to disconnect
CONN_Suspended_EV = 7,
CONN_Suspended_EVSE = 8,
//Reserved
} CONN_State_t;
// Управление
// Разрешение на зарядку
typedef enum __attribute__((packed)) {
CHARGING_NOT_ALLOWED = 1,
CHARGING_ALLOWED = 2,
FORCE_UNLOCK = 3,
} CONN_Control_t;
#include "charger_gbt.h"
#include "charger_control.h"
extern CONN_State_t connectorState;

52
Core/Inc/crc.h Normal file
View File

@@ -0,0 +1,52 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file crc.h
* @brief This file contains all the function prototypes for
* the crc.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __CRC_H__
#define __CRC_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern CRC_HandleTypeDef hcrc;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_CRC_Init(void);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __CRC_H__ */

View File

@@ -8,9 +8,27 @@
#ifndef SRC_DEBUG_H_
#define SRC_DEBUG_H_
void debug_task();
void debug_init();
void debug_rx_interrupt(UART_HandleTypeDef *huart, uint16_t Size);
#include <stdint.h>
#include <stdarg.h>
typedef enum {
LOG_EMERG = 1,
LOG_ALERT = 2,
LOG_CRIT = 3,
LOG_ERR = 4,
LOG_WARN = 5,
LOG_NOTICE = 6,
LOG_INFO = 7,
LOG_DEBUG = 8,
} LogLevel_t;
// Функции для работы с кольцевым буфером отладочных сообщений
void debug_buffer_add(const uint8_t* data, uint16_t len);
uint16_t debug_buffer_available(void);
void debug_buffer_send(void);
// Кастомный printf с приоритетом лога
int log_printf(LogLevel_t level, const char *format, ...);
#endif /* SRC_DEBUG_H_ */

View File

@@ -1,25 +0,0 @@
#ifndef EDCAN_CONFIG_H
#define EDCAN_CONFIG_H
#define DEVICE_ID 0x20
#define FWVER 1
//если используется STM32 с одним каном
//#define ED_CANx
//extern CAN_HandleTypeDef hcan;
//#define ED_CAN_INSTANCE hcan
//если используется CAN1 на STM32 с двумя канами
//#define ED_CAN1
//extern CAN_HandleTypeDef hcan1;
//#define ED_CAN_INSTANCE hcan1
//если используется CAN2 на STM32 с двумя канами
#define ED_CAN2
extern CAN_HandleTypeDef hcan2;
#define ED_CAN_INSTANCE hcan2
//можно уменьшать для уменьшения объема потребляемой памяти
#define BUFFER_SIZE 256
#endif //EDCAN_CONFIG_H

View File

@@ -13,14 +13,21 @@
void GBT_Lock(uint8_t state);
void GBT_ManageLock();
void GBT_ManageLockSolenoid();
void GBT_ManageLockMotor();
uint8_t GBT_LockGetState();
void GBT_ForceLock(uint8_t state);
void GBT_ResetErrorTimeout();
typedef struct {
// uint8_t state;
uint8_t demand;
uint8_t error;
uint8_t action_requested; // 0 = unlock, 1 = lock, 255 = no action
uint8_t motor_state; // 0 = idle, 1 = motor_on, 2 = waiting_off
uint32_t last_action_time; // время последнего изменения состояния мотора
uint8_t retry_count; // счетчик попыток
uint32_t error_tick; // время установки ошибки (для таймаута сброса)
} GBT_LockState_t;
extern GBT_LockState_t GBT_LockState;

46
Core/Inc/main.h Executable file → Normal file
View File

@@ -41,7 +41,9 @@ extern "C" {
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
#define FW_VERSION_MAJOR 0x01
#define FW_VERSION_MINOR 0x00
#define FW_VERSION_PATCH 0x01
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
@@ -57,8 +59,10 @@ void Error_Handler(void);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define ADC_CC1_Pin GPIO_PIN_6
#define ADC_CC1_GPIO_Port GPIOA
#define IN_SW0_Pin GPIO_PIN_1
#define IN_SW0_GPIO_Port GPIOA
#define IN_SW1_Pin GPIO_PIN_2
#define IN_SW1_GPIO_Port GPIOA
#define LOCK_A_Pin GPIO_PIN_4
#define LOCK_A_GPIO_Port GPIOC
#define LOCK_B_Pin GPIO_PIN_5
@@ -67,18 +71,36 @@ void Error_Handler(void);
#define ADC_NTC1_GPIO_Port GPIOB
#define ADC_NTC2_Pin GPIO_PIN_1
#define ADC_NTC2_GPIO_Port GPIOB
#define LOCK_FB_Pin GPIO_PIN_9
#define LOCK_FB_GPIO_Port GPIOE
#define ADDR_0_Pin GPIO_PIN_10
#define ADDR_0_GPIO_Port GPIOE
#define ADDR_1_Pin GPIO_PIN_11
#define ADDR_1_GPIO_Port GPIOE
#define IN0_Pin GPIO_PIN_7
#define IN0_GPIO_Port GPIOE
#define RELAY1_Pin GPIO_PIN_8
#define RELAY1_GPIO_Port GPIOE
#define RELAY2_Pin GPIO_PIN_9
#define RELAY2_GPIO_Port GPIOE
#define RELAY3_Pin GPIO_PIN_10
#define RELAY3_GPIO_Port GPIOE
#define RELAY4_Pin GPIO_PIN_11
#define RELAY4_GPIO_Port GPIOE
#define RELAY5_Pin GPIO_PIN_12
#define RELAY5_GPIO_Port GPIOE
#define AC_OK_Pin GPIO_PIN_14
#define AC_OK_GPIO_Port GPIOE
#define RELAY_CC_Pin GPIO_PIN_15
#define RELAY_CC_GPIO_Port GPIOE
#define RELAY_CC_GPIO_Port GPIOA
#define RELAY_DC_Pin GPIO_PIN_3
#define RELAY_DC_GPIO_Port GPIOD
#define USART2_DIR_Pin GPIO_PIN_4
#define USART2_DIR_GPIO_Port GPIOD
#define RELAY_AUX_Pin GPIO_PIN_4
#define RELAY_AUX_GPIO_Port GPIOB
#define IN_ESTOP_Pin GPIO_PIN_7
#define IN_ESTOP_GPIO_Port GPIOD
#define IN_FB2_Pin GPIO_PIN_3
#define IN_FB2_GPIO_Port GPIOB
#define IN_FB1_Pin GPIO_PIN_4
#define IN_FB1_GPIO_Port GPIOB
#define EE_WP_Pin GPIO_PIN_7
#define EE_WP_GPIO_Port GPIOB
#define ISO_IN_Pin GPIO_PIN_1
#define ISO_IN_GPIO_Port GPIOE
/* USER CODE BEGIN Private defines */

31
Core/Inc/meter.h Executable file
View File

@@ -0,0 +1,31 @@
/*
* psu_struct.h
*
* Created on: Jul 24, 2024
* Author: colorbass
*/
#ifndef INC_METER_H_
#define INC_METER_H_
#include "main.h"
#include "charger_config.h"
typedef struct {
uint32_t meterLastTick; // Время последнего пакета Alive
uint8_t online;
uint32_t lastTick; // Время последнего вызова для каждого коннектора
uint64_t EnergyPSU_Ws; // Энергия для каждого коннектора (расчет по силовым модулям)
uint32_t AbsoluteEnergy; // Абсолютная энергия каждого счетчика (ватт*час)
uint32_t EnergyOffset; // смещение энергии по счетчикам (если 0, значит не успели захватить Offset) (ватт*час)
uint32_t EnergyOffset1; // смещение энергии по счетчикам относительно PSU
uint8_t enable; //если 0, то счетчик обнуляется
}METER_t;
extern METER_t METER;
void METER_CalculateEnergy();
#endif /* INC_METER_H_ */

196
Core/Inc/psu_control.h Executable file
View File

@@ -0,0 +1,196 @@
/*
* ccs_control.h
*
* Created on: 19 авг. 2024 г.
* Author: colorbass
*/
#ifndef INC_PSU_CONTROL_H_
#define INC_PSU_CONTROL_H_
#include "main.h"
#include "charger_config.h"
void PSU_Init();
void PSU_Enable(uint8_t addr, uint8_t enable);
void PSU_Loop();
void CONT_Loop();
// --- Состояние силового модуля (DC30, один PSU) ---
typedef enum{
PSU_UNREADY, // отключен, не готов к использованию
PSU_INITIALIZING, // инициализация модуля
PSU_READY, // отключен, готов к использованию
PSU_WAIT_ACK_ON, // ждём подтверждение включения модуля (напряжение выше порога)
PSU_CONT_WAIT_ACK_ON, // включаем DC-контактор и ждём подтверждение
PSU_CONNECTED, // модуль включён, DC-контактор замкнут
PSU_CURRENT_DROP, // снижение тока перед отключением
PSU_WAIT_ACK_OFF, // ждём подтверждение выключения модуля (напряжение ниже порога)
PSU_CONT_WAIT_ACK_OFF, // выключаем DC-контактор и ждём подтверждение
PSU_OFF_PAUSE, // пауза после выключения модуля
} PSU_State_t;
/* Status0 (состояние модуля N, таблица 0 — modularForm0) */
typedef struct{
/* Bit0 */ uint8_t shortCircuitFault:1; /* 1: короткое замыкание на выходе */
/* Bit1 */ uint8_t unevenFlowAlarm:1; /* 1: перекос/неравномерность распределения тока между модулями */
/* Bit2 */ uint8_t internalCommunicationFault:1; /* 1: внутренняя ошибка связи модуля */
/* Bit3 */ uint8_t inputBusLineFault:1; /* 1: авария по входу или по шине постоянного тока */
/* Bit4 */ uint8_t lockProtection:1; /* 1: защита с защёлкой (латч, блокировка до сброса) */
/* Bit5 */ uint8_t dischargeFault:1; /* 1: неисправность цепи разряда (bleeder/разрядный резистор) */
/* Bit6 */ uint8_t eepromFault:1; /* 1: ошибка/неисправность EEPROM */
/* Bit7 */ uint8_t rsvd_s0:1; /* зарезервировано */
} PSU_Status0_t;
/* Status1 (состояние модуля N, таблица 1 — modularForm1) */
typedef struct{
/* Bit0 */ uint8_t dcSideOffStatus:1; /* 1: отключена сторона постоянного тока (DC-выход) */
/* Bit1 */ uint8_t moduleFaultAlarm:1; /* 1: общая авария модуля */
/* Bit2 */ uint8_t moduleProtectionAlarm:1; /* 1: сработала защита модуля */
/* Bit3 */ uint8_t fanFaultAlarm:1; /* 1: авария вентилятора */
/* Bit4 */ uint8_t overTempAlarm:1; /* 1: перегрев модуля */
/* Bit5 */ uint8_t outputOverVoltageAlarm:1; /* 1: перенапряжение на выходе */
/* Bit6 */ uint8_t outputOverCurrentAlarm:1; /* 1: сверхток на выходе */
/* Bit7 */ uint8_t canCommunicationInterruptAlarm:1; /* 1: нарушение связи по CAN */
} PSU_Status1_t;
/* Status2 (состояние модуля N, таблица 2 — modularForm2) */
typedef struct{
/* Bit0 */ uint8_t powerLimitStatus:1; /* 1: активен режим ограничения мощности */
/* Bit1 */ uint8_t moduleAddressDuplicate:1; /* 1: дублирование адреса модуля */
/* Bit2 */ uint8_t severeUnevenFlowFault:1; /* 1: сильный перекос токораспределения между модулями */
/* Bit3 */ uint8_t threePhaseInputPhaseLossAlarm:1; /* 1: авария по пропаданию фазы трёхфазного входа */
/* Bit4 */ uint8_t threePhaseInputUnbalanceAlarm:1; /* 1: авария по разбалансу трёхфазного входа */
/* Bit5 */ uint8_t inputUnderVoltageAlarm:1; /* 1: пониженное напряжение на входе */
/* Bit6 */ uint8_t inputOverVoltageAlarm:1; /* 1: повышенное напряжение на входе */
/* Bit7 */ uint8_t pfcSideOffStatus:1; /* 1: отключена сторона PFC */
} PSU_Status2_t;
typedef struct {
uint8_t enableAC; // состояние AC-контактора (желание)
uint8_t enableOutput; // разрешение выхода модуля (желание)
uint16_t outputVoltage; // измеренное выходное напряжение [В]
int16_t outputCurrent; // измеренный выходной ток [0.1 А]
uint8_t temperature; // температура модуля
PSU_State_t state; // состояние силового модуля и контакторов
uint8_t online; // модуль в сети (есть телеметрия)
uint8_t ready; // модуль готов к работе (online && нет ошибок)
uint8_t PSU_enabled; // на выходе есть напряжение (> порога)
uint8_t CONT_enabled; // DC-контактор замкнут (по обратной связи)
uint8_t cont_fault; // внутренняя ошибка контакторов
uint8_t psu_fault; // внутренняя ошибка силового модуля
uint32_t statetick; // время входа в состояние
// Дополнительные параметры для одного модуля DC30
uint32_t power_limit; // лимит мощности [кВт]
uint8_t hv_mode; // HV-режим (ограничение напряжения)
uint32_t tempAmbient; // температура окружающего воздуха (из PSU_04)
union { uint8_t raw; PSU_Status0_t bits; } status0; // modularForm0
union { uint8_t raw; PSU_Status1_t bits; } status1; // modularForm1
union { uint8_t raw; PSU_Status2_t bits; } status2; // modularForm2
} PSU_t;
extern PSU_t PSU0;
void PSU_Task(void);
#pragma pack(push, 1)
typedef struct{
uint8_t source:8;
uint8_t destination:8;
uint8_t command:6;
uint8_t device:4;
uint8_t error:3;
}CanId_t;
typedef struct{
uint8_t rsvd0[2];
uint16_t moduleNumber;
uint8_t rsvd1[5];
}PSU_02_t;
typedef struct{
uint8_t rsvd0[2];
uint16_t moduleGroupNumber;
uint8_t moduleTemperature;
uint8_t rsvd1;
uint8_t modularForm2;
uint8_t modularForm1;
uint8_t modularForm0;
}PSU_04_t;
typedef struct{
uint8_t VABHi;
uint8_t VABLo;
uint8_t VBCHi;
uint8_t VBCLo;
uint8_t VCAHi;
uint8_t VCALo;
uint8_t rsvd1[2];
uint32_t VAB;
uint32_t VBC;
uint32_t VCA;
}PSU_06_t;
typedef struct{
uint32_t totalSystemVoltage;
uint32_t totalSystemCurrent;
}PSU_08_t;
typedef struct{
uint8_t moduleNVoltage_[4];
uint8_t moduleNCurrent_[4];
uint32_t moduleNVoltage;
uint32_t moduleNCurrent;
}PSU_09_t;
// setup
typedef struct{
uint8_t enable;
uint8_t rsvd1[7];
}PSU_1A_t;
typedef struct{
uint8_t moduleVoltage[4];
uint8_t moduleCurrentTotal[4];
}PSU_1B_t;
//typedef struct{
// uint32_t moduleVoltage;
// uint32_t moduleCurrentTotal;
//}PSU_1B_t;
typedef struct{
uint8_t moduleVoltage[4];
uint8_t moduleCurrentTotal[4];
}PSU_1C_t;
typedef struct{
uint8_t enable;
uint8_t rsvd1[7];
}PSU_1D_t;
extern PSU_02_t PSU_02;
extern PSU_04_t PSU_04;
extern PSU_06_t PSU_06;
extern PSU_08_t PSU_08;
extern PSU_09_t PSU_09;
extern PSU_1A_t PSU_1A;
extern PSU_1B_t PSU_1B;
extern PSU_1C_t PSU_1C;
#pragma pack(pop)
#endif /* INC_PSU_CONTROL_H_ */

53
Core/Inc/rgb_controller.h Executable file
View File

@@ -0,0 +1,53 @@
/*
* rgb_handler.h
*
* Created on: Jul 25, 2024
* Author: colorbass
*/
#ifndef INC_RGB_CONTROLLER_H_
#define INC_RGB_CONTROLLER_H_
#include "main.h"
#pragma pack(push, 1)
typedef struct{
uint8_t R;
uint8_t G;
uint8_t B;
}RGB_t;
typedef struct{
RGB_t Color1;
uint8_t Tr; //20ms/step, 5.1s max
uint8_t Th; //20ms/step, 5.1s max
uint8_t Tf; //20ms/step, 5.1s max
uint8_t Tl; //20ms/step, 5.1s max
RGB_t Color2;
//uint8_t rsvd[6]; // 6 bytes reserved
}RGB_Cycle_t;
#pragma pack(pop)
typedef enum{
LED_RISING,
LED_HIGH,
LED_FALLING,
LED_LOW,
}RGB_Phase_t;
typedef struct{
uint8_t state; // 0 1 2 3
uint16_t tick;
RGB_t color;
uint8_t phasesync;
}RGB_State_t;
void LED_Task();
void LED_Write();
void LED_Init();
#endif /* INC_RGB_CONTROLLER_H_ */

164
Core/Inc/serial_control.h Normal file
View File

@@ -0,0 +1,164 @@
#ifndef SERIALCONTROL_H
#define SERIALCONTROL_H
#include "main.h"
#include <string.h>
#include "charger_control.h"
#define USE_WEB_INTERFACE
// Команды от ПК к устройству
#define CMD_GET_STATUS 0x40
#define CMD_GET_LOG 0x50
#define CMD_GET_LOG_CONTINUE 0x51
#define CMD_GET_INFO 0x60
// Команды с аргументами
#define CMD_SET_POWER_LIMIT 0xC0
#define CMD_TEST_PSU 0xC1
#define CMD_CHARGE_PERMIT 0xC2
// Сервисные команды
#define CMD_SET_CONFIG 0xB0
// Перезагрузка для входа в бутлоадер
#define CMD_DEVICE_RESET 0xB5
// Коды ответов
#define RESP_SUCCESS 0x12
#define RESP_FAILED 0x13
#define RESP_INVALID 0x14
// Максимальный размер буфера полезной нагрузки (включая 4 байта CRC)
#define MAX_TX_BUFFER_SIZE 256
// Максимальный размер буфера для принятого экранированного пакета без START/END
#define MAX_RX_BUFFER_SIZE 256
// Макросы для CRC
#define SERIAL_PROTOCOL_CRC_CLK_ENABLE() do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\
tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\
UNUSED(tmpreg); \
} while(0)
#define SERIAL_PROTOCOL_CRC_CLK_DISABLE() (RCC->AHBENR &= ~(RCC_AHBENR_CRCEN))
#define CRC32_POLYNOMIAL ((uint32_t)0xEDB88320)
void ReadVersion();
// Структура для хранения принятой команды с аргументом
typedef struct {
uint8_t command;
uint8_t argument_length;
void* argument;
} ReceivedCommand_t;
typedef struct __attribute__((packed)) {
CONN_State_t connState;
CONN_Error_t chargingError; // Причина остановки зарядки
uint8_t SOC; // State of charge [%]
uint32_t Energy; // Energy [Wh]
uint16_t RequestedVoltage; //1V/bit
uint16_t RequestedCurrent; //0.1A/bit
uint16_t MeasuredVoltage; //1V/bit
uint16_t MeasuredCurrent; //0.1A/bit
uint8_t outputEnabled;
uint16_t chargingElapsedTimeMin;
uint8_t chargingElapsedTimeSec;
uint16_t estimatedRemainingChargingTime;
// Flags (32 bit)
uint8_t relayAC:1;
uint8_t relayDC:1;
uint8_t relayAUX:1;
uint8_t lockState:1;
uint8_t stopButton:1;
uint8_t logAvailable:1;
uint8_t evInfoAvailable:1;
uint8_t psuOnline:1;
uint8_t rsvd1[3];
int8_t tempConnector0;
int8_t tempConnector1;
int8_t tempAmbient;
int8_t tempBatteryMax;
int8_t tempBatteryMin;
uint16_t highestVoltageOfBatteryCell;
uint8_t batteryStatus;
uint16_t phaseVoltageAB;
uint16_t phaseVoltageBC;
uint16_t phaseVoltageCA;
char VIN[17];
uint8_t batteryType; //battery type
uint16_t batteryCapacity; // 0.1Ah/bit
uint16_t batteryVoltage; // 0.1V/bit
uint8_t batteryVendor[4]; // Battery vendor (ASCII string)
uint32_t batterySN; // int
uint8_t batteryManuY; // year (offset 1985)
uint8_t batteryManuM; // month
uint8_t batteryManuD; // day
uint16_t batteryCycleCount;
uint8_t ownAuto; // 0 = lizing, 1 = own auto
uint8_t EV_SW_VER[8];
uint8_t testMode;
uint16_t testVoltage;
uint16_t testCurrent;
} StatusPacket_t;
typedef struct __attribute__((packed)) {
uint16_t serialNumber;
uint8_t boardVersion;
uint8_t stationType;
uint16_t fw_version_major;
uint16_t fw_version_minor;
uint16_t fw_version_patch;
} InfoPacket_t;
typedef struct __attribute__((packed)) {
char location[3];
uint32_t chargerNumber;
uint32_t unixTime;
} ConfigBlock_t;
// Предварительное объявление структуры протокола
typedef struct SerialControl_t SerialControl_t;
// Структура протокола
struct SerialControl_t {
// Буферы для UART
uint8_t tx_buffer[MAX_TX_BUFFER_SIZE];
uint8_t rx_buffer[MAX_RX_BUFFER_SIZE];
// Переменные для передачи команды
volatile ReceivedCommand_t received_command;
volatile uint8_t command_ready;
// Время отправки последнего пакета
volatile uint32_t tx_tick;
};
// Публичные методы
void SC_Init();
void SC_Task();
void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code);
// Внешняя функция обработки команд (определена в serial_handler.c)
extern void SC_CommandHandler(ReceivedCommand_t* cmd);
extern SerialControl_t serial_control;
extern StatusPacket_t statusPacket;
extern InfoPacket_t infoPacket;
#endif // SERIALCONTROL_H

4
Core/Inc/stm32f1xx_hal_conf.h Executable file → Normal file
View File

@@ -40,7 +40,7 @@
/*#define HAL_CAN_LEGACY_MODULE_ENABLED */
/*#define HAL_CEC_MODULE_ENABLED */
/*#define HAL_CORTEX_MODULE_ENABLED */
/*#define HAL_CRC_MODULE_ENABLED */
#define HAL_CRC_MODULE_ENABLED
/*#define HAL_DAC_MODULE_ENABLED */
/*#define HAL_DMA_MODULE_ENABLED */
/*#define HAL_ETH_MODULE_ENABLED */
@@ -64,7 +64,7 @@
/*#define HAL_SMARTCARD_MODULE_ENABLED */
/*#define HAL_SPI_MODULE_ENABLED */
/*#define HAL_SRAM_MODULE_ENABLED */
/*#define HAL_TIM_MODULE_ENABLED */
#define HAL_TIM_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
/*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_WWDG_MODULE_ENABLED */

4
Core/Inc/stm32f1xx_it.h Executable file → Normal file
View File

@@ -22,7 +22,7 @@
#define __STM32F1xx_IT_H
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/* Private includes ----------------------------------------------------------*/
@@ -56,7 +56,9 @@ void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
void CAN1_RX0_IRQHandler(void);
void USART1_IRQHandler(void);
void USART2_IRQHandler(void);
void USART3_IRQHandler(void);
void CAN2_TX_IRQHandler(void);
void CAN2_RX1_IRQHandler(void);
/* USER CODE BEGIN EFP */

54
Core/Inc/tim.h Normal file
View File

@@ -0,0 +1,54 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.h
* @brief This file contains all the function prototypes for
* the tim.c file
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TIM_H__
#define __TIM_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
extern TIM_HandleTypeDef htim4;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_TIM4_Init(void);
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/* USER CODE BEGIN Prototypes */
/* USER CODE END Prototypes */
#ifdef __cplusplus
}
#endif
#endif /* __TIM_H__ */

11
Core/Inc/usart.h Executable file → Normal file
View File

@@ -7,7 +7,7 @@
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
@@ -32,13 +32,22 @@ extern "C" {
/* USER CODE END Includes */
extern UART_HandleTypeDef huart5;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN Private defines */
/* USER CODE END Private defines */
void MX_UART5_Init(void);
void MX_USART1_UART_Init(void);
void MX_USART2_UART_Init(void);
void MX_USART3_UART_Init(void);
/* USER CODE BEGIN Prototypes */

BIN
Core/Src/.DS_Store vendored

Binary file not shown.

10
Core/Src/adc.c Executable file → Normal file
View File

@@ -84,13 +84,13 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**ADC1 GPIO Configuration
PA6 ------> ADC1_IN6
PA3 ------> ADC1_IN3
PB0 ------> ADC1_IN8
PB1 ------> ADC1_IN9
*/
GPIO_InitStruct.Pin = ADC_CC1_Pin;
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(ADC_CC1_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ADC_NTC1_Pin|ADC_NTC2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
@@ -114,11 +114,11 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC1 GPIO Configuration
PA6 ------> ADC1_IN6
PA3 ------> ADC1_IN3
PB0 ------> ADC1_IN8
PB1 ------> ADC1_IN9
*/
HAL_GPIO_DeInit(ADC_CC1_GPIO_Port, ADC_CC1_Pin);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_3);
HAL_GPIO_DeInit(GPIOB, ADC_NTC1_Pin|ADC_NTC2_Pin);

View File

@@ -1,11 +1,7 @@
/*
* board.c
*
* Created on: Apr 15, 2024
* Author: colorbass
*/
#include "main.h"
#include "board.h"
#include "tim.h"
extern ADC_HandleTypeDef hadc1;
@@ -13,10 +9,64 @@ extern ADC_HandleTypeDef hadc1;
//TEMP READ
//GBT_TEMP_SENSORS
void RELAY_Write(relay_t num, uint8_t state){
if(num==RELAY_AUX)HAL_GPIO_WritePin(RELAY_AUX_GPIO_Port, RELAY_AUX_Pin, state);
if(num==RELAY_CC)HAL_GPIO_WritePin(RELAY_CC_GPIO_Port, RELAY_CC_Pin, state);
InfoBlock_t *InfoBlock = (InfoBlock_t *)(VERSION_OFFSET);
uint8_t RELAY_State[RELAY_COUNT];
void RELAY_Write(relay_t num, uint8_t state){
switch (num) {
case RELAY_AUX0:
HAL_GPIO_WritePin(RELAY1_GPIO_Port, RELAY1_Pin, state);
break;
case RELAY_AUX1:
HAL_GPIO_WritePin(RELAY2_GPIO_Port, RELAY2_Pin, state);
break;
case RELAY3:
HAL_GPIO_WritePin(RELAY3_GPIO_Port, RELAY3_Pin, state);
break;
case RELAY_DC:
HAL_GPIO_WritePin(RELAY4_GPIO_Port, RELAY4_Pin, state);
break;
case RELAY_AC:
HAL_GPIO_WritePin(RELAY5_GPIO_Port, RELAY5_Pin, state);
break;
case RELAY_CC:
HAL_GPIO_WritePin(RELAY_CC_GPIO_Port, RELAY_CC_Pin, state);
break;
case RELAY_DC1:
HAL_GPIO_WritePin(RELAY_DC_GPIO_Port, RELAY_DC_Pin, state);
break;
default:
break;
}
RELAY_State[num] = state;
}
uint8_t RELAY_Read(relay_t num){
return RELAY_State[num];
}
uint8_t IN_ReadInput(inputNum_t input_n){
switch(input_n){
case IN_SW0:
return HAL_GPIO_ReadPin(IN_SW0_GPIO_Port, IN_SW0_Pin);
case IN_SW1:
return HAL_GPIO_ReadPin(IN_SW1_GPIO_Port, IN_SW1_Pin);
case IN0:
return HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
case IN_ESTOP:
return HAL_GPIO_ReadPin(IN_ESTOP_GPIO_Port, IN_ESTOP_Pin);
case IN_FB1:
return HAL_GPIO_ReadPin(IN_FB1_GPIO_Port, IN_FB1_Pin);
case IN_CONT_FB_DC:
return HAL_GPIO_ReadPin(IN_FB2_GPIO_Port, IN_FB2_Pin);
case ISO_IN:
return HAL_GPIO_ReadPin(ISO_IN_GPIO_Port, ISO_IN_Pin);
default:
return 0;
}
}
uint8_t GetBoardTemp(){
@@ -33,21 +83,21 @@ uint8_t GetBoardTemp(){
void Init_Peripheral(){
HAL_ADCEx_Calibration_Start(&hadc1);
RELAY_Write(RELAY_AUX, 0);
RELAY_Write(RELAY_CC, 1);
RELAY_Write(RELAY_AUX0, 0);
RELAY_Write(RELAY_AUX1, 0);
RELAY_Write(RELAY3, 0);
RELAY_Write(RELAY_DC, 0);
RELAY_Write(RELAY_AC, 0);
RELAY_Write(RELAY_CC, 1);
RELAY_Write(RELAY_DC1, 0);
}
float pt1000_to_temperature(float resistance) {
// Константы для PT1000
const float R0 = 1000.0; // Сопротивление при 0 °C
const float C_A = 3.9083E-3f;
// const float A = 3.9083e-03; // Коэффициент температурного изменения (°C^-1)
// const float B = -5.775e-07; // Второй коэффициент (°C^-2)
//
// // Расчет температуры по формуле
// float temperature = -A / (B - (R0 / resistance - 1) * A);
float temperature = (resistance-R0) / ( R0 * C_A);
return temperature;
@@ -95,15 +145,10 @@ int16_t GBT_ReadTemp(uint8_t ch){
float temp = pt1000_to_temperature(calculate_NTC_resistance(adcValue, Vref, Vin, R));
return (int16_t)temp;
}
void ADC_Select_Channel(uint32_t ch) {
ADC_ChannelConfTypeDef conf = {
.Channel = ch,
@@ -114,21 +159,3 @@ void ADC_Select_Channel(uint32_t ch) {
Error_Handler();
}
}
uint8_t SW_GetAddr(){
if(!HAL_GPIO_ReadPin(ADDR_0_GPIO_Port, ADDR_0_Pin)){
if(!HAL_GPIO_ReadPin(ADDR_1_GPIO_Port, ADDR_1_Pin)){
return 0x23;
}else{
return 0x21;
}
}else{
if(!HAL_GPIO_ReadPin(ADDR_1_GPIO_Port, ADDR_1_Pin)){
return 0x22;
}else{
return 0x20;
}
}
}

4
Core/Src/can.c Executable file → Normal file
View File

@@ -7,7 +7,7 @@
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
@@ -47,7 +47,7 @@ void MX_CAN1_Init(void)
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = ENABLE;
hcan1.Init.AutoWakeUp = ENABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.AutoRetransmission = ENABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = ENABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)

View File

@@ -0,0 +1,46 @@
#include "charger_control.h"
#include "charger_config.h"
#include "lock.h"
#include "psu_control.h"
ChargingConnector_t CONN;
void CONN_Init(){
CONN.connControl = CMD_NONE;
CONN.connState = Unknown;
CONN.RequestedVoltage = PSU_MIN_VOLTAGE;
}
void CONN_Loop(){
static CONN_State_t last_connState = Unknown;
if(last_connState != CONN.connState){
last_connState = CONN.connState;
CONN.connControl = CMD_NONE;
}
if(GBT_LockState.error){
CONN.chargingError = CONN_ERR_LOCK;
} else if(PSU0.cont_fault){
CONN.chargingError = CONN_ERR_CONTACTOR;
} else if(PSU0.psu_fault){
CONN.chargingError = CONN_ERR_PSU_FAULT;
// } else if(!CTRL.ac_ok) {
// CONN.chargingError = CONN_ERR_AC_FAULT;
// } else
}else if (CONN.EvConnected == 0){
CONN.chargingError = CONN_NO_ERROR;
}
if(ED_TraceWarning(CONN.chargingError, 0)) printf("CONN%d Error: %d\n", 0, CONN.chargingError);
}
void CONN_PrintChargingTotal(){
printf("CONN%d Charging Finished:\n", 0);
// printf("Charging Time: %d\n", CONN.chargingTime);
printf("Charging Energy: %d\n", CONN.Energy);
// printf("Charging Power: %d\n", CONN.chargingPower);
}

View File

@@ -12,10 +12,14 @@
#include "stdio.h"
#include "j1939.h"
#include "string.h"
#include "edcan.h"
#include "lock.h"
#include "connector.h"
#include "soft_rtc.h"
#include "debug.h"
#include "charger_config.h"
#include "serial_control.h"
#include "lock.h"
#include "psu_control.h"
uint8_t GBT_CC_GetStateRaw();
@@ -52,21 +56,36 @@ GBT_CSD_t GBT_ChargerStop;
uint8_t GBT_BRO;
uint32_t GBT_TimeChargingStarted;
/** Время последнего приёма любого из PGN BCL/BCS/BSM; общий таймаут в GBT_S10_CHARGING */
uint32_t GBT_last_BCL_BCS_BSM_tick;
#define GBT_BCL_BCS_BSM_TIMEOUT_MS 2000
uint32_t GBT_StopCauseCode;
uint32_t GBT_ErrorCode;
extern GBT_EDCAN_Output_t GBT_EDCAN_Output;
extern GBT_EDCAN_Input_t GBT_EDCAN_Input;
GBT_StopSource_t GBT_StopSource;
extern ConfigBlock_t config;
void GBT_Init(){
GBT_State = GBT_DISABLED;
GBT_EDCAN_Input.chargeControl = CHARGING_NOT_ALLOWED;
GBT_Reset();
GBT_MaxLoad.maxOutputVoltage = PSU_MAX_VOLTAGE*10; // 1000V
GBT_MaxLoad.minOutputVoltage = PSU_MIN_VOLTAGE*10; //150V
GBT_MaxLoad.maxOutputCurrent = 4000 - (PSU_MAX_CURRENT*10); //100A
GBT_MaxLoad.minOutputCurrent = 4000 - (PSU_MIN_CURRENT*10); //1A
}
void GBT_SetConfig(){
set_Time(config.unixTime);
GBT_ChargerInfo.chargerLocation[0] = config.location[0];
GBT_ChargerInfo.chargerLocation[1] = config.location[1];
GBT_ChargerInfo.chargerLocation[2] = config.location[2];
GBT_ChargerInfo.chargerNumber = config.chargerNumber;
}
void GBT_ChargerTask(){
@@ -99,22 +118,26 @@ void GBT_ChargerTask(){
break;
case 0x1000: //PGN BCL
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
//TODO: power block
memcpy (&GBT_ReqPower, j_rx.data, sizeof(GBT_ReqPower));
uint16_t volt=GBT_ReqPower.requestedVoltage;
GBT_EDCAN_Output.requestedVoltage = volt;
uint16_t curr=4000-GBT_ReqPower.requestedCurrent;
GBT_EDCAN_Output.requestedCurrent = curr;
uint16_t volt = GBT_ReqPower.requestedVoltage; // 0.1V/bit
uint16_t curr = 4000 - GBT_ReqPower.requestedCurrent; // 0.1A/bit
CONN.RequestedVoltage = volt / 10; // В
CONN.WantedCurrent = curr; // 0.1A
break;
case 0x1100: //PGN BCS
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
//TODO
memcpy (&GBT_ChargingStatus, j_rx.data, sizeof(GBT_ChargingStatus));
GBT_EDCAN_Output.chargingRemainingTimeMin = GBT_ChargingStatus.estimatedRemainingChargingTime;
GBT_EDCAN_Output.chargingPercentage = GBT_ChargingStatus.currentChargeState;
CONN.SOC = GBT_ChargingStatus.currentChargeState;
break;
case 0x1300: //PGN BSM
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
//TODO
memcpy (&GBT_BatteryStatus, j_rx.data, sizeof(GBT_BatteryStatus));
break;
@@ -154,48 +177,13 @@ void GBT_ChargerTask(){
//waiting
}else switch (GBT_State){
case GBT_DISABLED:
RELAY_Write(RELAY_AUX, 0);
if(connectorState == CONN_Charging){
RELAY_Write(RELAY_AUX0, 0);
RELAY_Write(RELAY_AUX1, 0);
if(connectorState == Preparing){
GBT_Reset();
GBT_Start();//TODO IF protections (maybe not needed)
}
break;
// case GBT_S0_UNCONNECTED:
// if(!GBT_Charger_Enable){
// GBT_Stop();
// break;
// }
// if(GBT_CC_GetState()==GBT_CC_4V){
//
// GBT_SwitchState(GBT_S1_CONNECTED);
// GBT_Delay(500);
// }
// break;
// case GBT_S1_CONNECTED:
// if(!GBT_Charger_Enable){
// GBT_Stop();
// break;
// }
// if(GBT_CC_GetState()==GBT_CC_4V){
//
// GBT_Lock(1);
// GBT_SwitchState(GBT_S2_LOCKED);
// GBT_Delay(500);
// }else{
// GBT_SwitchState(GBT_S0_UNCONNECTED);
// }
// break;
// case GBT_S2_LOCKED:
// if(!GBT_Charger_Enable){
// GBT_Stop();
// break;
// }
// if(1){ //TODO: charge permission
// RELAY_Write(RELAY_AUX, 1); // 13.8V AUX ON
// GBT_SwitchState(GBT_S3_STARTED);
// GBT_Delay(500);
// }
// break;
case GBT_S3_STARTED:
GBT_SwitchState(GBT_S31_WAIT_BHM);
@@ -207,36 +195,72 @@ void GBT_ChargerTask(){
GBT_Delay(250);
if(GBT_BHM_recv) {
GBT_SwitchState(GBT_S4_ISOTEST);
GBT_SwitchState(GBT_S4_WAIT_PSU_READY);
}
//Timeout 10S
if((GBT_BHM_recv == 0) && (GBT_StateTick()>10000)) { //BHM Timeout
GBT_Error(0xFCF0C0FC);
EDCAN_printf(LOG_WARN, "BHM Timeout\n");
CONN.chargingError = CONN_ERR_EV_COMM;
log_printf(LOG_ERR, "BHM Timeout\n");
}
break;
case GBT_S4_WAIT_PSU_READY:
if(j_rx.state == 0) GBT_SendCHM();
GBT_Delay(250);
if(PSU0.ready){
GBT_SwitchState(GBT_S4_WAIT_PSU_ON);
}
if(GBT_StateTick()>10000){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU ready timeout, stopping...\n");
break;
}
break;
case GBT_S4_WAIT_PSU_ON:
if(j_rx.state == 0) GBT_SendCHM();
GBT_Delay(250);
CONN.RequestedVoltage = GBT_MaxVoltage.maxOutputVoltage / 10; // 0.1V -> V
CONN.WantedCurrent = 10; // 1A max (0.1A units)
CONN.EnableOutput = 1;
if(PSU0.state == PSU_CONNECTED){
GBT_SwitchState(GBT_S4_ISOTEST);
}
if(GBT_StateTick()>10000){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU on timeout, stopping...\n");
break;
}
break;
case GBT_S4_ISOTEST:
if(j_rx.state == 0) GBT_SendCHM();
GBT_Delay(250);
GBT_EDCAN_Output.requestedVoltage = GBT_MaxVoltage.maxOutputVoltage;
GBT_EDCAN_Output.requestedCurrent = 10; // 1A max
GBT_EDCAN_Output.enablePSU = 1;
//TODO: Isolation test trigger
if(GBT_EDCAN_Input.chargingError == GBT_ERR_INSULATION){
GBT_Stop(GBT_CST_OTHERFALUT);
if(CONN.chargingError != CONN_NO_ERROR){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
}
if(GBT_StateTick()>5000){
GBT_SwitchState(GBT_S5_BAT_INFO);
GBT_EDCAN_Output.requestedVoltage = 50;
GBT_EDCAN_Output.requestedCurrent = 10; // 1A max
GBT_EDCAN_Output.enablePSU = 0;
GBT_SwitchState(GBT_S4_WAIT_PSU_OFF);
}
break;
case GBT_S4_WAIT_PSU_OFF:
CONN.RequestedVoltage = 0;
CONN.WantedCurrent = 0;
CONN.EnableOutput = 0;
if(GBT_StateTick()>5000){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU off timeout, stopping...\n");
break;
}
if(PSU0.PSU_enabled == 0){
GBT_SwitchState(GBT_S5_BAT_INFO);
}
break;
case GBT_S5_BAT_INFO:
@@ -245,24 +269,25 @@ void GBT_ChargerTask(){
if(GBT_BAT_INFO_recv){ //BRM
//Got battery info
GBT_SwitchState(GBT_S6_BAT_STAT);
EDCAN_printf(LOG_INFO, "EV info:\n");
EDCAN_printf(LOG_INFO, "GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]);
EDCAN_printf(LOG_INFO, "Battery type: %d\n",GBT_EVInfo.batteryType);
EDCAN_printf(LOG_INFO, "Battery capacity: %d\n", GBT_EVInfo.batteryCapacity); // 0.1Ah/bit
EDCAN_printf(LOG_INFO, "Battery voltage: %d\n", GBT_EVInfo.batteryVoltage); // 0.1V/bit
EDCAN_printf(LOG_INFO, "Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); // Battery vendor (ASCII string)
EDCAN_printf(LOG_INFO, "Battery SN: %lu\n", GBT_EVInfo.batterySN); // int
EDCAN_printf(LOG_INFO, "Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985); // year (offset 1985)
EDCAN_printf(LOG_INFO, "Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t
EDCAN_printf(LOG_INFO, "Own auto: %d\n", GBT_EVInfo.ownAuto); // 0 = lizing, 1 = own auto
EDCAN_printf(LOG_INFO, "EVIN: %.17s\n", GBT_EVInfo.EVIN); //EVIN
EDCAN_printf(LOG_INFO, "EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER);
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);
}
//Timeout
if((GBT_StateTick()>5000) && (GBT_BAT_INFO_recv == 0)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFDF0C0FC); //BRM Timeout
EDCAN_printf(LOG_WARN, "BRM Timeout\n");
log_printf(LOG_ERR, "BRM Timeout\n");
}
break;
@@ -272,19 +297,20 @@ void GBT_ChargerTask(){
if(GBT_BAT_STAT_recv){
//Got battery status
GBT_SwitchState(GBT_S7_BMS_WAIT);
EDCAN_printf(LOG_INFO, "Battery info:\n");
EDCAN_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); // 0.01v/bit
EDCAN_printf(LOG_INFO, "maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); // 0.1A/bit
EDCAN_printf(LOG_INFO, "totE %dkWh\n",GBT_BATStat.totalEnergy/10); // 0.1kWh
EDCAN_printf(LOG_INFO, "maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); // 0.1V/ bit
EDCAN_printf(LOG_INFO, "maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); // 1C/bit, -50C offset
EDCAN_printf(LOG_INFO, "SOC %dp\n",GBT_BATStat.SOC/10); // 0.1%/bit , 0..100%
EDCAN_printf(LOG_INFO, "Volt. %dV\n",GBT_BATStat.measVoltage/10); // 0.1V/bit
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
}
if((GBT_StateTick()>5000) && (GBT_BAT_STAT_recv == 0)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFCF1C0FC); //BCP Timeout
EDCAN_printf(LOG_WARN, "BCP Timeout\n");
log_printf(LOG_ERR, "BCP Timeout\n");
}
break;
@@ -294,16 +320,18 @@ void GBT_ChargerTask(){
if(j_rx.state == 0) GBT_SendCML();
GBT_Delay(250);
if((GBT_StateTick()>5000) && (GBT_BRO_recv == 0)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFCF4C0FC); //BRO Timeout
EDCAN_printf(LOG_WARN, "BRO Timeout\n");
log_printf(LOG_ERR, "BRO Timeout\n");
}
if(EV_ready){
//EV ready (AA)
GBT_SwitchState(GBT_S8_INIT_CHARGER);
}else{
if((GBT_StateTick()>60000) && (GBT_BRO_recv == 1)){
CONN.chargingError = CONN_ERR_EV_COMM;
GBT_Error(0xFCF4C0FC); //BRO Timeout
EDCAN_printf(LOG_WARN, "BRO Timeout\n");
log_printf(LOG_ERR, "EV not ready for a 60s\n");
}
}
break;
@@ -312,10 +340,16 @@ void GBT_ChargerTask(){
if(j_rx.state == 0) GBT_SendCRO(0x00);
//TODO
GBT_Delay(250);
if(GBT_StateTick()>1500){
// if(GBT_StateTick()>1500){
if(PSU0.ready){
//Power Modules initiated
GBT_SwitchState(GBT_S9_WAIT_BCL);
}
if((GBT_StateTick()>6000) && (PSU0.ready == 0)){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_PSU_FAULT;
log_printf(LOG_ERR, "PSU not ready, stopping...\n");
}
break;
case GBT_S9_WAIT_BCL:
@@ -325,14 +359,15 @@ void GBT_ChargerTask(){
//BCL power requirements received
GBT_SwitchState(GBT_S10_CHARGING);
CONN_SetState(CONN_Charging);
uint16_t curr=4000-GBT_ReqPower.requestedCurrent;
uint16_t volt=GBT_ReqPower.requestedVoltage;
//TODO Limits
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
CONN_SetState(Charging);
GBT_EDCAN_Output.requestedVoltage = volt;
GBT_EDCAN_Output.requestedCurrent = curr;
GBT_EDCAN_Output.enablePSU = 1;
uint16_t curr = 4000 - GBT_ReqPower.requestedCurrent;
uint16_t volt = GBT_ReqPower.requestedVoltage;
//TODO Limits
CONN.RequestedVoltage = volt / 10; // В
CONN.WantedCurrent = curr; // 0.1A
CONN.EnableOutput = 1;
GBT_TimeChargingStarted = get_Current_Time();
}
@@ -340,46 +375,65 @@ void GBT_ChargerTask(){
case GBT_S10_CHARGING:
//CHARGING
//TODO BCL BCS BSM missing ERRORS
if(GBT_EDCAN_Input.chargeControl == CHARGING_NOT_ALLOWED) GBT_Stop(GBT_CST_SUSPENDS_ARTIFICIALLY);
if(GBT_EDCAN_Input.chargeControl == FORCE_UNLOCK) GBT_Stop(GBT_CST_SUSPENDS_ARTIFICIALLY);//GBT_ForceStop();
if(GBT_LockState.error) GBT_Stop(GBT_CST_OTHERFALUT);
if((GBT_ReadTemp(0) > 90) || (GBT_ReadTemp(1) > 90)) {
GBT_Stop(GBT_CST_CONNECTOR_OVER_TEMP);
EDCAN_printf(LOG_WARN, "Connector overheat %d %d\n", GBT_ReadTemp(0), GBT_ReadTemp(1));
if((HAL_GetTick() - GBT_last_BCL_BCS_BSM_tick) > GBT_BCL_BCS_BSM_TIMEOUT_MS){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_EV_COMM;
log_printf(LOG_WARN, "BCL/BCS/BSM timeout, stopping...\n");
break;
}
if(GBT_EDCAN_Input.chargingError == GBT_ERR_INSULATION) {
GBT_Stop(GBT_CST_OTHERFALUT);
EDCAN_printf(LOG_WARN, "Isolation error\n");
if(CONN.connControl == CMD_STOP) GBT_StopOCPP(GBT_CST_SUSPENDS_ARTIFICIALLY);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_StopOCPP(GBT_CST_SUSPENDS_ARTIFICIALLY); // --> Finished
if(GBT_LockState.error) {
GBT_StopEVSE(GBT_CST_OTHERFALUT); // --> Suspend EVSE
CONN.chargingError = CONN_ERR_LOCK;
log_printf(LOG_WARN, "Lock error, stopping...\n");
break;
}
if(CONN_CC_GetState()!=GBT_CC_4V){
GBT_StopEVSE(GBT_CST_OTHERFALUT);
CONN.chargingError = CONN_ERR_HOTPLUG;
log_printf(LOG_WARN, "Hotplug detected, stopping...\n");
break;
}
if((GBT_ReadTemp(0) > 90) || (GBT_ReadTemp(1) > 90)) {
GBT_StopEVSE(GBT_CST_CONNECTOR_OVER_TEMP);
CONN.chargingError = CONN_ERR_CONN_TEMP;
log_printf(LOG_WARN, "Connector overheat %d %d, stopping...\n", GBT_ReadTemp(0), GBT_ReadTemp(1));
break;
}
if(CONN.chargingError != CONN_NO_ERROR){ // --> Suspend EVSE
GBT_StopEVSE(GBT_CST_OTHERFALUT);
// log_printf(LOG_WARN, "Isolation error\n");
}
//GBT_ChargerCurrentStatus.chargingPermissible = 0b1111111111111100;//NOT PERMITTED
GBT_ChargerCurrentStatus.chargingPermissible = 0b1111111111111101;
GBT_ChargerCurrentStatus.chargingTime = (get_Current_Time() - GBT_TimeChargingStarted)/60;
// GBT_ChargerCurrentStatus.outputCurrent = 4000 - GBT_EDCAN_Output.requestedCurrent;
// GBT_ChargerCurrentStatus.outputVoltage = GBT_EDCAN_Output.requestedVoltage;
GBT_ChargerCurrentStatus.outputCurrent = 4000 - GBT_EDCAN_Input.measuredCurrent;
GBT_ChargerCurrentStatus.outputVoltage = GBT_EDCAN_Input.measuredVoltage;
GBT_EDCAN_Output.chargingElapsedTimeMin = (get_Current_Time() - GBT_TimeChargingStarted)/60;
GBT_EDCAN_Output.chargingElapsedTimeSec = (get_Current_Time() - GBT_TimeChargingStarted)%60;
GBT_ChargerCurrentStatus.outputCurrent = 4000 - CONN.MeasuredCurrent; // 0.1A
GBT_ChargerCurrentStatus.outputVoltage = CONN.MeasuredVoltage * 10; // V -> 0.1V
if(j_rx.state == 0) GBT_SendCCS();
if(j_rx.state == 0) {
GBT_SendCCS();
GBT_Delay(49);
}else{
GBT_Delay(10); // Resend packet if not sent
GBT_Delay(50);
}
//TODO: снижение тока если перегрев контактов
break;
case GBT_STOP:
GBT_Delay(10);
GBT_EDCAN_Output.enablePSU = 0;
CONN.EnableOutput = 0;
GBT_SendCST(GBT_StopCauseCode);
//RELAY_Write(RELAY_OUTPUT, 0);
//GBT_SwitchState(GBT_DISABLED);
if(GBT_StateTick()>10000){
EDCAN_printf(LOG_WARN, "BSD Timeout\n");
log_printf(LOG_ERR, "BSD Timeout\n");
GBT_Error(0xFCF0C0FD); //BSD Timeout
}
if(GBT_BSD_recv != 0){
@@ -392,10 +446,7 @@ void GBT_ChargerTask(){
GBT_SendCSD();
if(GBT_StateTick()>2500){ //2.5S
GBT_SwitchState(GBT_COMPLETE);
// GBT_Reset();
//CONN_SetState(CONN_Occupied_complete);
//if(connectorState == CONN_Occupied_charging)
//PSU_Mode(0x0100);
}
break;
@@ -403,59 +454,44 @@ void GBT_ChargerTask(){
case GBT_ERROR:
GBT_SendCEM(GBT_ErrorCode); //2.5S
GBT_SwitchState(GBT_COMPLETE);
// GBT_Reset();
//
break;
case GBT_COMPLETE:
if(connectorState != CONN_Finishing) GBT_SwitchState(GBT_DISABLED);
if(connectorState != Finished) {
GBT_SwitchState(GBT_DISABLED);
GBT_Reset();//CHECK
}
break;
default:
GBT_SwitchState(GBT_DISABLED);
}
if (CONN_CC_GetState()==GBT_CC_4V) CONN.EvConnected = 1;
else CONN.EvConnected = 0;
}
void GBT_SwitchState(gbtState_t state){
GBT_State = state;
ED_status = state;
GBT_state_tick = HAL_GetTick();
if(GBT_State == GBT_DISABLED) printf ("GBT_DISABLED\n");
// if(GBT_State == GBT_S0_UNCONNECTED) printf ("GBT_S0_UNCONNECTED\n");
// if(GBT_State == GBT_S1_CONNECTED) printf ("GBT_S1_CONNECTED\n");
// if(GBT_State == GBT_S2_LOCKED) printf ("GBT_S2_LOCKED\n");
if(GBT_State == GBT_S3_STARTED) printf ("GBT_S3_STARTED\n");
if(GBT_State == GBT_S31_WAIT_BHM) printf ("GBT_S31_WAIT_BHM\n");
if(GBT_State == GBT_S4_ISOTEST) printf ("GBT_S4_ISOTEST\n");
if(GBT_State == GBT_S5_BAT_INFO) printf ("GBT_S5_BAT_INFO\n");
if(GBT_State == GBT_S6_BAT_STAT) printf ("GBT_S6_BAT_STAT\n");
if(GBT_State == GBT_S7_BMS_WAIT) printf ("GBT_S7_BMS_WAIT\n");
if(GBT_State == GBT_S8_INIT_CHARGER)printf ("GBT_S8_INIT_CHARGER\n");
if(GBT_State == GBT_S9_WAIT_BCL) printf ("GBT_S9_WAIT_BCL\n");
if(GBT_State == GBT_S10_CHARGING) printf ("GBT_S10_CHARGING\n");
if(GBT_State == GBT_STOP) printf ("GBT_STOP\n");
if(GBT_State == GBT_STOP_CSD) printf ("GBT_STOP_CSD\n");
if(GBT_State == GBT_ERROR) printf ("GBT_ERROR\n");
if(GBT_State == GBT_COMPLETE) printf ("GBT_COMPLETE\n");
if(GBT_State == GBT_DISABLED) EDCAN_printf(LOG_INFO, "GBT_DISABLED\n");
if(GBT_State == GBT_S3_STARTED) EDCAN_printf(LOG_INFO, "GBT_S3_STARTED\n");
if(GBT_State == GBT_S31_WAIT_BHM) EDCAN_printf(LOG_INFO, "GBT_S31_WAIT_BHM\n");
if(GBT_State == GBT_S4_ISOTEST) EDCAN_printf(LOG_INFO, "GBT_S4_ISOTEST\n");
if(GBT_State == GBT_S5_BAT_INFO) EDCAN_printf(LOG_INFO, "GBT_S5_BAT_INFO\n");
if(GBT_State == GBT_S6_BAT_STAT) EDCAN_printf(LOG_INFO, "GBT_S6_BAT_STAT\n");
if(GBT_State == GBT_S7_BMS_WAIT) EDCAN_printf(LOG_INFO, "GBT_S7_BMS_WAIT\n");
if(GBT_State == GBT_S8_INIT_CHARGER)EDCAN_printf(LOG_INFO, "GBT_S8_INIT_CHARGER\n");
if(GBT_State == GBT_S9_WAIT_BCL) EDCAN_printf(LOG_INFO, "GBT_S9_WAIT_BCL\n");
if(GBT_State == GBT_S10_CHARGING) EDCAN_printf(LOG_INFO, "GBT_S10_CHARGING\n");
if(GBT_State == GBT_STOP) EDCAN_printf(LOG_INFO, "GBT_STOP\n");
if(GBT_State == GBT_STOP_CSD) EDCAN_printf(LOG_INFO, "GBT_STOP_CSD\n");
if(GBT_State == GBT_ERROR) EDCAN_printf(LOG_WARN, "GBT_ERROR\n");
if(GBT_State == GBT_COMPLETE) EDCAN_printf(LOG_INFO, "GBT_COMPLETE\n");
if(GBT_State == GBT_DISABLED) log_printf(LOG_INFO, "Disabled\n");
if(GBT_State == GBT_S3_STARTED) log_printf(LOG_INFO, "Charging started\n");
if(GBT_State == GBT_S31_WAIT_BHM) log_printf(LOG_INFO, "Waiting for BHM\n");
if(GBT_State == GBT_S4_WAIT_PSU_READY) log_printf(LOG_INFO, "Waiting for PSU ready\n");
if(GBT_State == GBT_S4_ISOTEST) log_printf(LOG_INFO, "Isolation test\n");
if(GBT_State == GBT_S5_BAT_INFO) log_printf(LOG_INFO, "Waiting for battery info\n");
if(GBT_State == GBT_S6_BAT_STAT) log_printf(LOG_INFO, "Waiting for battery status\n");
if(GBT_State == GBT_S7_BMS_WAIT) log_printf(LOG_INFO, "Waiting for BMS\n");
if(GBT_State == GBT_S8_INIT_CHARGER)log_printf(LOG_INFO, "Initializing charger\n");
if(GBT_State == GBT_S9_WAIT_BCL) log_printf(LOG_INFO, "Waiting for BCL\n");
if(GBT_State == GBT_S10_CHARGING) log_printf(LOG_INFO, "Charging in progress\n");
if(GBT_State == GBT_STOP) log_printf(LOG_INFO, "Charging Stopped\n");
if(GBT_State == GBT_STOP_CSD) log_printf(LOG_INFO, "Charging Stopped with CSD\n");
if(GBT_State == GBT_ERROR) log_printf(LOG_INFO, "Charging Error\n");
if(GBT_State == GBT_COMPLETE) log_printf(LOG_INFO, "Charging Finished\n");
}
uint32_t GBT_StateTick(){
@@ -467,31 +503,57 @@ void GBT_Delay(uint32_t delay){
GBT_delay = delay;
}
void GBT_Stop(uint32_t causecode){
void GBT_StopEV(uint32_t causecode){ // --> Suspend EV
if (CONN.chargingError){
GBT_StopSource = GBT_STOP_EVSE;
}else{
GBT_StopSource = GBT_STOP_EV;
}
GBT_StopCauseCode = causecode;
if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP);
}
void GBT_Error(uint32_t errorcode){
EDCAN_printf(LOG_WARN, "GBT Error code: 0x%X\n", errorcode);
void GBT_StopEVSE(uint32_t causecode){ // --> Suspend EVSE
GBT_StopSource = GBT_STOP_EVSE;
GBT_StopCauseCode = causecode;
if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP);
}
void GBT_StopOCPP(uint32_t causecode){ // --> Finished
GBT_StopSource = GBT_STOP_OCPP;
GBT_StopCauseCode = causecode;
if(GBT_State != GBT_STOP) GBT_SwitchState(GBT_STOP);
}
void GBT_ForceStop(){ // --> Suspend EV
GBT_StopSource = GBT_STOP_EV;
CONN.EnableOutput = 0;
GBT_SwitchState(GBT_COMPLETE);
GBT_Lock(0);
RELAY_Write(RELAY_AUX0, 0);
RELAY_Write(RELAY_AUX1, 0);
}
void GBT_Error(uint32_t errorcode){ // --> Suspend EV
GBT_StopSource = GBT_STOP_EV;
log_printf(LOG_ERR, "GBT Error code: 0x%X\n", errorcode);
GBT_ErrorCode = errorcode;
GBT_SwitchState(GBT_ERROR);
}
void GBT_ForceStop(){
GBT_EDCAN_Output.enablePSU = 0;
GBT_SwitchState(GBT_COMPLETE);
GBT_Lock(0);
RELAY_Write(RELAY_AUX, 0);
}
void GBT_Reset(){
GBT_last_BCL_BCS_BSM_tick = HAL_GetTick();
GBT_BAT_INFO_recv = 0;
GBT_BAT_STAT_recv = 0;
GBT_BRO_recv = 0;
GBT_BHM_recv = 0;
GBT_BSD_recv = 0;
EV_ready = 0;
CONN.SOC = 0;
CONN.EnableOutput = 0;
CONN.WantedCurrent = 0;
CONN.RequestedVoltage = 0;
memset(&GBT_EVInfo, 0, sizeof (GBT_EVInfo));
memset(&GBT_BATStat, 0, sizeof (GBT_BATStat));
memset(&GBT_ReqPower, 0, sizeof (GBT_ReqPower));
@@ -505,8 +567,11 @@ void GBT_Reset(){
GBT_CurrPower.requestedVoltage = 500; //50V
GBT_TimeChargingStarted = 0;
GBT_BRO = 0x00;
GBT_LockResetError();
}
void GBT_Start(){
RELAY_Write(RELAY_AUX, 1);
RELAY_Write(RELAY_AUX0, 1);
RELAY_Write(RELAY_AUX1, 1);
GBT_SwitchState(GBT_S3_STARTED);
}

View File

@@ -7,107 +7,148 @@
#include "connector.h"
#include "lock.h"
#include "board.h"
#include "debug.h"
CONN_State_t connectorState;
extern GBT_EDCAN_Output_t GBT_EDCAN_Output;
extern GBT_EDCAN_Input_t GBT_EDCAN_Input;
uint8_t CC_STATE_FILTERED;
extern uint8_t config_initialized;
void CONN_Init(){
CONN_SetState(CONN_Initializing);
}
gbtCcState_t CC_STATE_FILTERED;
void CONN_Task(){
switch (connectorState){
case CONN_Initializing: // unlocked
case Unknown: // unlocked, waiting for config
GBT_Lock(0);
CONN_SetState(CONN_Available);
GBT_LockState.error = 0;
break;
case CONN_Faulted: //unlocked
GBT_Lock(0);
break;
case CONN_Available: //unlocked, waiting to connect
GBT_Lock(0);
GBT_LockState.error = 0;
if((CONN_CC_GetState()==GBT_CC_4V) && (GBT_EDCAN_Input.chargeControl != FORCE_UNLOCK)){ // Исправить
CONN_SetState(CONN_Preparing);
GBT_Lock(1);
if (config_initialized) {
CONN_SetState(Unplugged);
}
break;
// Выйти из двух состояний в Finished если force unlock
case CONN_Preparing: //locked, waiting to charge
GBT_Lock(1);
case Disabled: // faulted, unlocked
GBT_Lock(0);
if(CONN.chargingError == 0) CONN_SetState(Unplugged);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
break;
case Unplugged: // unlocked, waiting to connect
GBT_Lock(0);
if(CONN.chargingError != 0) CONN_SetState(Disabled);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
if((CONN_CC_GetState()==GBT_CC_4V) && (CONN.connControl != CMD_FORCE_UNLOCK)){
CONN_SetState(AuthRequired);
GBT_Lock(0);
}
break;
case AuthRequired: // plugged, waiting to start charge
GBT_Lock(0);
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
if(CONN_CC_GetState()==GBT_CC_4V){
if(GBT_EDCAN_Input.chargeControl == CHARGING_ALLOWED){
// RELAY_Write(RELAY_AUX, 1);
// GBT_Start();
CONN_SetState(CONN_Charging);
if(CONN.connControl == CMD_START){
CONN_SetState(Preparing);
}
if(GBT_EDCAN_Input.chargeControl == FORCE_UNLOCK){
CONN_SetState(CONN_Available);//TODO: CONN_Occupied_complete
if(CONN.connControl == CMD_FORCE_UNLOCK){
CONN_SetState(Unplugged);
}
//if (CHARGING_NOT_ALLOWED) stay here
// if CHARGING_NOT_ALLOWED stay here
}else{
CONN_SetState(CONN_Available);
CONN_SetState(Unplugged);
}
break;
case CONN_Charging://charging, locked
case Preparing: // charging, locked
GBT_Lock(1);
if(GBT_State == GBT_COMPLETE){
CONN_SetState(CONN_Finishing);
if(GBT_StopSource == GBT_STOP_EVSE){
CONN_SetState(FinishedEVSE);
}else if(GBT_StopSource == GBT_STOP_EV){
CONN_SetState(FinishedEV);
}else if(GBT_StopSource == GBT_STOP_OCPP){
CONN_SetState(Finished);
}else{
CONN_SetState(FinishedEVSE);
}
}
if(GBT_State == GBT_S10_CHARGING){
CONN_SetState(Charging);
}
//
break;
case CONN_Finishing://charging completed, waiting to disconnect, unlocked
case Charging: // charging, locked
GBT_Lock(1);
if(GBT_State == GBT_COMPLETE){
if(GBT_StopSource == GBT_STOP_EVSE){
CONN_SetState(FinishedEVSE);
}else if(GBT_StopSource == GBT_STOP_EV){
CONN_SetState(FinishedEV);
}else if(GBT_StopSource == GBT_STOP_OCPP){
CONN_SetState(Finished);
}else{
CONN_SetState(FinishedEVSE);
}
}
break;
case FinishedEV: // charging completed by EV, waiting to transaction stop
GBT_Lock(0);
// RELAY_Write(RELAY_AUX, 0);
//TODO: Reconnection
// if(GBT_EDCAN_Input.chargeControl == CHARGING_NOT_ALLOWED){
// CONN_SetState(CONN_Initializing);
// }
if(CONN_CC_GetState()==GBT_CC_6V){
CONN_SetState(CONN_Initializing);
}
//Проблема, если нажать кнопку и не вынуть пистолет, то он снова блочится
CONN_SetState(Finished);
break;
case FinishedEVSE: // charging completed by EVSE, waiting to transaction stop
GBT_Lock(0);
CONN_SetState(Finished);
break;
case Finished: // charging completed, waiting to disconnect, unlocked
GBT_Lock(0);
//TODO Force unlock time limit
if(CONN.connControl == CMD_FORCE_UNLOCK) GBT_ForceLock(0);
if(CONN_CC_GetState()==GBT_CC_6V){
GBT_Lock(0);
CONN_SetState(Unplugged);
}
break;
default:
CONN_SetState(CONN_Initializing);
CONN_SetState(Unknown);
}
}
//external
//CONN_SetState(CONN_Error);
//CONN_SetState(CONN_Occupied_charging);
//CONN_SetState(CONN_Occupied_Complete);
//CONN_SetState(Disabled);
void CONN_SetState(CONN_State_t state){
connectorState = state;
if(connectorState == CONN_Initializing) printf ("CONN_Initializing\n");
if(connectorState == CONN_Faulted) printf ("CONN_Error\n");
if(connectorState == CONN_Available) printf ("CONN_Available\n");
if(connectorState == CONN_Preparing) printf ("CONN_Occupied_waiting\n");
if(connectorState == CONN_Charging) printf ("CONN_Occupied_charging\n");
if(connectorState == CONN_Finishing) printf ("CONN_Occupied_complete\n");
GBT_EDCAN_Output.connectorState = state;
if(connectorState == Unknown) log_printf(LOG_INFO, "Connector: Unknown\n");
if(connectorState == Unplugged) log_printf(LOG_INFO, "Connector: Unplugged\n");
if(connectorState == Disabled) log_printf(LOG_INFO, "Connector: Disabled\n");
if(connectorState == Preparing) log_printf(LOG_INFO, "Connector: Preparing\n");
if(connectorState == AuthRequired) log_printf(LOG_INFO, "Connector: AuthRequired\n");
if(connectorState == WaitingForEnergy) log_printf(LOG_INFO, "Connector: WaitingForEnergy\n");
if(connectorState == ChargingPausedEV) log_printf(LOG_INFO, "Connector: ChargingPausedEV\n");
if(connectorState == ChargingPausedEVSE) log_printf(LOG_INFO, "Connector: ChargingPausedEVSE\n");
if(connectorState == Charging) log_printf(LOG_INFO, "Connector: Charging\n");
if(connectorState == AuthTimeout) log_printf(LOG_INFO, "Connector: AuthTimeout\n");
if(connectorState == Finished) log_printf(LOG_INFO, "Connector: Finished\n");
if(connectorState == FinishedEVSE) log_printf(LOG_INFO, "Connector: FinishedEVSE\n");
if(connectorState == FinishedEV) log_printf(LOG_INFO, "Connector: FinishedEV\n");
if(connectorState == Replugging) log_printf(LOG_INFO, "Connector: Replugging\n");
CONN.connState = state;
}
void CONN_CC_ReadStateFiltered() {
static uint32_t last_change_time;
static uint32_t last_check_time;
static uint8_t prev_state;
static uint32_t last_change_time = 0;
static uint32_t last_check_time = 0;
static uint8_t prev_state = 0;
// if((last_check_time+100)>HAL_GetTick()) return;
if((HAL_GetTick()-last_check_time)<100) return;
last_check_time = HAL_GetTick();
@@ -120,64 +161,13 @@ void CONN_CC_ReadStateFiltered() {
} else if ((HAL_GetTick() - last_change_time) >= 300) {
CC_STATE_FILTERED = prev_state;
}
// switch(new_state){
// case GBT_CC_UNKNOWN:
// printf("GBT_CC_UNKNOWN\n");
// break;
// case GBT_CC_12V:
// printf("GBT_CC_12V\n");
// break;
// case GBT_CC_6V:
// printf("GBT_CC_6V\n");
// break;
// case GBT_CC_4V:
// printf("GBT_CC_4V\n");
// break;
// case GBT_CC_2V:
// printf("GBT_CC_2V\n");
// break;
//
// }
// switch(CONN_CC_GetState()){
// case GBT_CC_UNKNOWN:
// printf("FGBT_CC_UNKNOWN\n");
// break;
// case GBT_CC_12V:
// printf("FGBT_CC_12V\n");
// break;
// case GBT_CC_6V:
// printf("FGBT_CC_6V\n");
// break;
// case GBT_CC_4V:
// printf("FGBT_CC_4V\n");
// break;
// case GBT_CC_2V:
// printf("FGBT_CC_2V\n");
// break;
//
// }
}
uint8_t CONN_CC_GetState(){
return CC_STATE_FILTERED;
}
uint8_t CONN_CC_GetStateRaw(){
//Vref=3.3v = 4095
//k=1/11
//Vin = 12v
//Vin*k= 1.09v
//12vin = 1353 ADC
//TODO: Filter 100ms
uint32_t adc;
float volt;
ADC_Select_Channel(ADC_CHANNEL_6);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
adc = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
volt = (float)adc/113.4f;
float volt = CONN_CC_GetAdc();
// if((volt<12.6f) && (volt>11.4f)) return GBT_CC_12V;
// if((volt<6.8f) && (volt>5.2f)) return GBT_CC_6V;
// if((volt<4.8f) && (volt>3.2f)) return GBT_CC_4V;
@@ -199,7 +189,7 @@ float CONN_CC_GetAdc(){
uint32_t adc;
float volt;
ADC_Select_Channel(ADC_CHANNEL_6);
ADC_Select_Channel(ADC_CHANNEL_3);
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
adc = HAL_ADC_GetValue(&hadc1);

85
Core/Src/crc.c Normal file
View File

@@ -0,0 +1,85 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file crc.c
* @brief This file provides code for the configuration
* of the CRC instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "crc.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
CRC_HandleTypeDef hcrc;
/* CRC init function */
void MX_CRC_Init(void)
{
/* USER CODE BEGIN CRC_Init 0 */
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
void HAL_CRC_MspInit(CRC_HandleTypeDef* crcHandle)
{
if(crcHandle->Instance==CRC)
{
/* USER CODE BEGIN CRC_MspInit 0 */
/* USER CODE END CRC_MspInit 0 */
/* CRC clock enable */
__HAL_RCC_CRC_CLK_ENABLE();
/* USER CODE BEGIN CRC_MspInit 1 */
/* USER CODE END CRC_MspInit 1 */
}
}
void HAL_CRC_MspDeInit(CRC_HandleTypeDef* crcHandle)
{
if(crcHandle->Instance==CRC)
{
/* USER CODE BEGIN CRC_MspDeInit 0 */
/* USER CODE END CRC_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_CRC_CLK_DISABLE();
/* USER CODE BEGIN CRC_MspDeInit 1 */
/* USER CODE END CRC_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@@ -8,29 +8,156 @@
#include "main.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include "debug.h"
#include "board.h"
#include "charger_gbt.h"
#include "usart.h"
#include <time.h>
#include <connector.h>
#include "serial_control.h"
// Кольцевой буфер для отладочных сообщений
#define DEBUG_BUFFER_SIZE 1024
#define DEBUG_BUFFER_MAX_COUNT 128
typedef struct {
uint8_t buffer[DEBUG_BUFFER_SIZE];
volatile uint16_t write_index;
volatile uint16_t read_index;
volatile uint16_t count;
} DebugBuffer_t;
static DebugBuffer_t debug_buffer = {
.buffer = {0},
.write_index = 0,
.read_index = 0,
.count = 0
};
#if defined(__GNUC__)
int _write(int fd, char * ptr, int len)
{
debug_buffer_add((const uint8_t*)ptr, len);
return len;
}
#endif
// Добавляет данные в кольцевой буфер
void debug_buffer_add(const uint8_t* data, uint16_t len)
{
__disable_irq();
for (uint16_t i = 0; i < len; i++) {
// Если буфер полон, перезаписываем старые данные
if (debug_buffer.count >= DEBUG_BUFFER_SIZE) {
debug_buffer.read_index = (debug_buffer.read_index + 1) % DEBUG_BUFFER_SIZE;
debug_buffer.count--;
}
debug_buffer.buffer[debug_buffer.write_index] = data[i];
debug_buffer.write_index = (debug_buffer.write_index + 1) % DEBUG_BUFFER_SIZE;
debug_buffer.count++;
}
__enable_irq();
}
// Возвращает количество доступных данных в буфере
uint16_t debug_buffer_available(void)
{
__disable_irq();
uint16_t count = debug_buffer.count;
__enable_irq();
return count;
}
// Отправляет один пакет данных из буфера через SC_SendPacket (не более 250 байт)
void debug_buffer_send(void)
{
__disable_irq();
// Если буфер пуст, ничего не делаем
if (debug_buffer.count == 0) {
__enable_irq();
return;
}
// Определяем сколько байт можно отправить (не более 250)
uint16_t bytes_to_send = debug_buffer.count;
if (bytes_to_send > DEBUG_BUFFER_MAX_COUNT) {
bytes_to_send = DEBUG_BUFFER_MAX_COUNT;
}
// Вычисляем сколько байт до конца буфера
uint16_t bytes_to_end = DEBUG_BUFFER_SIZE - debug_buffer.read_index;
// Отправляем только непрерывный блок (до конца буфера или до bytes_to_send)
if (bytes_to_send > bytes_to_end) {
bytes_to_send = bytes_to_end;
}
// Отправляем данные напрямую из буфера
if(bytes_to_send == debug_buffer.count){
SC_SendPacket(&debug_buffer.buffer[debug_buffer.read_index], bytes_to_send, CMD_GET_LOG);
}else{
SC_SendPacket(&debug_buffer.buffer[debug_buffer.read_index], bytes_to_send, CMD_GET_LOG_CONTINUE);
}
debug_buffer.read_index = (debug_buffer.read_index + bytes_to_send) % DEBUG_BUFFER_SIZE;
debug_buffer.count -= bytes_to_send;
__enable_irq();
}
#define LOG_BUFFER_SIZE 128
uint8_t log_buffer[LOG_BUFFER_SIZE];
// Кастомный printf с приоритетом лога
int log_printf(LogLevel_t level, const char *format, ...)
{
va_list args;
int result;
// Добавляем приоритет первым байтом
log_buffer[0] = (uint8_t)level;
// Форматируем строку начиная со второго байта
va_start(args, format);
result = vsnprintf((char*)&log_buffer[1], LOG_BUFFER_SIZE - 2, format, args);
va_end(args);
// Проверяем, не переполнился ли буфер
if (result < 0) {
return result;
}
// Ограничиваем размер, чтобы оставить место для нуль-терминатора
if (result >= (LOG_BUFFER_SIZE - 2)) {
result = LOG_BUFFER_SIZE - 2;
}
// Добавляем нуль-терминатор в конец
log_buffer[result + 1] = '\0';
// Отправляем в буфер (приоритет + строка + нуль-терминатор)
debug_buffer_add(log_buffer, result + 2);
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;
extern UART_HandleTypeDef huart2;
#if defined(__GNUC__)
int _write(int fd, char * ptr, int len)
{
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, 1);
HAL_UART_Transmit(&huart2, (uint8_t *) ptr, len, HAL_MAX_DELAY);
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, 0);
return len;
}
#endif
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
@@ -50,12 +177,6 @@ void debug_rx_interrupt(UART_HandleTypeDef *huart, uint16_t Size){
void debug_init(){
HAL_UARTEx_ReceiveToIdle_IT(&huart2,debug_rx_buffer,255);
//mm_schedule_write(0x01, 0x0000, 0x0800);
// mm_schedule_write(0x02, 0x00FF, 0xFFFF);
//for (int i=0;i<60;i++)
// mm_schedule_write(0x02, 0x0000, 0xFF00);
// mm_schedule_write(0x01, 0x0000, 0x0100);
// mm_schedule_write(0x01, 0x0000, 0x0100);
}
void parse_command(uint8_t* buffer, size_t length) {
@@ -70,56 +191,61 @@ void parse_command(uint8_t* buffer, size_t length) {
}
if (buffer[0] == 0) return;
if (strncmp((const char*)buffer, "reset", length) == 0) {
printf("Resetting...\n");
log_printf(LOG_INFO, "Resetting...\n");
NVIC_SystemReset();
} else if (strncmp((const char*)buffer, "relayaux", length) == 0) {
printf("Relaying...\n");
log_printf(LOG_INFO, "Relaying...\n");
RELAY_Write(RELAY_AUX, 1);
HAL_Delay(200);
HAL_Delay(2000);
RELAY_Write(RELAY_AUX, 0);
} else if (strncmp((const char*)buffer, "relaycc", length) == 0) {
printf("Relaying...\n");
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, "voltage", length) == 0) {
// printf("Voltaging...\n");
// mm_schedule_read(0x02, 0x0001);
} 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) {
printf("CC1=%.2f\n", CONN_CC_GetAdc());
log_printf(LOG_INFO, "CC1=%.2f\n", CONN_CC_GetAdc());
} else if (strncmp((const char*)buffer, "lock_state", length) == 0) {
printf("Lock state=%d\n", GBT_LockGetState());
log_printf(LOG_INFO, "Lock state=%d\n", GBT_LockGetState());
} else if (strncmp((const char*)buffer, "lock_lock", length) == 0) {
printf("Locked\n");
log_printf(LOG_INFO, "Locked\n");
GBT_Lock(1);
} else if (strncmp((const char*)buffer, "lock_unlock", length) == 0) {
printf("Unlocked\n");
log_printf(LOG_INFO, "Unlocked\n");
GBT_Lock(0);
} else if (strncmp((const char*)buffer, "complete", length) == 0) {
CONN_SetState(CONN_Finishing);
CONN_SetState(Finished);
} else if (strncmp((const char*)buffer, "start", length) == 0) {
printf("Started\n");
log_printf(LOG_INFO, "Started\n");
GBT_Start();
} else if (strncmp((const char*)buffer, "stop", length) == 0) {
printf("Stopped\n");
GBT_Stop(GBT_CST_SUSPENDS_ARTIFICIALLY);
log_printf(LOG_INFO, "Stopped\n");
GBT_StopEVSE(GBT_CST_SUSPENDS_ARTIFICIALLY);
} else if (strncmp((const char*)buffer, "stop1", length) == 0) {
printf("Stopped\n");
log_printf(LOG_INFO, "Stopped\n");
GBT_ForceStop();
// } else if (strncmp((const char*)buffer, "force", length) == 0) {
// printf("Stopped\n");
// log_printf(LOG_INFO, "Stopped\n");
// GBT_Lock(1);
// GBT_SwitchState(GBT_S2_LOCKED);
// GBT_Delay(500);
@@ -127,81 +253,81 @@ void parse_command(uint8_t* buffer, size_t length) {
} else if (strncmp((const char*)buffer, "cc_state", length) == 0) {
switch(CONN_CC_GetState()){
case GBT_CC_UNKNOWN:
printf("GBT_CC_UNKNOWN\n");
log_printf(LOG_INFO, "GBT_CC_UNKNOWN\n");
break;
case GBT_CC_12V:
printf("GBT_CC_12V\n");
log_printf(LOG_INFO, "GBT_CC_12V\n");
break;
case GBT_CC_6V:
printf("GBT_CC_6V\n");
log_printf(LOG_INFO, "GBT_CC_6V\n");
break;
case GBT_CC_4V:
printf("GBT_CC_4V\n");
log_printf(LOG_INFO, "GBT_CC_4V\n");
break;
case GBT_CC_2V:
printf("GBT_CC_2V\n");
log_printf(LOG_INFO, "GBT_CC_2V\n");
break;
}
} else if (strncmp((const char*)buffer, "temp", length) == 0) {
printf("temp1 %d\n",GBT_ReadTemp(0));
printf("temp2 %d\n",GBT_ReadTemp(1));
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) {
printf("Battery info:\n");
printf("maxCV %dV\n",GBT_BATStat.maxCellVoltage/100); // 0.01v/bit
printf("maxCC %dA\n",GBT_BATStat.maxChargingCurrent/10); // 0.1A/bit
printf("totE %dkWh\n",GBT_BATStat.totalEnergy/10); // 0.1kWh
printf("maxCV %dV\n",GBT_BATStat.maxChargingVoltage/10); // 0.1V/ bit
printf("maxT %dC\n",(int16_t)GBT_BATStat.maxTemp-50); // 1C/bit, -50C offset
printf("SOC %dp\n",GBT_BATStat.SOC/10); // 0.1%/bit , 0..100%
printf("Volt. %dV\n",GBT_BATStat.measVoltage/10); // 0.1V/bit
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) {
printf("EV info:\n");
printf("GBT_ver V%d.%d%d\n",GBT_EVInfo.version[0],GBT_EVInfo.version[1],GBT_EVInfo.version[2]);
printf("Battery type: %d\n",GBT_EVInfo.batteryType);
printf("Battery capacity: %d\n", GBT_EVInfo.batteryCapacity); // 0.1Ah/bit
printf("Battery voltage: %d\n", GBT_EVInfo.batteryVoltage); // 0.1V/bit
printf("Battery vendor: %.4s\n", GBT_EVInfo.batteryVendor); // Battery vendor (ASCII string)
printf("Battery SN: %lu\n", GBT_EVInfo.batterySN); // int
printf("Battery manufacture date: %02d.%02d.%04d\n", GBT_EVInfo.batteryManuD, GBT_EVInfo.batteryManuM ,GBT_EVInfo.batteryManuY+1985); // year (offset 1985)
printf("Battery cycles: %d\n", GBT_EVInfo.batteryCycleCount); //uint24_t
printf("Own auto: %d\n", GBT_EVInfo.ownAuto); // 0 = lizing, 1 = own auto
printf("EVIN: %.17s\n", GBT_EVInfo.EVIN); //EVIN
printf("EV_SW_VER: %.8s\n", GBT_EVInfo.EV_SW_VER);
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) {
printf("GBT_MaxLoad info:\n");
printf("Output max current: %d\n",GBT_MaxLoad.maxOutputCurrent);
printf("Output min current: %d\n",GBT_MaxLoad.minOutputCurrent);
printf("Output max voltage: %d\n",GBT_MaxLoad.maxOutputVoltage);
printf("Output min voltage: %d\n",GBT_MaxLoad.minOutputVoltage);
printf("\nGBT_ChargerInfo info:\n");
printf("BMS Recognized: %d\n",GBT_ChargerInfo.bmsIdentified);
printf("Charger location: %.3s\n",GBT_ChargerInfo.chargerLocation);
printf("Charger number: %lu\n",GBT_ChargerInfo.chargerNumber);
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) {
printf("Command list:\n");
printf("reset\n");
printf("help\n");
printf("cc_state\n");
printf("lock_lock\n");
printf("lock_unlock\n");
printf("lock_state\n");
printf("adc\n");
printf("relay(cc,aux)\n");
printf("start\n");
printf("stop\n");
printf("stop1\n");
// printf("force\n");
printf("temp\n");
printf("info1\n");
printf("info2\n");
printf("info3\n");
printf("time\n");
printf("cantest\n");
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
@@ -210,20 +336,20 @@ void parse_command(uint8_t* buffer, size_t length) {
time_t unix_time = (time_t)get_Current_Time();
struct tm *parts = localtime(&unix_time);
printf("Year: %d\n", parts->tm_year + 1900);
printf("Month: %d\n", parts->tm_mon + 1);
printf("Day: %d\n", parts->tm_mday);
printf("Hour: %d\n", parts->tm_hour);
printf("Minute: %d\n", parts->tm_min);
printf("Second: %d\n", parts->tm_sec);
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
printf("can test\n");
log_printf(LOG_INFO, "can test\n");
} else {
printf("Unknown command\n");
log_printf(LOG_INFO, "Unknown command\n");
}
}
@@ -234,3 +360,7 @@ void debug_task(){
debug_cmd_received = 0;
}
}
#else
#endif // USE_WEB_INTERFACE

View File

@@ -1,242 +0,0 @@
/*
* edcan_handler.c
*
* В этом файле расположены обработчики приходящих пакетов для пользовательских регистров
*
* Created on: Jul 5, 2024
* Author: colorbass
*/
#include <edcan.h>
#include "stdio.h"
#include "soft_rtc.h"
#include "charger_gbt.h"
// * здесь объявлять внешние устройства и их регистры *
//uint8_t edcan_register_BMS[256];//300...3FF
////meter registers
//#define EDCAN_ID_METER 0x10
//#define EDCAN_REG_METER_VOLTAGE 0x03
//#define EDCAN_REG_METER_CURRENT 0x04
//own registers
#define EDCAN_REG_CHARGER_ENABLE 0x100
/* Charger info registers */
#define EDCAN_REG_CHARGER_INFO 0x200
//UNIX TIME
#define EDCAN_REG_TIME_0 0x210
#define EDCAN_REG_TIME_1 0x211
#define EDCAN_REG_TIME_2 0x212
#define EDCAN_REG_TIME_3 0x213
#define EDCAN_REG_MAX_LOAD 0x220
#define EDCAN_REG_BRM 0x310
#define EDCAN_REG_BCP 0x350
#define EDCAN_REG_BRO 0x35F
#define EDCAN_REG_BCL 0x360
#define EDCAN_REG_BCS 0x370
#define EDCAN_REG_BSM 0x380
#define EDCAN_REG_OUTPUT 0x500
GBT_EDCAN_Output_t GBT_EDCAN_Output;
#define EDCAN_REG_INPUT 0x580
GBT_EDCAN_Input_t GBT_EDCAN_Input;
/**
* @brief Handler for incoming Read packet
* Another device reply value of its registers
*
* @param SourceID: Packet Source ID
* DestinationID: Packet Destination ID
* Addr: First register address in sequence
* *data: pointer for data array
* len: length of data (1..255)
*/
void EDCAN_ReadHandler(uint8_t SourceID, uint8_t DestinationID, uint16_t Addr, uint8_t *data, uint8_t len){
//Получили пакет Read (запрошенное значение регистров)
// printf("Received packet: Read\n");
// printf("Source ID = %d\n", SourceID);
// printf("Destination ID = %d\n", DestinationID);
// printf("Address = %d\n", Addr);
// printf("Len = %d\n", len);
// printf("\n");
for (uint16_t AddrOffset = 0; AddrOffset < len; AddrOffset++){ //по очереди перебираем все полученные регистры через Handler
// * добавить сюда новые устройства *
// if(SourceID == EDCAN_ID_METER){
// printf ("register[%d] = %d\n", Addr+AddrOffset, data[AddrOffset]);
// switch(Addr+AddrOffset){
//
// // * добавить сюда внешние регистры этого устройства *
// case EDCAN_REG_METER_VOLTAGE:
// printf ("Voltage = %d\n", data[AddrOffset]);
// break;
//
// case EDCAN_REG_METER_CURRENT:
// printf ("Current = %d\n", data[AddrOffset]);
// break;
// default:
// printf ("Unknown register\n");
// }
// }
}
// printf("\n");
}
/**
* @brief Handler for incoming Read packet
* Another device reply value of its registers
*
* @param SourceID: Packet Source ID
* DestinationID: Packet Destination ID
* Addr: First register address in sequence
* *data: pointer for data array
* len: length of data (1..255)
*/
void EDCAN_WriteUserRegister(uint16_t addr, uint8_t value){
switch(addr){
//edcan_register[addr] = value;
// case EDCAN_REG_K0:
// printf ("K0 = %d\n", value);
// HAL_GPIO_WritePin (K0_GPIO_Port, K0_Pin, (value == 0));
// break;
// case EDCAN_REG_CHARGER_ENABLE:
// if(value)GBT_Charger_Enable = 1;
// else GBT_Charger_Enable = 0;
// break;
case EDCAN_REG_TIME_0:
writeTimeReg(0, value);
break;
case EDCAN_REG_TIME_1:
writeTimeReg(1, value);
break;
case EDCAN_REG_TIME_2:
writeTimeReg(2, value);
break;
case EDCAN_REG_TIME_3:
writeTimeReg(3, value);
break;
//0x220
case EDCAN_REG_MAX_LOAD ... (EDCAN_REG_MAX_LOAD+sizeof(GBT_CML_t)):
((uint8_t*)&GBT_MaxLoad)[addr - EDCAN_REG_MAX_LOAD] = value;
break;
//0x200
case EDCAN_REG_CHARGER_INFO ... (EDCAN_REG_CHARGER_INFO+sizeof(GBT_CRM_t)):
((uint8_t*)&GBT_ChargerInfo)[addr - EDCAN_REG_CHARGER_INFO] = value;
break;
//0x580
case EDCAN_REG_INPUT ... (EDCAN_REG_INPUT+sizeof(GBT_EDCAN_Input_t)):
((uint8_t*)&GBT_EDCAN_Input)[addr - EDCAN_REG_INPUT] = value;
//TODO
//GBT_EDCAN_Input.measuredCurrent;
break;
default:
printf ("Unknown register\n");
}
}
uint8_t EDCAN_GetUserRegisterValue(uint16_t addr){
switch (addr){
// /* регистры 256..2047 используются пользовательских нужд */
// 0x400
case EDCAN_REG_TIME_0:
return getTimeReg(0);
break;
case EDCAN_REG_TIME_1:
return getTimeReg(1);
break;
case EDCAN_REG_TIME_2:
return getTimeReg(2);
break;
case EDCAN_REG_TIME_3:
return getTimeReg(3);
break;
//0x220
case EDCAN_REG_MAX_LOAD ... (EDCAN_REG_MAX_LOAD+sizeof(GBT_CML_t)):
return ((uint8_t*)&GBT_MaxLoad)[addr - EDCAN_REG_MAX_LOAD];
//0x310
case EDCAN_REG_BRM ... (EDCAN_REG_BRM+sizeof(GBT_BRM_t)-1):
return ((uint8_t*)&GBT_EVInfo)[addr - EDCAN_REG_BRM];
//0x340
case EDCAN_REG_BCP ... (EDCAN_REG_BCP+sizeof(GBT_BCP_t)):
return ((uint8_t*)&GBT_BATStat)[addr - EDCAN_REG_BCP];
//0x34F
case EDCAN_REG_BRO:
return GBT_BRO;
//0x350
case EDCAN_REG_BCL ... (EDCAN_REG_BCL+sizeof(GBT_BCL_t)):
return ((uint8_t*)&GBT_ReqPower)[addr - EDCAN_REG_BCL];
//0x360
case EDCAN_REG_BCS ... (EDCAN_REG_BCS+sizeof(GBT_BCS_t)):
return ((uint8_t*)&GBT_ChargingStatus)[addr - EDCAN_REG_BCS];
//0x370
case EDCAN_REG_BSM ... (EDCAN_REG_BSM+sizeof(GBT_BSM_t)):
return ((uint8_t*)&GBT_BatteryStatus)[addr - EDCAN_REG_BSM];
//0x500
case EDCAN_REG_OUTPUT ... (EDCAN_REG_OUTPUT+sizeof(GBT_EDCAN_Output_t)):
return ((uint8_t*)&GBT_EDCAN_Output)[addr - EDCAN_REG_OUTPUT];
//0x580
case EDCAN_REG_INPUT ... (EDCAN_REG_INPUT+sizeof(GBT_EDCAN_Input_t)):
return ((uint8_t*)&GBT_EDCAN_Input)[addr - EDCAN_REG_INPUT];
default:
return 0x00;
}
}

78
Core/Src/gpio.c Executable file → Normal file
View File

@@ -38,6 +38,8 @@
* Output
* EVENT_OUT
* EXTI
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
void MX_GPIO_Init(void)
{
@@ -54,54 +56,94 @@ void MX_GPIO_Init(void)
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, LOCK_A_Pin|LOCK_B_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOE, RELAY1_Pin|RELAY2_Pin|RELAY3_Pin|RELAY4_Pin
|RELAY5_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(RELAY_CC_GPIO_Port, RELAY_CC_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOD, RELAY_DC_Pin|USART2_DIR_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(RELAY_AUX_GPIO_Port, RELAY_AUX_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(EE_WP_GPIO_Port, EE_WP_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : PCPin PCPin */
/*Configure GPIO pin : IN_SW0_Pin */
GPIO_InitStruct.Pin = IN_SW0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(IN_SW0_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : IN_SW1_Pin */
GPIO_InitStruct.Pin = IN_SW1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(IN_SW1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : LOCK_A_Pin LOCK_B_Pin */
GPIO_InitStruct.Pin = LOCK_A_Pin|LOCK_B_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = LOCK_FB_Pin;
/*Configure GPIO pins : IN0_Pin AC_OK_Pin ISO_IN_Pin */
GPIO_InitStruct.Pin = IN0_Pin|AC_OK_Pin|ISO_IN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(LOCK_FB_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PEPin PEPin */
GPIO_InitStruct.Pin = ADDR_0_Pin|ADDR_1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
/*Configure GPIO pins : RELAY1_Pin RELAY2_Pin RELAY3_Pin RELAY4_Pin
RELAY5_Pin */
GPIO_InitStruct.Pin = RELAY1_Pin|RELAY2_Pin|RELAY3_Pin|RELAY4_Pin
|RELAY5_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
/*Configure GPIO pin : RELAY_CC_Pin */
GPIO_InitStruct.Pin = RELAY_CC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(RELAY_CC_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = USART2_DIR_Pin;
/*Configure GPIO pins : RELAY_DC_Pin USART2_DIR_Pin */
GPIO_InitStruct.Pin = RELAY_DC_Pin|USART2_DIR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(USART2_DIR_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = RELAY_AUX_Pin;
/*Configure GPIO pin : IN_ESTOP_Pin */
GPIO_InitStruct.Pin = IN_ESTOP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(IN_ESTOP_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : IN_FB2_Pin IN_FB1_Pin */
GPIO_InitStruct.Pin = IN_FB2_Pin|IN_FB1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : EE_WP_Pin */
GPIO_InitStruct.Pin = EE_WP_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(RELAY_AUX_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(EE_WP_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PB8 PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure peripheral I/O remapping */
__HAL_AFIO_REMAP_I2C1_ENABLE();
}

View File

@@ -10,7 +10,7 @@
#include "charger_gbt.h"
#include "string.h"
#include "can.h"
#include "edcan.h"
#include "debug.h"
extern GBT_BCL_t GBT_ReqPower;
extern GBT_BCL_t GBT_CurrPower;
@@ -79,18 +79,21 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
case 0x1E00: //PGN BEM (ERROR)
//Error force stop
EDCAN_printf(LOG_WARN, "BEM Received, force stopping...\n");
EDCAN_printf(LOG_WARN, "BEM: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
// --> Suspend EV
log_printf(LOG_ERR, "BEM Received, force stopping...\n");
log_printf(LOG_ERR, "BEM: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
log_printf(LOG_ERR, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_ForceStop();
break;
case 0x1900: //PGN BST (STOP)
//Normal stop
EDCAN_printf(LOG_WARN, "BST Received, stopping...\n");
EDCAN_printf(LOG_WARN, "BST: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
EDCAN_printf(LOG_WARN, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_Stop(GBT_CST_BMS_ACTIVELY_SUSPENDS);
// --> Suspend EV
log_printf(LOG_INFO, "BST Received, stopping...\n");
log_printf(LOG_INFO, "BST: %02X %02X %02X %02X", RxData[0], RxData[1], RxData[2], RxData[3]);
log_printf(LOG_INFO, " %02X %02X %02X %02X\n", RxData[4], RxData[5], RxData[6], RxData[7]);
GBT_StopEV(GBT_CST_BMS_ACTIVELY_SUSPENDS);
break;
@@ -114,9 +117,9 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
void GBT_CAN_ReInit(){
HAL_CAN_Stop(&hcan1);
MX_CAN1_Init();
GBT_CAN_FilterInit();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
GBT_CAN_FilterInit();
}
void J_SendPacket(uint32_t PGN, uint8_t pri, uint8_t DLC, uint8_t *data){

View File

@@ -5,45 +5,37 @@
* Author: colorbass
*/
#include "lock.h"
#include "debug.h"
uint8_t LOCK_POLARITY = 1;
uint8_t LOCK_POLARITY = 1; // 1 for v1
uint8_t LOCK_MOTOR_POLARITY = 1;
uint8_t LOCK_DELAY = 50;
uint16_t LOCK_DELAY = 100;
GBT_LockState_t GBT_LockState;
GBT_LockState_t GBT_LockState = {
.demand = 0,
.error = 0,
.action_requested = 255, // нет запрошенного действия
.motor_state = 0, // idle
.last_action_time = 0,
.retry_count = 0,
.error_tick = 0
};
void GBT_ForceLock(uint8_t state){
if(LOCK_MOTOR_POLARITY){
if(state){//LOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
HAL_Delay(LOCK_DELAY);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
}else{ //UNLOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
HAL_Delay(LOCK_DELAY);
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
}
}else{
if(state){//LOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
HAL_Delay(LOCK_DELAY);
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
}else{ //UNLOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
HAL_Delay(LOCK_DELAY);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
}
}
// Устанавливаем флаг для выполнения действия
GBT_LockState.action_requested = state ? 1 : 0;
GBT_LockState.retry_count = 0;
}
uint8_t GBT_LockGetState(){
//1 = locked
//0 = unlocked
if(LOCK_POLARITY){
return HAL_GPIO_ReadPin(LOCK_FB_GPIO_Port, LOCK_FB_Pin);
return HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
}else{
return !HAL_GPIO_ReadPin(LOCK_FB_GPIO_Port, LOCK_FB_Pin);
return !HAL_GPIO_ReadPin(IN0_GPIO_Port, IN0_Pin);
}
}
@@ -52,37 +44,126 @@ void GBT_Lock(uint8_t state){
GBT_LockState.demand = state;
}
void GBT_ManageLock(){
uint8_t MAX_RETRIES = 5;
if (GBT_LockState.error) {
return;
}
void GBT_ManageLockSolenoid(){
static uint32_t tick;
if(HAL_GetTick() - tick < 50) return;
tick = HAL_GetTick();
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, GBT_LockState.demand ? 1 : 0);
}
void GBT_ManageLockMotor(){
static const uint8_t MAX_RETRIES = 5;
uint32_t current_tick = HAL_GetTick();
// Проверяем таймаут сброса ошибки (до проверки error, чтобы можно было сбросить)
GBT_ResetErrorTimeout();
if (GBT_LockState.error) {
return;
}
// Проверяем, нужно ли выполнить действие
bool lock_is_open = GBT_LockGetState() == 0;
bool lock_should_be_open = GBT_LockState.demand == 0;
uint8_t retry_count = 0;
if (lock_is_open != lock_should_be_open) {
while (retry_count < MAX_RETRIES) {
if (lock_should_be_open) {
GBT_ForceLock(0);
} else {
GBT_ForceLock(1);
}
lock_is_open = GBT_LockGetState() == 0;
if (lock_is_open == lock_should_be_open) {
break;
}
retry_count++;
// Если есть запрошенное действие или состояние не соответствует требуемому
if (GBT_LockState.action_requested != 255 || (lock_is_open != lock_should_be_open)) {
// Если действие еще не запрошено, запрашиваем его
if (GBT_LockState.action_requested == 255) {
GBT_LockState.action_requested = lock_should_be_open ? 0 : 1;
GBT_LockState.retry_count = 0;
}
// Управление мотором через машину состояний
switch (GBT_LockState.motor_state) {
case 0: // idle - мотор выключен
// Определяем, какой пин нужно включить
if (LOCK_MOTOR_POLARITY) {
if (GBT_LockState.action_requested == 1) { // LOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
} else { // UNLOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
}
} else {
if (GBT_LockState.action_requested == 1) { // LOCK
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 1);
} else { // UNLOCK
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 1);
}
}
GBT_LockState.motor_state = 1; // motor_on
GBT_LockState.last_action_time = current_tick;
break;
case 1: // motor_on - мотор включен, ждем LOCK_DELAY
if (current_tick - GBT_LockState.last_action_time >= LOCK_DELAY) {
// Выключаем оба пина
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
GBT_LockState.motor_state = 2; // waiting_off
GBT_LockState.last_action_time = current_tick;
}
break;
case 2: // waiting_off - ждем немного перед проверкой состояния
// Небольшая задержка перед проверкой состояния (например, 50мс)
if (current_tick - GBT_LockState.last_action_time >= 50) {
// Проверяем, достигнуто ли требуемое состояние
lock_is_open = GBT_LockGetState() == 0;
bool action_success = (lock_is_open == (GBT_LockState.action_requested == 0));
if (action_success) {
// Действие выполнено успешно
GBT_LockState.action_requested = 255; // сбрасываем флаг
GBT_LockState.motor_state = 0; // idle
GBT_LockState.retry_count = 0;
} else {
// Действие не выполнено, повторяем попытку
GBT_LockState.retry_count++;
if (GBT_LockState.retry_count >= MAX_RETRIES) {
// Превышено количество попыток
GBT_LockState.error = 1;
GBT_LockState.error_tick = current_tick; // сохраняем время установки ошибки
GBT_LockState.action_requested = 0; // пытаемся разблокировать
GBT_LockState.motor_state = 0;
GBT_LockState.retry_count = 0;
log_printf(LOG_ERR, "Lock error\n");
} else {
// Повторяем попытку
GBT_LockState.motor_state = 0; // возвращаемся к началу
}
}
}
break;
}
} else {
// Состояние соответствует требуемому, сбрасываем флаги
if (GBT_LockState.motor_state != 0) {
HAL_GPIO_WritePin(LOCK_A_GPIO_Port, LOCK_A_Pin, 0);
HAL_GPIO_WritePin(LOCK_B_GPIO_Port, LOCK_B_Pin, 0);
GBT_LockState.motor_state = 0;
}
GBT_LockState.action_requested = 255;
GBT_LockState.retry_count = 0;
}
}
if (retry_count >= MAX_RETRIES) {
GBT_LockState.error = 1;
GBT_ForceLock(0);
printf ("Lock error\n");
void GBT_LockResetError(){
GBT_LockState.error = 0;
GBT_LockState.error_tick = 0;
log_printf(LOG_INFO, "Lock error reset\n");
}
void GBT_ResetErrorTimeout(){
static const uint32_t ERROR_TIMEOUT_MS = 300000; // 5 минут
if (GBT_LockState.error && GBT_LockState.error_tick != 0) {
if ((HAL_GetTick()-GBT_LockState.error_tick) >= ERROR_TIMEOUT_MS) {
// Прошло 5 минут, сбрасываем ошибку
GBT_LockResetError();
}
}
}

139
Core/Src/main.c Executable file → Normal file
View File

@@ -1,26 +1,12 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "can.h"
#include "crc.h"
#include "rtc.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
@@ -35,6 +21,8 @@
#include "j1939.h"
#include "lock.h"
#include "connector.h"
#include "serial_control.h"
#include "charger_config.h"
/* USER CODE END Includes */
@@ -46,8 +34,6 @@
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#include "edcan_config.h"
#include "edcan_defines.h"
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
@@ -70,6 +56,70 @@ void SystemClock_Config(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/**
* @brief Vector base address configuration. It should no longer be at the start of
* flash memory but moved forward because the first part of flash is
* reserved for the bootloader. Note that this is already done by the
* bootloader before starting this program. Unfortunately, function
* SystemInit() overwrites this change again.
* @return none.
*/
static void VectorBase_Config(void)
{
/* The constant array with vectors of the vector table is declared externally in the
* c-startup code.
*/
extern const unsigned long g_pfnVectors[];
/* Remap the vector table to where the vector table is located for this program. */
SCB->VTOR = (unsigned long)&g_pfnVectors[0];
}
uint8_t ED_TraceWarning(uint8_t flag, uint8_t id){
static uint8_t memory[32];
if(id > 31) return 0;
uint8_t result = 0;
if(memory[id] != flag){
result = 1;
}
memory[id] = flag;
return result;
}
void ED_Delay(uint32_t Delay)
{
uint32_t tickstart = HAL_GetTick();
uint32_t wait = Delay;
/* Add a freq to guarantee minimum wait */
if (wait < HAL_MAX_DELAY)
{
wait += (uint32_t)(uwTickFreq);
}
while ((HAL_GetTick() - tickstart) < wait){
CONN_CC_ReadStateFiltered();
GBT_ManageLockMotor();
CONN_Task();
GBT_ChargerTask();
LED_Task();
SC_Task();
// if(huart2.gState != HAL_UART_STATE_BUSY_TX) debug_buffer_send(); // TEST
}
}
void StopButtonControl(){
//Charging do nothing
if(!IN_ReadInput(IN_ESTOP)){
CONN.connControl = CMD_STOP;
}
}
uint8_t temp0, temp1;
/* USER CODE END 0 */
/**
@@ -78,8 +128,9 @@ void SystemClock_Config(void);
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE BEGIN 1 */
VectorBase_Config();
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
@@ -88,7 +139,7 @@ int main(void)
HAL_Init();
/* USER CODE BEGIN Init */
HAL_RCC_DeInit();
/* USER CODE END Init */
/* Configure the system clock */
@@ -103,24 +154,30 @@ int main(void)
MX_ADC1_Init();
MX_CAN1_Init();
MX_CAN2_Init();
MX_USART2_UART_Init();
MX_RTC_Init();
MX_TIM4_Init();
MX_USART2_UART_Init();
MX_CRC_Init();
MX_UART5_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
/* USER CODE BEGIN 2 */
CAN_ReInit();
Init_Peripheral();
LED_Init();
HAL_Delay(300);
GBT_Init();
set_Time(1721651966);
printf("Startup (type \'help\' for command list)\n");
debug_init();
EDCAN_Init(SW_GetAddr()); //0x20..0x23
EDCAN_printf(LOG_INFO, "Startup\n");
//EDCAN_Init(0x20); //Адрес EDCAN
SC_Init();
log_printf(LOG_INFO, "GBT Charger v%d.%d\n", GBT_CH_VER_MAJOR, GBT_CH_VER_MINOR);
ReadVersion();
log_printf(LOG_INFO, "Serial number: %d\n", infoPacket.serialNumber);
log_printf(LOG_INFO, "Board revision: %d\n", infoPacket.boardVersion);
log_printf(LOG_INFO, "FW version: %d.%d.%d\n", infoPacket.fw_version_major, infoPacket.fw_version_minor, infoPacket.fw_version_patch);
GBT_SetConfig();
GBT_CAN_ReInit();
CAN_ReInit();
PSU_Init();
CONN_Init();
/* USER CODE END 2 */
/* Infinite loop */
@@ -130,14 +187,17 @@ int main(void)
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// HAL_Delay(1);
EDCAN_Loop();
//can_task();
debug_task();
CONN_CC_ReadStateFiltered();
GBT_ManageLock();
CONN_Task();
GBT_ChargerTask();
PSU_ReadWrite();
PSU_Task();
ED_Delay(10);
METER_CalculateEnergy();
CONN_Loop();
LED_Write();
ED_Delay(10);
StopButtonControl();
ED_Delay(50);
}
/* USER CODE END 3 */
@@ -217,8 +277,7 @@ void Error_Handler(void)
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.

54
Core/Src/meter.c Executable file
View File

@@ -0,0 +1,54 @@
/*
* meter.c
*
* Created on: 27 сент. 2024 г.
* Author: root
*/
#include "meter.h"
#include "charger_config.h"
#include "charger_control.h"
METER_t METER;
// Функция для расчета и накопления энергии c дробной частью без счетчиков
void METER_CalculateEnergy() {
// Проверяем, что индекс находится в пределах массива
METER.online = 0;
if(CONN.connState == Charging){
METER.enable = 1;
}else{
METER.enable = 0;
}
uint32_t currentTick = HAL_GetTick(); // Получаем текущее время в миллисекундах
uint32_t elapsedTimeMs = currentTick - METER.lastTick; // Вычисляем время, прошедшее с последнего вызова в секундах
METER.lastTick = currentTick; // Обновляем время последнего вызова для текущего коннектора
uint32_t energyWs = CONN.Power * elapsedTimeMs / 1000; // Рассчитываем энергию в ватт-секундах за прошедший промежуток времени
//Расчет энергии теперь идет всегда, смещение берем суммарное
METER.EnergyPSU_Ws += energyWs;
// Абсолютное значение энергии разъема складывается из накопленной дробной части и значения со счетчиков
METER.AbsoluteEnergy = (uint32_t)METER.EnergyPSU_Ws/3600; //переводим в Вт*час
if(METER.enable) {
//enabled state
CONN.Energy = METER.AbsoluteEnergy - METER.EnergyOffset;//переводим в Вт*час
}else{
// Reset statе
CONN.Energy = 0;
METER.EnergyOffset = METER.AbsoluteEnergy;
}
}

448
Core/Src/psu_control.c Executable file
View File

@@ -0,0 +1,448 @@
#include <psu_control.h>
#include "can.h"
#include "string.h"
#include "stdio.h"
#include "charger_config.h"
#include "charger_control.h"
#include "charger_gbt.h"
#include "board.h"
#include "debug.h"
PSU_02_t PSU_02;
PSU_04_t PSU_04;
PSU_06_t PSU_06;
PSU_08_t PSU_08;
PSU_09_t PSU_09;
PSU_1A_t PSU_1A;
PSU_1B_t PSU_1B;
PSU_1C_t PSU_1C;
PSU_t PSU0;
#define CAN_DELAY 20
#define PSU_VOLTAGE_THRESHOLD 20 // Порог напряжения для определения состояния (В)
#define PSU_ONLINE_TIMEOUT 500 // Таймаут для определения состояния (мс)
#define PSU_STARTUP_DELAY 4000 // Задержка 2 секунды перед включением
uint32_t can_lastpacket;
extern CAN_HandleTypeDef hcan2;
static void PSU_SwitchState(PSU_State_t state){
PSU0.state = state;
PSU0.statetick = HAL_GetTick();
}
static uint32_t PSU_StateTime(void){
return HAL_GetTick() - PSU0.statetick;
}
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan){
static CAN_RxHeaderTypeDef RxHeader;
static uint8_t RxData[8] = {0,};
CanId_t CanId;
if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO1, &RxHeader, RxData) == HAL_OK)
{
memcpy(&CanId, &RxHeader.ExtId, sizeof(CanId_t));
/* Для DC30 поддерживается только один силовой модуль (source == 0) */
if(CanId.source != 0) return;
can_lastpacket = HAL_GetTick();
if(CanId.command==0x02){
memcpy(&PSU_02, RxData, 8);
}
if(CanId.command==0x04){
memcpy(&PSU_04, RxData, 8);
PSU0.tempAmbient = PSU_04.moduleTemperature;
PSU0.status0.raw = PSU_04.modularForm0;
PSU0.status1.raw = PSU_04.modularForm1;
PSU0.status2.raw = PSU_04.modularForm2;
}
if(CanId.command==0x06){
memcpy(&PSU_06, RxData, 8);
PSU_06.VAB = PSU_06.VABLo+(PSU_06.VABHi<<8);
PSU_06.VBC = PSU_06.VBCLo+(PSU_06.VBCHi<<8);
PSU_06.VCA = PSU_06.VCALo+(PSU_06.VCAHi<<8);
}
if(CanId.command==0x08){
memcpy(&PSU_08, RxData, 8);
}
if(CanId.command==0x09){
memcpy(&PSU_09, RxData, 8);
PSU_09.moduleNCurrent = PSU_09.moduleNCurrent_[3];
PSU_09.moduleNCurrent |= PSU_09.moduleNCurrent_[2]<<8;
PSU_09.moduleNCurrent |= PSU_09.moduleNCurrent_[1]<<16;
PSU_09.moduleNCurrent |= PSU_09.moduleNCurrent_[0]<<24;
PSU_09.moduleNVoltage = PSU_09.moduleNVoltage_[3];
PSU_09.moduleNVoltage |= PSU_09.moduleNVoltage_[2]<<8;
PSU_09.moduleNVoltage |= PSU_09.moduleNVoltage_[1]<<16;
PSU_09.moduleNVoltage |= PSU_09.moduleNVoltage_[0]<<24;
// PSU_09 -> PSU -> CONN (один модуль)
{
uint16_t v = PSU_09.moduleNVoltage / 1000;
int16_t i = PSU_09.moduleNCurrent / 100;
// Обновляем модель PSU0 по телеметрии
PSU0.outputVoltage = v;
PSU0.outputCurrent = i;
PSU0.PSU_enabled = (v >= PSU_VOLTAGE_THRESHOLD);
PSU0.online = 1;
PSU0.temperature = PSU_04.moduleTemperature;
// Экспортируем значения из PSU0 в CONN только,
// когда модуль хотя бы в состоянии READY и выше
if(PSU0.state >= PSU_READY){
CONN.MeasuredVoltage = PSU0.outputVoltage;
CONN.MeasuredCurrent = PSU0.outputCurrent;
CONN.Power = CONN.MeasuredCurrent * CONN.MeasuredVoltage / 10;
CONN.outputEnabled = PSU0.PSU_enabled;
}
}
}
}
}
void PSU_CAN_FilterInit(){
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 14;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO1;
sFilterConfig.SlaveStartFilterBank = 14;
if(HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
{
Error_Handler();
}
}
void PSU_Init(){
HAL_CAN_Stop(&hcan2);
MX_CAN2_Init();
PSU_CAN_FilterInit();
HAL_CAN_Start(&hcan2);
HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO1_MSG_PENDING /* | CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_LAST_ERROR_CODE | CAN_IT_TX_MAILBOX_EMPTY*/);
memset(&PSU0, 0, sizeof(PSU0));
PSU0.state = PSU_UNREADY;
PSU0.statetick = HAL_GetTick();
PSU0.power_limit = PSU_MAX_POWER; // kW
PSU0.hv_mode = 0;
PSU_Enable(0, 0);
}
void PSU_Enable(uint8_t addr, uint8_t enable){
PSU_1A_t data;
memset(&data, 0, sizeof(data));
/* Для DC30 поддерживается только один модуль с адресом 0 */
if(addr != 0) return;
if(PSU0.online == 0) return;
data.enable = !enable;
PSU_SendCmd(0xF0, addr, 0x1A, &data);
ED_Delay(CAN_DELAY);
}
void PSU_SetHVMode(uint8_t addr, uint8_t enable){
PSU_1D_t data;
memset(&data, 0, sizeof(data));
data.enable = !enable;
if(addr != 0) return;
PSU_SendCmd(0xF0, addr, 0x1D, &data);
}
void PSU_SetVoltageCurrent(uint8_t addr, uint16_t voltage, uint16_t current){
PSU_1C_t data;
memset(&data, 0, sizeof(data));
if(addr != 0) return;
if(voltage<PSU_MIN_VOLTAGE) voltage = PSU_MIN_VOLTAGE;
if((PSU0.hv_mode==0) && voltage>499) voltage = 499;
uint32_t current_ma = current * 100;
uint32_t voltage_mv = voltage * 1000;
data.moduleCurrentTotal[0] = (current_ma >> 24) & 0xFF;
data.moduleCurrentTotal[1] = (current_ma >> 16) & 0xFF;
data.moduleCurrentTotal[2] = (current_ma >> 8) & 0xFF;
data.moduleCurrentTotal[3] = (current_ma >> 0) & 0xFF;
data.moduleVoltage[0] = (voltage_mv >> 24) & 0xFF;
data.moduleVoltage[1] = (voltage_mv >> 16) & 0xFF;
data.moduleVoltage[2] = (voltage_mv >> 8) & 0xFF;
data.moduleVoltage[3] = (voltage_mv >> 0) & 0xFF;
PSU_SendCmd(0xF0, addr, 0x1C, &data);
}
void PSU_SendCmd(uint8_t source, uint8_t destination, uint8_t cmd, void *data){
CanId_t CanId;
CanId.source = source;
CanId.destination = destination;
CanId.command = cmd;
CanId.device = 0x0A;
int8_t retry_counter = 10;
CAN_TxHeaderTypeDef tx_header;
uint32_t tx_mailbox;
HAL_StatusTypeDef CAN_result;
memcpy(&tx_header.ExtId, &CanId, sizeof(CanId_t));
tx_header.RTR = CAN_RTR_DATA;
tx_header.IDE = CAN_ID_EXT;
tx_header.DLC = 8;
while(retry_counter>0){ //если буфер полон, ждем пока он освободится
if (HAL_CAN_GetTxMailboxesFreeLevel(&hcan2) > 0){
/* отправка сообщения */
CAN_result = HAL_CAN_AddTxMessage(&hcan2, &tx_header, (uint8_t*)data, &tx_mailbox);
/* если отправка удалась, выход */
if(CAN_result == HAL_OK) {
return;
retry_counter = 0;
}
}
ED_Delay(1);
retry_counter--;
}
}
uint32_t max(uint32_t a, uint32_t b){
if(a>b) return a;
else return b;
}
void PSU_ReadWrite(){
uint8_t zero_data[8] = {0,0,0,0,0,0,0,0};
PSU_SendCmd(0xF0, 0, 0x04, zero_data);ED_Delay(CAN_DELAY);
PSU_SendCmd(0xF0, 0, 0x06, zero_data);ED_Delay(CAN_DELAY);
// PSU_SendCmd(0xF0, 0, 0x08, zero_data);ED_Delay(CAN_DELAY);
PSU_SendCmd(0xF0, 0, 0x09, zero_data);ED_Delay(CAN_DELAY);
// Power Limit
if ((CONN.WantedCurrent/10) * CONN.MeasuredVoltage > PSU0.power_limit){
CONN.RequestedCurrent = PSU0.power_limit * 10 / CONN.MeasuredVoltage;
}else{
CONN.RequestedCurrent = CONN.WantedCurrent;
}
if(CONN.RequestedCurrent > (PSU_MAX_CURRENT*10)){
CONN.RequestedCurrent = PSU_MAX_CURRENT*10;
}
CONN.RequestedPower = CONN.RequestedCurrent * CONN.RequestedVoltage / 10;
if(PSU0.ready){
PSU_SetVoltageCurrent(0, CONN.RequestedVoltage, CONN.RequestedCurrent); // Normal mode
ED_Delay(CAN_DELAY);
if(CONN.MeasuredVoltage>490) PSU0.hv_mode = 1;
}
// PSU_SetHVMode(0, PSU0.hv_mode); // auto set, no need
// ED_Delay(CAN_DELAY);
}
void PSU_Task(void){
static uint32_t psu_on_tick = 0;
static uint32_t dc_on_tick = 0;
static uint32_t cont_ok_tick = 0;
// Обновляем ONLINE/READY по таймауту
if((HAL_GetTick() - can_lastpacket) > PSU_ONLINE_TIMEOUT){
PSU0.online = 0;
PSU0.PSU_enabled = 0;
PSU_04.moduleTemperature = 0;
PSU_04.modularForm0 = 0;
PSU_04.modularForm1 = 0;
PSU_04.modularForm2 = 0;
PSU_06.VAB = 0;
PSU_06.VBC = 0;
PSU_06.VCA = 0;
PSU_09.moduleNCurrent = 0;
PSU_09.moduleNVoltage = 0;
}
if(!PSU0.online || !PSU0.enableAC){
CONN.MeasuredVoltage = 0;
CONN.MeasuredCurrent = 0;
CONN.outputEnabled = 0;
}
// Управление AC-контактором с задержкой отключения 1 минута
if(CONN.EvConnected){
RELAY_Write(RELAY_AC, 1);
psu_on_tick = HAL_GetTick();
PSU0.enableAC = 1;
}else{
if((HAL_GetTick() - psu_on_tick) > 1 * 60000){
RELAY_Write(RELAY_AC, 0);
PSU0.enableAC = 0;
}
}
// Текущее состояние DC-контактора по обратной связи
PSU0.CONT_enabled = IN_ReadInput(IN_CONT_FB_DC);
// Обновляем ready с учётом ошибок
if(PSU0.online && !PSU0.cont_fault && PSU0.enableAC){
// PSU0.ready = 1;
}else{
PSU0.ready = 0;
}
switch(PSU0.state){
case PSU_UNREADY:
PSU0.enableOutput = 0;
RELAY_Write(RELAY_DC, 0);
if(PSU0.online && PSU0.enableAC && !PSU0.cont_fault){
PSU_SwitchState(PSU_INITIALIZING);
}
break;
case PSU_INITIALIZING:
if(PSU_StateTime() > 4000){ // Wait 4s for PSU to initialize
PSU0.ready = 1;
PSU_SwitchState(PSU_READY);
}
break;
case PSU_READY:
// модуль готов, но выключен
PSU0.hv_mode = 0;
RELAY_Write(RELAY_DC, 0);
if(!PSU0.ready){
PSU_SwitchState(PSU_UNREADY);
break;
}
if(CONN.EnableOutput){
PSU_Enable(0, 1);
PSU_SwitchState(PSU_WAIT_ACK_ON);
}
break;
case PSU_WAIT_ACK_ON:
if(PSU0.PSU_enabled && PSU0.ready){
dc_on_tick = HAL_GetTick();
PSU_SwitchState(PSU_CONT_WAIT_ACK_ON);
}else if(PSU_StateTime() > 10000){
PSU0.psu_fault = 1;
CONN.chargingError = CONN_ERR_PSU_FAULT;
PSU_SwitchState(PSU_UNREADY);
log_printf(LOG_ERR, "PSU on timeout\n");
}
break;
case PSU_CONT_WAIT_ACK_ON:
// замыкаем DC-контактор и ждём подтверждение
RELAY_Write(RELAY_DC, 1);
if(PSU0.CONT_enabled){
PSU_SwitchState(PSU_CONNECTED);
}else if(PSU_StateTime() > 1000){
PSU0.cont_fault = 1;
CONN.chargingError = CONN_ERR_CONTACTOR;
PSU_SwitchState(PSU_CURRENT_DROP);
log_printf(LOG_ERR, "Contactor error, stopping...\n");
}
break;
case PSU_CONNECTED:
// Основное рабочее состояние
if(!CONN.EnableOutput || !PSU0.ready){
PSU_SwitchState(PSU_CURRENT_DROP);
break;
}
// контроль контактора: 1 c таймаут
if (IN_ReadInput(IN_CONT_FB_DC) != RELAY_Read(RELAY_DC)){
if((HAL_GetTick() - cont_ok_tick) > 1000){
CONN.chargingError = CONN_ERR_CONTACTOR;
PSU0.cont_fault = 1;
PSU_SwitchState(PSU_CURRENT_DROP);
log_printf(LOG_ERR, "Contactor error, stopping...\n");
}
}else{
cont_ok_tick = HAL_GetTick();
}
break;
case PSU_CURRENT_DROP:
// снижаем ток до нуля перед отключением DC
CONN.RequestedCurrent = 0;
// если ток действительно упал или вышло время, отключаем DC
if((CONN.MeasuredCurrent < 30) || (PSU_StateTime() > 5000)){
PSU_SwitchState(PSU_CONT_WAIT_ACK_OFF);
}
break;
case PSU_CONT_WAIT_ACK_OFF:
RELAY_Write(RELAY_DC, 0);
if(!PSU0.CONT_enabled){
PSU_Enable(0, 0);
PSU_SwitchState(PSU_WAIT_ACK_OFF);
}else if(PSU_StateTime() > 1000){
PSU0.cont_fault = 1;
CONN.chargingError = CONN_ERR_CONTACTOR;
PSU_Enable(0, 0);
PSU_SwitchState(PSU_WAIT_ACK_OFF);
log_printf(LOG_ERR, "Contactor error, stopping...\n");
}
break;
case PSU_WAIT_ACK_OFF:
if(!PSU0.PSU_enabled){
PSU_SwitchState(PSU_OFF_PAUSE);
}else if(PSU_StateTime() > 10000){
PSU0.psu_fault = 1;
CONN.chargingError = CONN_ERR_PSU_FAULT;
PSU_SwitchState(PSU_UNREADY);
log_printf(LOG_ERR, "PSU off timeout\n");
}
break;
case PSU_OFF_PAUSE:
if(PSU_StateTime() > 4000){
PSU_SwitchState(PSU_READY);
}
break;
default:
PSU_SwitchState(PSU_UNREADY);
break;
}
}

251
Core/Src/rgb_controller.c Normal file
View File

@@ -0,0 +1,251 @@
#include "rgb_controller.h"
#include "main.h"
#include "string.h"
#include "charger_control.h"
#include "tim.h"
RGB_State_t LED_State;
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,
};
RGB_Cycle_t color_unknown = {
.Color1 = { .R = 64, .G = 0, .B = 0 },
.Color2 = { .R = 64, .G = 0, .B = 0 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_light = {
.Color1 = { .R = 0, .G = 255, .B = 0 },
.Color2 = { .R = 0, .G = 255, .B = 0 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_disabled = {
.Color1 = { .R = 250, .G = 0, .B = 0 },
.Color2 = { .R = 32, .G = 0, .B = 0 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_unplugged = {
.Color1 = { .R = 0, .G = 128, .B = 0 },
.Color2 = { .R = 0, .G = 128, .B = 0 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_preparing = {
.Color1 = { .R = 0, .G = 0, .B = 250 },
.Color2 = { .R = 0, .G = 0, .B = 250 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_charging = {
.Color1 = { .R = 0, .G = 255, .B = 0 },
.Color2 = { .R = 0, .G = 32, .B = 0 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_finished = {
.Color1 = { .R = 255, .G = 255, .B = 255 },
.Color2 = { .R = 255, .G = 255, .B = 255 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
RGB_Cycle_t color_error = {
.Color1 = { .R = 255, .G = 0, .B = 0 },
.Color2 = { .R = 32, .G = 0, .B = 0 },
.Tr = 50,
.Th = 10,
.Tf = 50,
.Tl = 0,
};
void LED_Write(){
if(CONN.chargingError != CONN_NO_ERROR){
LED_SetColor(&color_error);
return;
}
switch(CONN.connState){
case Unknown:
LED_SetColor(&color_unknown);
break;
case Unplugged:
LED_SetColor(&color_unplugged);
break;
case Disabled:
LED_SetColor(&color_error);
break;
case Preparing:
LED_SetColor(&color_preparing);
break;
case AuthRequired:
LED_SetColor(&color_preparing);
break;
case WaitingForEnergy:
LED_SetColor(&color_charging);
break;
case ChargingPausedEV:
LED_SetColor(&color_charging);
break;
case ChargingPausedEVSE:
LED_SetColor(&color_charging);
break;
case Charging:
LED_SetColor(&color_charging);
break;
case AuthTimeout:
LED_SetColor(&color_finished);
break;
case Finished:
LED_SetColor(&color_finished);
break;
case FinishedEVSE:
LED_SetColor(&color_finished);
break;
case FinishedEV:
LED_SetColor(&color_finished);
break;
case Replugging:
LED_SetColor(&color_preparing);
break;
default:
LED_SetColor(&color_unknown);
break;
}
}
void interpolateColors(RGB_t* color1, RGB_t* color2, uint16_t a, uint16_t b, RGB_t *result) {
// Проверяем, чтобы a не выходила за пределы диапазона
if (a > b) a = b;
if(b==0) b = 1;
// Вычисляем коэффициент смешивания в виде целого числа
uint16_t t = (a * 255) / b; // t будет от 0 до 255
// Линейная интерполяция с использованием целых чисел
result->R = (color1->R * (255 - t) + color2->R * t) / 255;
result->G = (color1->G * (255 - t) + color2->G * t) / 255;
result->B = (color1->B * (255 - t) + color2->B * t) / 255;
}
void RGB_SetColor(RGB_t *color){
htim4.Instance->CCR2 = color->R * 100 / 255;
htim4.Instance->CCR3 = color->G * 100 / 255;
htim4.Instance->CCR4 = color->B * 100 / 255;
}
void LED_SetColor(RGB_Cycle_t *color){
memcpy(&LED_Cycle, color, sizeof(RGB_Cycle_t));
}
void LED_Init(){
RGB_t color = {.R=0, .G=0, .B=0};
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
RGB_SetColor(&color);
}
// void LED_PhaseSync(uint8_t led_n){
// if(LED_State[led_n].phasesync){
// LED_State[led_n].phasesync = 0;
// //default settings
// LED_State[led_n].state = LED_HIGH;
// LED_State[led_n].tick = 0;
// //ищем среди всех светодиодов такую же последовательность
// for (uint8_t led_n1 = 0; led_n1 < 5; led_n1++){
// if ((LED_Cycle[led_n].Tf == LED_Cycle[led_n1].Tf) &&
// (LED_Cycle[led_n].Tr == LED_Cycle[led_n1].Tr) &&
// (LED_Cycle[led_n].Th == LED_Cycle[led_n1].Th) &&
// (LED_Cycle[led_n].Tl == LED_Cycle[led_n1].Tl) &&
// (led_n != led_n1)){
// //если нашли, то копируем фазу оттуда
// LED_State[led_n].state = LED_State[led_n1].state;
// LED_State[led_n].tick = LED_State[led_n1].tick;
// return;
// }
// }
// }
// }
void LED_Task(){
static uint32_t led_tick;
if((HAL_GetTick() - led_tick) > 20){
led_tick = HAL_GetTick();
LED_State.tick++;
// LED_PhaseSync(led_n);
switch(LED_State.state){
case LED_RISING:
interpolateColors(&LED_Cycle.Color2, &LED_Cycle.Color1, LED_State.tick, LED_Cycle.Tr, &LED_State.color);
if(LED_State.tick>LED_Cycle.Tr){
LED_State.state = LED_HIGH;
LED_State.tick = 0;
}
break;
case LED_HIGH:
memcpy(&LED_State.color, &LED_Cycle.Color1, sizeof(RGB_t));
if(LED_State.tick>LED_Cycle.Th){
LED_State.state = LED_FALLING;
LED_State.tick = 0;
}
break;
case LED_FALLING:
interpolateColors(&LED_Cycle.Color1, &LED_Cycle.Color2, LED_State.tick, LED_Cycle.Tf, &LED_State.color);
if(LED_State.tick>LED_Cycle.Tf){
LED_State.state = LED_LOW;
LED_State.tick = 0;
}
break;
case LED_LOW:
memcpy(&LED_State.color, &LED_Cycle.Color2, sizeof(RGB_t));
if(LED_State.tick>LED_Cycle.Tl){
LED_State.state = LED_RISING;
LED_State.tick = 0;
}
break;
default:
LED_State.state = LED_RISING;
}
RGB_SetColor(&LED_State.color);
}
}

View File

@@ -1,21 +1,5 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file rtc.c
* @brief This file provides code for the configuration
* of the RTC instances.
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "rtc.h"

243
Core/Src/serial_control.c Normal file
View File

@@ -0,0 +1,243 @@
#include "serial_control.h"
#include "crc.h"
#include "usart.h"
#include "board.h"
// Приватные функции
uint32_t revbit(uint32_t uData);
uint32_t CRC32_ForBytes(uint8_t *pData, uint32_t uLen);
uint32_t calculate_crc32(const uint8_t* data, uint16_t length);
uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code);
uint8_t process_received_packet(const uint8_t* packet_data, uint16_t packet_len);
uint8_t test_crc_invalid = 0;
SerialControl_t serial_control;
StatusPacket_t statusPacket = {
.SOC = 0,
.Energy = 0,
.RequestedVoltage = 0,
.RequestedCurrent = 0,
.MeasuredVoltage = 0,
.MeasuredCurrent = 0,
.outputEnabled = 0,
.chargingError = 0,
.connState = 0,
.chargingElapsedTimeMin = 0,
.chargingElapsedTimeSec = 0,
.estimatedRemainingChargingTime = 0,
.relayAC = 0,
.relayDC = 0,
.relayAUX = 0,
.lockState = 0,
.evInfoAvailable = 0,
.psuOnline = 0,
.tempConnector0 = 0,
.tempConnector1 = 0,
.tempAmbient = 0,
.tempBatteryMax = 0,
.tempBatteryMin = 0,
.highestVoltageOfBatteryCell = 0,
.batteryStatus = 0,
.phaseVoltageAB = 0,
.phaseVoltageBC = 0,
.phaseVoltageCA = 0,
};
InfoPacket_t infoPacket = {
.serialNumber = 0,
.boardVersion = 0,
.stationType = 0,
.fw_version_major = 0,
.fw_version_minor = 0,
.fw_version_patch = 0,
};
void ReadVersion(){
infoPacket.serialNumber = InfoBlock->serialNumber;
infoPacket.boardVersion = InfoBlock->boardVersion;
infoPacket.stationType = InfoBlock->stationType;
infoPacket.fw_version_major = FW_VERSION_MAJOR;
infoPacket.fw_version_minor = FW_VERSION_MINOR;
infoPacket.fw_version_patch = FW_VERSION_PATCH;
}
// Внешняя функция обработки команд (определена в serial_handler.c)
extern void SC_CommandHandler(ReceivedCommand_t* cmd);
void SC_Init() {
// Обнуляем структуру
memset(&serial_control, 0, sizeof(SerialControl_t));
}
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);
// Проверка таймаута отправки пакета (больше 100 мс)
if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0) {
if ((HAL_GetTick() - serial_control.tx_tick) > 100) {
// Таймаут: принудительно сбрасываем передачу
HAL_UART_Abort_IT(&huart2);
// Выключаем DIR при сбросе передачи
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
serial_control.tx_tick = 0; // Сбрасываем tick
}
}
// Проверка наличия принятой команды для обработки
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
// HAL_Delay(2);
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; // Сбрасываем флаг
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
if (huart->Instance == huart2.Instance) {
if(!process_received_packet(serial_control.rx_buffer, Size)){
SC_SendPacket(NULL, 0, RESP_INVALID);
}
}
}
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);
serial_control.tx_tick = 0;
}
}
// Приватные функции реализации
uint32_t revbit(uint32_t uData) {
uint32_t uRevData = 0, uIndex = 0;
uRevData |= ((uData >> uIndex) & 0x01);
for(uIndex = 1; uIndex < 32; uIndex++) {
uRevData <<= 1;
uRevData |= ((uData >> uIndex) & 0x01);
}
return uRevData;
}
uint32_t CRC32_ForBytes(uint8_t *pData, uint32_t uLen) {
uint32_t uIndex = 0, uData = 0, i;
uIndex = uLen >> 2;
SERIAL_PROTOCOL_CRC_CLK_ENABLE();
__HAL_CRC_DR_RESET(&hcrc);
while(uIndex--) {
((uint8_t *) & uData)[0] = pData[0];
((uint8_t *) & uData)[1] = pData[1];
((uint8_t *) & uData)[2] = pData[2];
((uint8_t *) & uData)[3] = pData[3];
pData += 4;
uData = revbit(uData);
hcrc.Instance->DR = uData;
}
uData = revbit(hcrc.Instance->DR);
uIndex = uLen & 0x03;
while(uIndex--) {
uData ^= (uint32_t) * pData++;
for(i = 0; i < 8; i++)
if (uData & 0x1)
uData = (uData >> 1) ^ CRC32_POLYNOMIAL;
else
uData >>= 1;
}
SERIAL_PROTOCOL_CRC_CLK_DISABLE();
return uData ^ 0xFFFFFFFF;
}
uint32_t calculate_crc32(const uint8_t* data, uint16_t length) {
return CRC32_ForBytes((uint8_t*)data, (uint32_t)length);
}
uint16_t encode_packet(const uint8_t* payload, uint16_t payload_len, uint8_t* output, uint8_t response_code) {
uint16_t out_index = 0;
output[out_index++] = response_code;
if (payload != NULL) {
// Просто копируем полезную нагрузку без какого‑либо экранирования
for (uint16_t i = 0; i < payload_len; i++) {
output[out_index++] = payload[i];
// Проверка переполнения
if (out_index >= MAX_TX_BUFFER_SIZE - 5) { // 4 байта CRC + END_BYTE
return 0;
}
}
}
// Вычисляем CRC для всего содержимого (код ответа + полезная нагрузка)
uint32_t crc = calculate_crc32(output, out_index);
uint8_t* crc_bytes = (uint8_t*)&crc;
// Добавляем CRC без экранирования
for (int i = 0; i < 4; i++) {
output[out_index++] = crc_bytes[i];
if (out_index >= MAX_TX_BUFFER_SIZE - 1) { // место для END_BYTE
return 0;
}
}
return out_index;
}
void SC_SendPacket(const uint8_t* payload, uint16_t payload_len, uint8_t response_code) {
uint16_t packet_len = encode_packet(payload, payload_len, serial_control.tx_buffer, response_code);
if (packet_len > 0) {
if (huart2.gState == HAL_UART_STATE_BUSY_TX) {
HAL_UART_Abort_IT(&huart2);
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_SET);
HAL_UART_Transmit_IT(&huart2, serial_control.tx_buffer, packet_len);
serial_control.tx_tick = HAL_GetTick();
}
}
uint8_t process_received_packet(const uint8_t* packet_data, uint16_t packet_len) {
// if (test_crc_invalid && (packet_data[1] != CMD_GET_STATUS)) {
// test_crc_invalid--;
// return 0;
// }else{
// test_crc_invalid = 5;
// }
// Минимальный размер: 1 байт команды + 4 байта CRC
if (packet_len < 5) return 0;
if (packet_len > MAX_RX_BUFFER_SIZE) return 0;
uint16_t payload_length = packet_len - 4;
// Извлекаем принятую CRC (последние 4 байта, little-endian)
uint32_t received_checksum =
((uint32_t)packet_data[payload_length] << 0) |
((uint32_t)packet_data[payload_length + 1] << 8) |
((uint32_t)packet_data[payload_length + 2] << 16) |
((uint32_t)packet_data[payload_length + 3] << 24);
// Вычисляем CRC для полезной нагрузки
uint32_t calculated_checksum = calculate_crc32(packet_data, payload_length);
if (received_checksum != calculated_checksum) return 0; // CRC не совпадает
serial_control.received_command.argument = &packet_data[1];
serial_control.received_command.command = packet_data[0];
serial_control.received_command.argument_length = payload_length - 1;
serial_control.command_ready = 1;
return 1;
}

188
Core/Src/serial_handler.c Normal file
View File

@@ -0,0 +1,188 @@
#include "serial_control.h"
#include "charger_gbt.h"
#include "crc.h"
#include "usart.h"
#include "charger_control.h"
#include "charger_gbt.h"
#include "board.h"
#include "psu_control.h"
#include "debug.h"
#ifdef USE_WEB_INTERFACE
extern uint8_t GBT_BAT_STAT_recv;
uint8_t config_initialized = 0;
ConfigBlock_t config = {
.location = "RUS",
.chargerNumber = 00001,
.unixTime = 1721651966,
};
// Единая функция-обработчик всех команд со switch-case
void SC_CommandHandler(ReceivedCommand_t* cmd) {
uint8_t response_code = RESP_FAILED;
switch (cmd->command) {
// Команды БЕЗ аргументов
case CMD_GET_STATUS:
// Логика получения информации
monitoring_data_callback();
// Отправляем с нормальным приоритетом
SC_SendPacket((uint8_t*)&statusPacket, sizeof(statusPacket), CMD_GET_STATUS);
return; // Специальный ответ уже отправлен
case CMD_GET_INFO:
SC_SendPacket((uint8_t*)&infoPacket, sizeof(infoPacket), CMD_GET_INFO);
return;
case CMD_GET_LOG:
debug_buffer_send();
return; // Ответ формируется внутри debug_buffer_send
// Команды С аргументами
case CMD_SET_CONFIG:
if (cmd->argument_length == sizeof(ConfigBlock_t)) {
memcpy(&config, cmd->argument, sizeof(ConfigBlock_t));
GBT_SetConfig();
config_initialized = 1;
GBT_SetConfig();
// CONN.connState = CONN_Available; //
log_printf(LOG_INFO, "Set Config: %s %d\n", config.location, config.chargerNumber);
response_code = RESP_SUCCESS;
break;
}
response_code = RESP_FAILED;
break;
case CMD_SET_POWER_LIMIT:
if (cmd->argument_length == 1) {
PSU0.power_limit = ((uint8_t*)cmd->argument)[0] * 1000;
log_printf(LOG_INFO, "Power limit: %d\n", PSU0.power_limit);
//CONN.connState = (((uint8_t*)cmd->argument)[0])/4;
response_code = RESP_SUCCESS;
break;
}
response_code = RESP_FAILED;
break;
case CMD_CHARGE_PERMIT:
if (cmd->argument_length == 1) {
CONN.connControl = ((uint8_t*)cmd->argument)[0];
log_printf(LOG_INFO, "Charge permit: %d\n", CONN.connControl);
response_code = RESP_SUCCESS;
break;
}
response_code = RESP_FAILED;
break;
case CMD_TEST_PSU:
// if (cmd->argument_length == sizeof(PSU_TestMode_t)) {
// memcpy(&PSU_TestMode, cmd->argument, sizeof(PSU_TestMode_t));
// log_printf(LOG_INFO, "Test PSU: %d %d %d\n", PSU_TestMode.enable, PSU_TestMode.voltage, PSU_TestMode.current);
// response_code = RESP_SUCCESS;
// break;
// }
response_code = RESP_FAILED;
break;
case CMD_DEVICE_RESET:
// 2. Отправляем SUCCESS (хост может успеть получить его перед ребутом)
SC_SendPacket(NULL, 0, RESP_SUCCESS);
while(huart2.gState == HAL_UART_STATE_BUSY_TX); // Ожидание завершения передачи
// 3. Выполняем программный сброс
NVIC_SystemReset();
return; // Сюда код уже не дойдет, но для компилятора нужно
default:
// Неизвестная команда
response_code = RESP_FAILED;
break;
}
// Отправляем финальный ответ (для команд без собственного ответа)
SC_SendPacket(NULL, 0, response_code);
}
// Колбэк для заполнения данных мониторинга
void monitoring_data_callback() {
// Информация о зарядной сессии
statusPacket.SOC = CONN.SOC;
statusPacket.Energy = CONN.Energy;
statusPacket.RequestedVoltage = CONN.RequestedVoltage;
statusPacket.RequestedCurrent = CONN.WantedCurrent;
statusPacket.MeasuredVoltage = CONN.MeasuredVoltage;
statusPacket.MeasuredCurrent = CONN.MeasuredCurrent;
statusPacket.outputEnabled = CONN.outputEnabled;
statusPacket.chargingError = CONN.chargingError;
statusPacket.connState = CONN.connState;
statusPacket.chargingElapsedTimeMin = 0;
statusPacket.chargingElapsedTimeSec = 0;
statusPacket.estimatedRemainingChargingTime = 0;
// состояние зарядной станции
statusPacket.relayAC = RELAY_Read(RELAY_AC);
statusPacket.relayDC = RELAY_Read(RELAY_DC);
statusPacket.relayAUX = RELAY_Read(RELAY_AUX0);
statusPacket.lockState = GBT_LockGetState();
statusPacket.stopButton = !IN_ReadInput(IN_ESTOP);
statusPacket.logAvailable = (debug_buffer_available()>0)?1:0;
statusPacket.evInfoAvailable = GBT_BAT_STAT_recv;
statusPacket.psuOnline = PSU0.online;
statusPacket.tempConnector0 = GBT_ReadTemp(0); // температура коннектора
statusPacket.tempConnector1 = GBT_ReadTemp(1);
statusPacket.tempAmbient = PSU0.tempAmbient; // температура окружающего воздуха
statusPacket.tempBatteryMax = GBT_BatteryStatus.batteryHighestTemp; // максимальная температура батареи
statusPacket.tempBatteryMin = GBT_BatteryStatus.batteryLowestTemp; // минимальная температура батареи
statusPacket.highestVoltageOfBatteryCell = GBT_ChargingStatus.highestVoltageOfBatteryCell;
statusPacket.batteryStatus = GBT_BatteryStatus.batteryStatus;
statusPacket.phaseVoltageAB = PSU_06.VAB;
statusPacket.phaseVoltageBC = PSU_06.VBC;
statusPacket.phaseVoltageCA = PSU_06.VCA;
memcpy(statusPacket.VIN, GBT_EVInfo.EVIN, sizeof(GBT_EVInfo.EVIN));
statusPacket.batteryType = GBT_EVInfo.batteryType;
statusPacket.batteryCapacity = GBT_EVInfo.batteryCapacity;
statusPacket.batteryVoltage = GBT_EVInfo.batteryVoltage;
memcpy(statusPacket.batteryVendor, GBT_EVInfo.batteryVendor, sizeof(statusPacket.batteryVendor));
statusPacket.batterySN = GBT_EVInfo.batterySN;
statusPacket.batteryManuD = GBT_EVInfo.batteryManuD;
statusPacket.batteryManuM = GBT_EVInfo.batteryManuM;
statusPacket.batteryManuY = GBT_EVInfo.batteryManuY;
statusPacket.batteryCycleCount = GBT_EVInfo.batteryCycleCount;
statusPacket.ownAuto = GBT_EVInfo.ownAuto;
memcpy(statusPacket.EV_SW_VER, GBT_EVInfo.EV_SW_VER, sizeof(statusPacket.EV_SW_VER));
statusPacket.testMode = 0;
statusPacket.testVoltage = 0;
statusPacket.testCurrent = 0;
// Информация о тачке
// --- Информация об EV (из команды info2) ---
// memcpy(statusPacket.version, GBT_EVInfo.version, sizeof(statusPacket.version));
// --- Состояние Hardware и GBT (различные команды) ---
//statusPacket.lockState = GBT_LockGetState(); // Из команды lock_state
//statusPacket.ccState = CONN_CC_GetState(); // Из команды cc_state
//statusPacket.ccAdc = CONN_CC_GetAdc(); // Из команды adc
// --- Поля, требующие внимания (неявные геттеры) ---
// 1. Состояние соединения (ConnState)
// В debug.c есть CONN_SetState, предполагаем наличие CONN_GetState()
// Если такой функции нет, закомментируйте следующую строку:
// statusPacket.connState = CONN_GetState();
}
#endif

View File

@@ -72,7 +72,7 @@ uint8_t getTimeReg(uint8_t reg_number){
//
// // Print the BCD values for verification
// for (int i = 0; i < 8; i++) {
// printf("time[%d]: %02X\n", i, time[i]);
// log_printf(LOG_INFO, "time[%d]: %02X\n", i, time[i]);
// }
//
// return 0;

1
Core/Src/stm32f1xx_hal_msp.c Executable file → Normal file
View File

@@ -62,6 +62,7 @@
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */

30
Core/Src/stm32f1xx_it.c Executable file → Normal file
View File

@@ -57,7 +57,9 @@
/* External variables --------------------------------------------------------*/
extern CAN_HandleTypeDef hcan1;
extern CAN_HandleTypeDef hcan2;
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */
/* USER CODE END EV */
@@ -214,6 +216,20 @@ void CAN1_RX0_IRQHandler(void)
/* USER CODE END CAN1_RX0_IRQn 1 */
}
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt.
*/
@@ -228,6 +244,20 @@ void USART2_IRQHandler(void)
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
/**
* @brief This function handles CAN2 TX interrupt.
*/

155
Core/Src/tim.c Normal file
View File

@@ -0,0 +1,155 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
TIM_HandleTypeDef htim4;
/* TIM4 init function */
void MX_TIM4_Init(void)
{
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 720;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 100;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
HAL_TIM_MspPostInit(&htim4);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspInit 0 */
/* USER CODE END TIM4_MspInit 0 */
/* TIM4 clock enable */
__HAL_RCC_TIM4_CLK_ENABLE();
/* USER CODE BEGIN TIM4_MspInit 1 */
/* USER CODE END TIM4_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspPostInit 0 */
/* USER CODE END TIM4_MspPostInit 0 */
__HAL_RCC_GPIOD_CLK_ENABLE();
/**TIM4 GPIO Configuration
PD13 ------> TIM4_CH2
PD14 ------> TIM4_CH3
PD15 ------> TIM4_CH4
*/
GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
__HAL_AFIO_REMAP_TIM4_ENABLE();
/* USER CODE BEGIN TIM4_MspPostInit 1 */
/* USER CODE END TIM4_MspPostInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM4)
{
/* USER CODE BEGIN TIM4_MspDeInit 0 */
/* USER CODE END TIM4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM4_CLK_DISABLE();
/* USER CODE BEGIN TIM4_MspDeInit 1 */
/* USER CODE END TIM4_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

245
Core/Src/usart.c Executable file → Normal file
View File

@@ -7,7 +7,7 @@
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
@@ -24,8 +24,68 @@
/* USER CODE END 0 */
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
/* UART5 init function */
void MX_UART5_Init(void)
{
/* USER CODE BEGIN UART5_Init 0 */
/* USER CODE END UART5_Init 0 */
/* USER CODE BEGIN UART5_Init 1 */
/* USER CODE END UART5_Init 1 */
huart5.Instance = UART5;
huart5.Init.BaudRate = 115200;
huart5.Init.WordLength = UART_WORDLENGTH_8B;
huart5.Init.StopBits = UART_STOPBITS_1;
huart5.Init.Parity = UART_PARITY_NONE;
huart5.Init.Mode = UART_MODE_TX_RX;
huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart5.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart5) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART5_Init 2 */
/* USER CODE END UART5_Init 2 */
}
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/* USART2 init function */
void MX_USART2_UART_Init(void)
@@ -54,13 +114,100 @@ void MX_USART2_UART_Init(void)
/* USER CODE END USART2_Init 2 */
}
/* USART3 init function */
void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==USART2)
if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspInit 0 */
/* USER CODE END UART5_MspInit 0 */
/* UART5 clock enable */
__HAL_RCC_UART5_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**UART5 GPIO Configuration
PC12 ------> UART5_TX
PD2 ------> UART5_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USER CODE BEGIN UART5_MspInit 1 */
/* USER CODE END UART5_MspInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
@@ -92,12 +239,84 @@ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
/* USER CODE END USART2_MspInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
__HAL_AFIO_REMAP_USART3_PARTIAL();
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==USART2)
if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspDeInit 0 */
/* USER CODE END UART5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART5_CLK_DISABLE();
/**UART5 GPIO Configuration
PC12 ------> UART5_TX
PD2 ------> UART5_RX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2);
/* USER CODE BEGIN UART5_MspDeInit 1 */
/* USER CODE END UART5_MspDeInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
@@ -117,6 +336,26 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
/* USER CODE END USART2_MspDeInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11);
/* USART3 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */

View File

@@ -59,6 +59,7 @@ defined in linker script */
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr sp, =_estack /* set stack pointer */
/* Call the clock system initialization function.*/
bl SystemInit
@@ -252,6 +253,7 @@ g_pfnVectors:
.word 0
.word BootRAM /* @0x1E0. This is for boot in RAM mode for
STM32F10x Connectivity line Devices. */
.word 0x66666666 /* Reserved for OpenBLT checksum*/
/*******************************************************************************
*