#include "main.h" #include "usb_device.h" #include "usbd_cdc_if.h" #include "LCD_I2C_Driver.h" #include "InitSequence.h" #include "Config_Store.h" #include "Menu_Controller.h" #include "PressureChannel.h" #include "RelayChannel.h" #include "GPIChannel.h" #include "Menu.h" #define SLAVE_ADDRESS_LCD 0x4e ADC_HandleTypeDef hadc1; I2C_HandleTypeDef hi2c1; RTC_HandleTypeDef hrtc; TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim3; UART_HandleTypeDef huart1; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_RTC_Init(void); static void MX_ADC1_Init(void); static void MX_I2C1_Init(void); static void MX_TIM2_Init(void); static void MX_TIM3_Init(void); static void MX_USART1_UART_Init(void); extern uint16_t rot_counter; extern bool rot_button; extern uint16_t minute_counter; using namespace floatpump; bool S_backlight = false; bool S_tankempty = true; bool S_refilling = false; bool S_refillempty = true; uint32_t S_refillcooldown = 0; void CheckTankConditions(Config_Store &cfg, io::PressureChannel &tankLevel, io::RelayChannel &tankPump) { //Check if config says relay works inverted tankPump.setInverted(cfg.TankPumpInvert.getValue()); //First check if Tank has enough water and disable pump if necessary if (tankLevel.getPercent() < cfg.TankMinLevel.getValue()) { tankPump.switchRelay(io::RelayChannel::state::OFF); S_tankempty = true; } else if (tankLevel.getPercent() > cfg.TankMinLevel.getValue() + cfg.TankHysteresis.getValue()) { tankPump.switchRelay(io::RelayChannel::state::ON); S_tankempty = false; } } void CheckRefillConditions(Config_Store &cfg, io::PressureChannel &tankLevel, io::GPIChannel &refillBlock, io::RelayChannel &refillPump) { static uint32_t c_RefillCooldown = 0; static bool c_LastState = false; bool rblock = (cfg.RefillBlockInvert.getValue()) ? !refillBlock.getStateBool() : refillBlock.getStateBool(); if (cfg.RefillEnable.getValue()) { //Check whether refilling is necessary if (HAL_GetTick() > (c_RefillCooldown + (cfg.RefillCooldown.getValue() * 60 * 1000))) { S_refillcooldown = 0; if (tankLevel.getPercent() < cfg.RefillBelow.getValue()) { if (cfg.RefillBlockEnable.getValue() && !rblock) { refillPump.switchRelay(io::RelayChannel::state::ON); c_LastState = true; S_refilling = true; S_refillempty = false; } else if (rblock) { refillPump.switchRelay(io::RelayChannel::state::OFF); S_refilling = false; S_refillempty = true; //Reset cooldown only if it was previously on if (c_LastState) c_RefillCooldown = HAL_GetTick(); c_LastState = false; } else { refillPump.switchRelay(io::RelayChannel::state::ON); c_LastState = true; S_refilling = true; S_refillempty = false; } } else if (tankLevel.getPercent() > cfg.RefillBelow.getValue() + cfg.RefillHysteresis.getValue()) { refillPump.switchRelay(io::RelayChannel::state::OFF); S_refilling = false; S_refillempty = false; if (c_LastState) c_RefillCooldown = HAL_GetTick(); c_LastState = false; } } else { HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin); refillPump.switchRelay(io::RelayChannel::state::OFF); S_refillcooldown = (((c_RefillCooldown + (cfg.RefillCooldown.getValue() * 60 * 1000)) - HAL_GetTick()) / 1000); } } else { refillPump.switchRelay(io::RelayChannel::state::OFF); } } void SendUartString(UART_HandleTypeDef *huart, char out[]) { HAL_UART_Transmit(huart, (uint8_t *) out, strlen(out), 500); char newline[1] = {'\n'}; HAL_UART_Transmit(huart, (uint8_t *) newline, 1, 100); } int main(void) { // Step 1: Initialize HAL HAL_Init(); //Step 2: Configure Clock and RCC SystemClock_Config(); //Step 3: Configure Peripherals MX_GPIO_Init(); //MX_RTC_Init(); MX_TIM2_Init(); MX_TIM3_Init(); //MX_USB_DEVICE_Init(); MX_ADC1_Init(); MX_I2C1_Init(); MX_USART1_UART_Init(); //Disable Interrupt for Debouncing timer during display initialisation (exact timings are necessary) HAL_NVIC_DisableIRQ(TIM2_IRQn); LCD_I2C_Driver &display = floatpump::LCD_I2C_Driver::getInstance(hi2c1, SLAVE_ADDRESS_LCD); HAL_NVIC_EnableIRQ(TIM2_IRQn); //Restore configuration Config_Store::getInstance().loadFromFlash(); //Run init Sequence InitSequence initializer(display); initializer.runInitSequence(); using namespace floatpump::menu; Menu tankmenu("Tank"); bool a_caliblow, a_calibhigh = false; tankmenu.addEntry(&a_caliblow, "Kal. Unt. Punkt"); tankmenu.addEntry(&a_calibhigh, "Kal. Ob. Punkt"); tankmenu.addEntry(Config_Store::getInstance().TankCalibLow.getLink(), "K Unten"); tankmenu.addEntry(Config_Store::getInstance().TankCalibHigh.getLink(), "K Oben"); tankmenu.addEntry(Config_Store::getInstance().TankMinLevel.getLink(), "Min. Fuellst."); tankmenu.addEntry(Config_Store::getInstance().TankHysteresis.getLink(), "Hysterese"); tankmenu.addEntry(Config_Store::getInstance().TankPumpInvert.getLink(), "Inv Relais"); Menu refillmenu("Nachspeisung"); refillmenu.addEntry(Config_Store::getInstance().RefillEnable.getLink(), "Nachsp. akt."); refillmenu.addEntry(Config_Store::getInstance().RefillBlockEnable.getLink(), "Notabschalt."); refillmenu.addEntry(Config_Store::getInstance().RefillBlockInvert.getLink(), "NotAbs. Inv."); refillmenu.addEntry(Config_Store::getInstance().RefillBelow.getLink(), "Auff. bis"); refillmenu.addEntry(Config_Store::getInstance().RefillHysteresis.getLink(), "Hysterese"); refillmenu.addEntry(Config_Store::getInstance().RefillCooldown.getLink(), "Wartezeit"); Menu mainmenu("Hauptmenu"); mainmenu.addSubmenu(tankmenu); mainmenu.addSubmenu(refillmenu); //Instantiate Input and Output modules io::PressureChannel tankLevel0(&hadc1, MPWR0_GPIO_Port, MPWR0_Pin, 50); tankLevel0.LinkCalibConfig(Config_Store::getInstance().TankCalibLow.getLink(), Config_Store::getInstance().TankCalibHigh.getLink()); io::GPIChannel refillBlocker0(GPI0_GPIO_Port, GPI0_Pin); io::RelayChannel tankPump(OCHAN0_GPIO_Port, OCHAN0_Pin, true, io::RelayChannel::state::OFF); io::RelayChannel refillPump(OCHAN1_GPIO_Port, OCHAN1_Pin, false, io::RelayChannel::state::OFF); //Initially switch relays off by forcing a refresh tankPump.forceRefresh(); refillPump.forceRefresh(); uint32_t last_menu_retrigger = 0; uint32_t last_backlight_retrigger = 0; bool f_store = false, f_restore = false; mainmenu.addEntry(&f_store, "Speichern"); mainmenu.addEntry(&f_restore, "Laden"); Menu_Controller controller(&mainmenu, display); static int old_pos = 0; static int8_t history_h[59]; static int8_t history_d[23]; static int8_t diff_hist_hour = 0; static int8_t diff_hist_day = 0; static uint16_t old_minute_counter = minute_counter; static uint32_t dly_disp, dly_stats, dly_switch; SendUartString(&huart1, "Hello from FloatPUMP Controller"); SendUartString(&huart1, {"Revision: " GIT_HASH}); while (1) { //Execute this block each second only if(HAL_GetTick() > dly_disp + 1000) { dly_disp = HAL_GetTick(); display.LCDSetBacklight(S_backlight); //Increase to 21 -> crucial bug! usually never use sprintf! TODO: find another option instead!!!! char buf[21]; display.LCDSetCursor(0, 0); sprintf(buf, "Fuellstand %3d %%", tankLevel0.getPercent()); display.LCDSendCString(buf); display.LCDSetCursor(0, 1); if (S_tankempty) { display.LCDSendCString(const_cast(std::string("Tank Wassermangel ").c_str())); HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_SET); } else { display.LCDSendCString(const_cast(std::string("Tank Normal ").c_str())); HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_RESET); } display.LCDSetCursor(0, 2); if (S_refilling) { display.LCDSendCString(const_cast(std::string("Nachspeisung laeuft ").c_str())); HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_RESET); } else { display.LCDSendCString(const_cast(std::string("Nachspeisung inaktiv").c_str())); HAL_GPIO_WritePin(LED4_GPIO_Port, LED4_Pin, GPIO_PIN_SET); } display.LCDSetCursor(0, 3); if (S_refillcooldown > 0) { int remaining_mins = S_refillcooldown / 60; if (remaining_mins > 0) { sprintf(buf, "Nsp. wartet: %3d min", S_refillcooldown / 60); display.LCDSendCString(buf); } else { sprintf(buf, "Nsp. wartet: %3d sec", S_refillcooldown); display.LCDSendCString(buf); } } else if (S_refillempty) { display.LCDSendCString(const_cast(std::string("Nachspeisung mangel ").c_str())); HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); } else { display.LCDSendCString(const_cast(std::string("Nachspeisung ok ").c_str())); HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_SET); } } //Check for rotation to enable display backlight if (old_pos < rot_counter) { controller.pushEvent(menu::Menu_Controller::Event::Increase); old_pos = rot_counter; last_backlight_retrigger = HAL_GetTick(); } else if (old_pos > rot_counter) { controller.pushEvent(menu::Menu_Controller::Event::Decrease); old_pos = rot_counter; last_backlight_retrigger = HAL_GetTick(); } //Check and toggle backlight state if (HAL_GetTick() > last_backlight_retrigger + 60000) { S_backlight = false; } else { S_backlight = true; } if (rot_button) { display.LCDSetBacklight(true); rot_button = false; last_menu_retrigger = HAL_GetTick(); while (true) { //Display menu until timeout tankPump.switchRelay(floatpump::io::RelayChannel::state::OFF); refillPump.switchRelay(floatpump::io::RelayChannel::state::OFF); //Force refresh tankPump.forceRefresh(); refillPump.forceRefresh(); controller.execute(); if (rot_button) { rot_button = false; controller.pushEvent(menu::Menu_Controller::Event::Push); last_menu_retrigger = HAL_GetTick(); } if (old_pos < rot_counter) { controller.pushEvent(menu::Menu_Controller::Event::Increase); old_pos = rot_counter; last_menu_retrigger = HAL_GetTick(); } else if (old_pos > rot_counter) { controller.pushEvent(menu::Menu_Controller::Event::Decrease); old_pos = rot_counter; last_menu_retrigger = HAL_GetTick(); } HAL_Delay(10); //Execute Calibrations if necessary if (a_caliblow) { tankLevel0.calibrateLow(); controller.execute(); HAL_Delay(2000); a_caliblow = false; } else if (a_calibhigh) { tankLevel0.calibrateHigh(); controller.execute(); HAL_Delay(2000); a_calibhigh = false; } //Store or restore if necessary if (f_store) { Config_Store::getInstance().saveToFlash(); f_store = false; } else if (f_restore) { Config_Store::getInstance().loadFromFlash(); f_restore = false; } if (HAL_GetTick() > last_menu_retrigger + 10000) { display.LCDClearDisplay(); //Force relay refresh to apply inverted outputs immediately tankPump.forceRefresh(); refillPump.forceRefresh(); break; } } } //Execute this only each 5 seconds if(HAL_GetTick() > dly_switch + 5000) { dly_switch = HAL_GetTick(); HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET); //Poll Sensors tankLevel0.poll(); refillBlocker0.poll(); //Check conditions CheckTankConditions(Config_Store::getInstance(), tankLevel0, tankPump); CheckRefillConditions(Config_Store::getInstance(), tankLevel0, refillBlocker0, refillPump); //Create history if (old_minute_counter < minute_counter) { old_minute_counter = minute_counter; history_h[minute_counter % 60] = tankLevel0.getPercent(); history_d[minute_counter / 60] = tankLevel0.getPercent(); //Calculate diff to value 1h ago -> minute_counter+1's entry is always 60mins ago ! diff_hist_hour = history_h[minute_counter % 60] - history_h[(minute_counter + 1) % 60]; //Same here for daily history diff_hist_day = history_d[(minute_counter / 60) % 24] - history_d[((minute_counter + 60) / 60) % 24]; } HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_SET); } HAL_Delay(1000); //Periodically send stats via uart in json format each minute if(HAL_GetTick() > dly_stats + 60000) { dly_stats = HAL_GetTick(); char buffer[400]; sprintf(buffer, "{" "\"Status\": true, " "\"TankLevel\": %hhd, " "\"TankPump\": %s, " "\"RefillPump\": %s, " "\"RefillEmpty\": %s, " "\"RefillCooldown\": %hhd, " "\"HourlyHist\": %hhd, " "\"DailyHist\": %hhd, " "}", tankLevel0.getPercent(), (S_tankempty) ? "false" : "true", (S_refilling) ? "true" : "false", (S_refillempty) ? "true" : "false", S_refillcooldown, diff_hist_hour, diff_hist_day); SendUartString(&huart1, buffer); } } } void SystemClock_Config(void) { /*RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; *//** Configure the main internal regulator output voltage *//* __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); *//** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. *//* RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_LSI; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.LSEState = RCC_LSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLM = 12; RCC_OscInitStruct.PLL.PLLN = 144; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV6; RCC_OscInitStruct.PLL.PLLQ = 3; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } *//** Initializes the CPU, AHB and APB buses clocks *//* RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); }*/ //Workaround by using internal oscillator //TODO: Fix this issue later, must work with HSE as well RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLM = 16; RCC_OscInitStruct.PLL.PLLN = 192; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV8; RCC_OscInitStruct.PLL.PLLQ = 4; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. */ sConfig.Channel = ADC_CHANNEL_8; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } static void MX_I2C1_Init(void) { /* USER CODE BEGIN I2C1_Init 0 */ /* USER CODE END I2C1_Init 0 */ /* USER CODE BEGIN I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */ hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ /* USER CODE END I2C1_Init 2 */ } static void MX_RTC_Init(void) { /* USER CODE BEGIN RTC_Init 0 */ /* USER CODE END RTC_Init 0 */ RTC_TimeTypeDef sTime = {0}; RTC_DateTypeDef sDate = {0}; /* USER CODE BEGIN RTC_Init 1 */ /* USER CODE END RTC_Init 1 */ /** Initialize RTC Only */ hrtc.Instance = RTC; hrtc.Init.HourFormat = RTC_HOURFORMAT_24; hrtc.Init.AsynchPrediv = 127; hrtc.Init.SynchPrediv = 255; hrtc.Init.OutPut = RTC_OUTPUT_DISABLE; hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH; hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN; if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } /** Initialize RTC and set the Time and Date */ sTime.Hours = 0; sTime.Minutes = 0; sTime.Seconds = 0; sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; sTime.StoreOperation = RTC_STOREOPERATION_RESET; if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } sDate.WeekDay = RTC_WEEKDAY_MONDAY; sDate.Month = RTC_MONTH_JANUARY; sDate.Date = 1; sDate.Year = 0; if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN RTC_Init 2 */ /* USER CODE END RTC_Init 2 */ } /** * @brief TIM2 Initialization Function * @param None * @retval None */ static void MX_TIM2_Init(void) { //Timer has input of 24MHZ //Scale down with prescaler to 10kHz //Auto reload each ms /* USER CODE BEGIN TIM2_Init 0 */ /* USER CODE END TIM2_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; /* USER CODE BEGIN TIM2_Init 1 */ /* USER CODE END TIM2_Init 1 */ htim2.Instance = TIM2; htim2.Init.Prescaler = 23; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 99; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } //HAL_TIM_Base_Start(&htim2); //Directly start timer base generation in interrupt mode HAL_TIM_Base_Start_IT(&htim2); /* USER CODE BEGIN TIM2_Init 2 */ /* USER CODE END TIM2_Init 2 */ } static void MX_TIM3_Init(void) { //Timer has input of 24MHZ //Scale down with prescaler to 10kHz //Auto reload each ms /* USER CODE BEGIN TIM2_Init 0 */ /* USER CODE END TIM2_Init 0 */ TIM_ClockConfigTypeDef sClockSourceConfig = {0}; /* USER CODE BEGIN TIM2_Init 1 */ /* USER CODE END TIM2_Init 1 */ htim3.Instance = TIM3; htim3.Init.Prescaler = 24000; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 59000; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; if (HAL_TIM_Base_Init(&htim3) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } //HAL_TIM_Base_Start(&htim2); //Directly start timer base generation in interrupt mode HAL_TIM_Base_Start_IT(&htim3); /* USER CODE BEGIN TIM2_Init 2 */ /* USER CODE END TIM2_Init 2 */ } /** * @brief USART1 Initialization Function * @param None * @retval None */ static 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 = 9600; 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 */ } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(XXUNUSED_GPIO_Port, XXUNUSED_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, OCHAN0_Pin | OCHAN1_Pin | OCHAN2_Pin | BEEP_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, LED2_Pin | LED3_Pin | LED4_Pin | LED5_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, LED0_Pin | LED1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, MPWR0_Pin | MPWR1_Pin | MPWR2_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : XXUNUSED_Pin */ GPIO_InitStruct.Pin = XXUNUSED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(XXUNUSED_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pins : OCHAN0_Pin OCHAN1_Pin OCHAN2_Pin LED2_Pin LED3_Pin LED4_Pin LED5_Pin BEEP_Pin */ GPIO_InitStruct.Pin = OCHAN0_Pin | OCHAN1_Pin | OCHAN2_Pin | LED2_Pin | LED3_Pin | LED4_Pin | LED5_Pin | BEEP_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : RRDT_Pin RRSW_pin RRCLK_Pin */ GPIO_InitStruct.Pin = RRDT_Pin | RRSW_Pin | RRCLK_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : ADC1_2_Pin */ GPIO_InitStruct.Pin = ADC1_2_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(ADC1_2_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pins : MPWR0_Pin MPWR1_Pin MPWR2_Pin LED0_Pin LED1_Pin */ GPIO_InitStruct.Pin = MPWR0_Pin | MPWR1_Pin | MPWR2_Pin | LED0_Pin | LED1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : GPI1_Pin GPI2_Pin GPI0_Pin */ GPIO_InitStruct.Pin = GPI1_Pin | GPI2_Pin | GPI0_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } /** * @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 */ __disable_irq(); MX_GPIO_Init(); HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_RESET); while (1) { } /* 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, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */