/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
*
© Copyright (c) 2019 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dma.h"
#include "rtc.h"
#include "spi.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include
#include
#include
#include "sysdata.h"
#include "chip_temperature.h"
#include "shunt_voltage.h"
#include "shunt_temperature.h"
#include "ads1260.h"
#include "modbus.h"
#include "hsi16.h"
#include "hsi16_calibration.h"
#include "eeprom.h"
#include "ah_counter.h"
#include "battery_voltage.h"
#include "ref_voltage.h"
#include "fast_current.h"
#include "wh_counter.h"
#include "efficiency.h"
#include "esr.h"
#include "self_discharge.h"
#include "outputs.h"
#include "stm32g0xx_hal_crc.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
CRC_HandleTypeDef hcrc;
/* USER CODE BEGIN PV */
modbus_t modbusData;
static volatile uint32_t adcData[8];
static RTC_TimeTypeDef Time;
static uint32_t conversionCounter;
static double submAhCounter;
static volatile uint32_t newADC = 0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_CRC_Init(void);
/* USER CODE BEGIN PFP */
bool SetFlashReadProtection(bool state);
uint8_t printprotectionstate(void);
bool SetBootFromFlashAndReadOutProtection(void);
void SaveCounter(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t oldTime = 0;
uint32_t newTime = 0;
uint32_t timeDiff;
uint32_t timeDiff10ms = 0;
uint32_t timeDiff100ms = 0;
uint32_t i = 0;
uint32_t x;
int32_t mwValueCounter;
int silentmode =0;
int mode_button_disable_time=0;
uint8_t sekunde = 0;
uint8_t sekundeOld = 0;
uint32_t dummyDate;
uint8_t firstStartCatcher;
if (printprotectionstate() == 0)
{
// SetFlashReadProtection(true);
// HAL_FLASH_OB_Launch();
}
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
// printprotectionstate();
printf("ISENSOR: Init\n");
#ifdef DO_HSI16_CALIBRATION
// HSI16 Frequenzkompensation Initilisierung
HSI16_MeasurementInit();
HSI16_GetCurve();
orderTrimmingValues();
#endif
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
//MX_USART1_UART_Init();
MX_ADC1_Init();
MX_RTC_Init();
MX_CRC_Init();
/* USER CODE BEGIN 2 */
SYS_DATA_Init();
WH_COUNTER_Init();
AH_COUNTER_Init();
startType_t startType = EEPROM_isFirstStart(&firstStartCatcher);
sys_data.s.parameter.reserved0 = startType;
sys_data.s.parameter.reserved1 = firstStartCatcher;
switch(startType)
{
case FIRST_START_AFTER_ERASE: EEPROM_fullRestore(&sys_data); break;
case FIRST_START_AFTER_COMPARTIBLE_UPDATE: EEPROM_readConfig(&sys_data); break;
case FIRST_START_AFTER_INCOMPARTIBLE_UPDATE: EEPROM_factoryRestore(&sys_data, 0); break; // Preserving calibration and settings
case FIRST_START_ERROR: EEPROM_fullRestore(&sys_data); break;
}
printf("read config...\n");
EEPROM_readConfig(&sys_data);
if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
{
HAL_Delay(50);
if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
{
printf("factory restore...\n");
EEPROM_factoryRestore(&sys_data, 1);
}
}
// Modbus Initialisierung
mbInit(&modbusData, sys_data.s.parameter.baudrate, sys_data.s.parameter.parityMode, sys_data.s.parameter.stopBit, &huart1);
// STM32G0 Chiptemperatur Kalibrierung
//CHIP_TEMPERATURE_Calibration(/*&sys_data*/);
// ADC auf STM32G0 starten
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adcData, 8);
// Power up Sequenz fr INA240 Strommessverstrker
HAL_Delay(100);
// ADS1260 Initialierung
ADS1260_init();
printf("ADS1260 Init\n");
OUTPUTS_Init();
//Display Adress with Error LED blinks
for (int n = 0; n < sys_data.s.parameter.slave_address; n++)
{
HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_SET);
HAL_Delay(350);
HAL_GPIO_WritePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin, GPIO_PIN_RESET);
HAL_Delay(350);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if (newADC == 1)
{
// Systemtakt 64Mhz
// ADC Takt 64Mhz
// ADC DIV 1
// SAMPLE Time 160,5 Cycles
// OVERSAMPLING 16
// TOTAL TIME 160,5 + 12 * 16 * 8 == 22080 -->2,899 kHz
//Neue ADC Daten mit einer Frequenz von ca. 1,9 Khz
newADC = 0;
// Messe genaue Spannungsreferenz aus ADS1260 um eigene Spannungsmessung damit zu kalibrieren
REF_VOLTAGE_Exec(adcData[2]);
// Differenz der Spannung Ubat- und Ushunt
SHUNT_VOLTAGE_Exec( adcData[0]);
BATTERY_VOLTAGE_Exec( adcData[1]);
FAST_CURRENT_Exec( adcData[3], adcData[4]);
sys_data.s.values.batteryPower = ((int64_t) sys_data.s.values.batteryVoltage * (int64_t)sys_data.s.values.batteryCurrent) / 1000LL;
ESR_FAST_Exec();
//HAL_GPIO_TogglePin(LED_ERROR_GPIO_Port, LED_ERROR_Pin);
}
if (newCurrentValue == 1)
{
ADS1260_ConversionFinished();
ESR_Exec();
newCurrentValue = 0;
}
// Zeitbasis ms Systick;
newTime = HAL_GetTick();
timeDiff = newTime - oldTime;
oldTime = newTime;
timeDiff10ms += timeDiff;
timeDiff100ms += timeDiff;
if ((mode_button_disable_time > 0) && (timeDiff > 0))
{
mode_button_disable_time--;
}
// Zeitbasis Sekunde ber RTC
// muss immer sowohl das Zeit- als auch das Datumsregister lesen
// da beide Shadowregister sind sonst wird die Zeit nicht mehr geupdatet
sekunde = hrtc.Instance->TR & 0x0000000F;
dummyDate = hrtc.Instance->DR;
if (sekundeOld != sekunde)
{
sekundeOld = sekunde;
sys_data.s.values.onTime++;
// Funktions Led blinken
if (silentmode == 0)
{
HAL_GPIO_TogglePin(LED_FUNCTION_GPIO_Port, LED_FUNCTION_Pin);
HAL_GPIO_TogglePin(AUX_EN_GPIO_Port, AUX_EN_Pin);
}
// Amperestundenzhler
AH_COUNTER_Exec();
WH_COUNTER_Exec();
// LVP
OUTPUTS_CheckLVP();
// OVP
OUTPUTS_CheckOVP();
SaveCounter();
sys_data.s.values.selfDischargeStatus = SELF_DISCHARGE_Exec();
sys_data.s.values.efficiency = EFFICIENCY_Exec();
// Ausgabe der Temperatur des STM32G0
//CHIP_TEMPERATURE_Exec( adcData[7]);
SHUNT_TEMPERATURE_Exec(adcData[7]);
sys_data.s.values.ovp_sense = (adcData[5] * (uint64_t)sys_data.s.values.realVdd * 11 ) / 655360.0;
sys_data.s.values.lvp_sense = (adcData[6] * (uint64_t)sys_data.s.values.realVdd * 11 ) / 655360.0;
}
if(sys_data.s.parameter.command != 0)
{
if (modbusData.current_query == MB_QUERY_NOTHING)
{
//printf("CMD = %d\n", sys_data.s.parameter.command);
switch (sys_data.s.parameter.command )
{
case COMMAND_STORE_CONFIG: EEPROM_storeConfig(&sys_data,0); break;
case COMMAND_FULL_RESTORE: EEPROM_fullRestore(&sys_data); break;
case COMMAND_FACTORY_RESTORE: EEPROM_factoryRestore(&sys_data, 1); break;
case COMMAND_RESTORE_LAST_SAVED_VALUES: EEPROM_readConfig(&sys_data); break;
case COMMAND_STORE_WITH_SERIAL_NUMBER: EEPROM_storeConfig(&sys_data,1); break; // Seriennummer schreiben
case COMMAND_RESTART: NVIC_SystemReset(); break;
case COMMAND_BATTERY_CURRENT_OFFSET_CAL: ADS_1260_BatteryCurrentOffsetCalibrationStart(&sys_data); break;
case COMMAND_BATTERY_CURRENT_OFFSET_COMMONMODE_CAL: ADS_1260_BatteryCurrentOffsetCommonModeErrorComepensationStart(&sys_data); break;
case COMMAND_BATTERY_CURRENT_OFFSET_TEMP_CAL: ADS_1260_BatteryCurrentOffsetTemperatureErrorComepensationStart(); break;
case COMMAND_BATTERY_CURRENT_GAIN_CAL: ADS_1260_BatteryCurrentGainCalibrationStart(&sys_data); break;
case COMMAND_BATTERY_CURRENT_GAIN_TEMP_SHUNT_CAL: ADS_1260_BatteryCurrentGainTemperatureCalibrationShuntStart(); break;
// case COMMAND_BATTERY_CURRENT_GAIN_TEMP_CHIP_CAL: ADS_1260_BatteryCurrentGainTemperatureCalibrationChipStart(); break;
case COMMAND_SET_RDP_LEVEL0: SetFlashReadProtection(false); break;
case COMMAND_SET_RDP_LEVEL1: SetFlashReadProtection(true); break;
case COMMAND_SET_RDP_LEVEL1_AND_BOOTSEL: SetBootFromFlashAndReadOutProtection(); break;
default: printf("UNKNOWN COMMAND\n");
}
sys_data.s.parameter.command = 0;
}
else
{
//printf("wait with execution till modbus communnikation finished\n");
}
}
if((HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET) && (mode_button_disable_time == 0))
{
HAL_Delay(10);
//Taste weiterhin gedrckt?
if(HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET)
{
//Ja, dann Silent Mode umschalten
mode_button_disable_time=500;
if (silentmode == 0)
{
silentmode = 1;
HAL_GPIO_WritePin(LED_FUNCTION_GPIO_Port, LED_FUNCTION_Pin,GPIO_PIN_SET);
}
else
{
silentmode = 0;
}
}
}
// Modbus Kommunikation
if (mbGetFrameComplete(&modbusData) == true)
{
if (mbSlaveCheckModbusRtuQuery(&modbusData) == RESPOND_TO_QUERY)
{
if (silentmode == 0)
{
mbSlaveProcessRtuQuery(&modbusData);
}
}
else
{
huart1.RxState = HAL_UART_STATE_BUSY_RX;
}
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Configure LSE Drive Capability
*/
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_HIGH);
HAL_PWR_DisableBkUpAccess();
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
RCC_OscInitStruct.PLL.PLLN = 8;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_USART1
|RCC_PERIPHCLK_ADC;
PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1;
PeriphClkInit.AdcClockSelection = RCC_ADCCLKSOURCE_PLLADC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
//-----------------------------------------------------------------------------
static void MX_CRC_Init(void)
{
/* USER CODE BEGIN CRC_Init 0 */
__HAL_RCC_CRC_CLK_ENABLE();
/* USER CODE END CRC_Init 0 */
/* USER CODE BEGIN CRC_Init 1 */
/* USER CODE END CRC_Init 1 */
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
hcrc.Init.GeneratingPolynomial = 7;
hcrc.Init.CRCLength = CRC_POLYLENGTH_8B;
hcrc.Init.InitValue = 0xFF;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN CRC_Init 2 */
/* USER CODE END CRC_Init 2 */
}
//-----------------------------------------------------------------------------
void SaveCounter(void)
{
static uint32_t last_days;
// Converting seconds into days
uint32_t days = sys_data.s.values.onTime / (24U * 3600U);
// Alle 24 Stunden führen wir ein Speicherbefehl durch um die Counter zu spiechern
if (days != last_days)
{
last_days = days;
// Here we can save our counter(s)
EEPROM_storeConfig(&sys_data, 0);
}
}
//------------------------------------------------------------------------------
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
newADC = 1;
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/**
* @brief Set flash read protection.
* @param [in] state: Flash read protection state, true: enable protection, false: disable protection.
* @retval true: Successful operation.
* @retval false: Operation failed.
*/
bool SetFlashReadProtection(bool state)
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct = {0};
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
if(state == true)
{
printf("Start enable readout protection\n");
if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_0)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_1;
if (HAL_FLASH_Unlock() != HAL_OK)
{
printf("Flash unlock error\n");
}
if (HAL_FLASH_OB_Unlock() != HAL_OK)
{
printf("Flash ob unlock error\n");
}
printf("...Flash unlock\n");
if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
{
printf("...Enable lock error\n");
HAL_FLASH_OB_Lock();
return false;
}
HAL_FLASH_OB_Lock();
printf("Flash Optionbyte locked\n");
HAL_FLASH_Lock();
printf("Flash locked\n");
printf("...Enable lock process finished\n");
}
else
{
printf("...Flash lock already active\n");
}
}
else
{
if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_1)
{
OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_0;
if (HAL_FLASH_Unlock() != HAL_OK)
{
printf("Flash unlock error\n");
return false;
}
printf("...Flash unlocked\n");
if (HAL_FLASH_OB_Unlock() != HAL_OK)
{
printf("Flash ob unlock error\n");
return false;
}
printf("...Flash ob unlocked\n");
if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
{
HAL_FLASH_OB_Lock();
printf("Flash Optionbyte programm failed\n");
return false;
}
printf("Flash Optionbyte programmed\n");
HAL_FLASH_OB_Lock();
printf("Flash Optionbyte locked\n");
HAL_FLASH_Lock();
printf("Flash locked\n");
printf("...Disable lock process finished\n");
;
}
}
return true;
}
bool SetBootFromFlashAndReadOutProtection(void)
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct = {0};
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
//Konfiguriere RDP fr Readoutprotection and USER OPTION BYTE FR Boot from Flash
OptionsBytesStruct.OptionType = OPTIONBYTE_USER | OPTIONBYTE_RDP;
//Set Readout Protection Level 1
OptionsBytesStruct.OptionType = OPTIONBYTE_USER|OPTIONBYTE_RDP;
OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_1;
//Selecting Boot from Main Flash Memory
OptionsBytesStruct.USERType = OB_USER_nBOOT0 | OB_USER_nBOOT_SEL | OB_USER_nBOOT1 ;
OptionsBytesStruct.USERConfig = OB_USER_nBOOT0 | OB_USER_nBOOT_SEL;
if (HAL_FLASH_Unlock() != HAL_OK)
{
printf("Flash unlock error\n");
}
if (HAL_FLASH_OB_Unlock() != HAL_OK)
{
printf("Flash ob unlock error\n");
}
printf("...Flash unlock\n");
if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
{
printf("...Enable lock error\n");
HAL_FLASH_OB_Lock();
return false;
}
HAL_FLASH_OB_Lock();
printf("Flash Optionbyte locked\n");
HAL_FLASH_Lock();
printf("Flash locked\n");
printf("...Enable lock process finished\n");
return true;
}
uint8_t printprotectionstate(void)
{
FLASH_OBProgramInitTypeDef OptionsBytesStruct = {0};
HAL_FLASHEx_OBGetConfig(&OptionsBytesStruct);
uint8_t result = 0;
if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_0)
{
//OptionsBytesStruct.OptionType = OPTIONBYTE_RDP;
//OptionsBytesStruct.RDPLevel = OB_RDP_LEVEL_1;
printf("PROTECTION: OB_RDP_LEVEL_0\n");
result = 0;
}
else if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_1)
{
printf("PROTECTION: OB_RDP_LEVEL_1\n");
result = 1;
}
else if(OptionsBytesStruct.RDPLevel == OB_RDP_LEVEL_2)
{
printf("PROTECTION: OB_RDP_LEVEL_2\n");
result = 2;
}
return result;
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/