#include "main.h" #include "usb_device.h" #include "usbd_cdc_if.h" #include "LCD_I2C_Driver.h" #include "InitSequence.h" #include "button_input.h" #include "Menu.h" #include "Menu_Entry_Type_Checkable.h" #include "Menu_Entry_Type_Numeric.h" #include "Menu_Entry_Type_Percent.h" #include "Menu_Entry_Type_ReadOnly.h" #include "Menu_Entry_Type_Time.h" #include "Config_Store.h" #include "Menu_Controller.h" #define SLAVE_ADDRESS_LCD 0x4e ADC_HandleTypeDef hadc1; I2C_HandleTypeDef hi2c1; RTC_HandleTypeDef hrtc; TIM_HandleTypeDef htim2; 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_USART1_UART_Init(void); extern int16_t rot_counter; extern bool rot_button; using namespace floatpump; int main(void) { Config_Store globalConfig; // 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_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); //Run init Sequence InitSequence initializer(display); initializer.runInitSequence(); //Enable green led HAL_GPIO_WritePin(LED5_GPIO_Port, LED5_Pin, GPIO_PIN_RESET); /// /// /// EXPERIMENTAL CODE BEGIN /// /// /// using namespace floatpump::menu; Menu mainmenu("Hauptmenu"); Menu_Entry_Type_Checkable entry1bool(false), entry2bool(false); bool l_calib = false, h_calib = false; uint16_t lcb = 0, hcb = 4096; uint8_t perc = 50; uint8_t cur_perc = 0; uint32_t current = 0; entry1bool.linkConfig(&l_calib); entry2bool.linkConfig(&h_calib); Menu_Entry entry(entry1bool, "Low Calib"); Menu_Entry entry2(entry2bool, "High Calib"); Menu_Entry_Type_Percent entry1perc(15); Menu_Entry entry3(entry1perc, "Pegel Schalten"); Menu_Entry_Type_ReadOnly entry1read(0); entry1read.linkConfig(¤t); Menu_Entry entry4(entry1read, "Pegel"); Menu_Entry_Type_ReadOnly entry2read(0); entry2read.linkConfig(&cur_perc); Menu_Entry entry5(entry2read, "Pegel Proz"); mainmenu.addEntry(entry); mainmenu.addEntry(entry2); mainmenu.addEntry(entry3); mainmenu.addEntry(entry4); mainmenu.addEntry(entry5); Menu_Controller controller(&mainmenu, display); HAL_GPIO_WritePin(MPWR0_GPIO_Port, MPWR0_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(MPWR2_GPIO_Port, MPWR2_Pin, GPIO_PIN_SET); uint16_t timed_tp = 0; uint16_t averaging[25]; int index_avg = 0; static int old_pos = 0; while (1) { controller.execute(); if (rot_button) { rot_button = false; controller.pushEvent(Menu_Controller::Event::Push); } if (old_pos < rot_counter) { controller.pushEvent(Menu_Controller::Event::Increase); old_pos = rot_counter; } else if (old_pos > rot_counter) { controller.pushEvent(Menu_Controller::Event::Decrease); old_pos = rot_counter; } HAL_Delay(100); timed_tp++; //Execute each second uint32_t measured, avg = 0; HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, 1); measured = HAL_ADC_GetValue(&hadc1); averaging[index_avg % 25] = measured; for(int i = 0; i < 25; i++) { avg += averaging[i]; } current = avg/25; index_avg++; //calibrate if(l_calib) { l_calib = false; lcb = current - 10; } if(h_calib) { h_calib = false; hcb = current + 10; } cur_perc = ((current - lcb) *100)/(hcb-lcb); if(cur_perc > perc + 5) { HAL_GPIO_WritePin(OCHAN0_GPIO_Port, OCHAN0_Pin, GPIO_PIN_SET); } else if(cur_perc < perc - 5) { HAL_GPIO_WritePin(OCHAN0_GPIO_Port, OCHAN0_Pin, GPIO_PIN_RESET); } } } 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_LSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.LSEState = RCC_LSE_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(); } } 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 */ } /** * @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 = 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 */ } 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(); 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 */