/* 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****/