#include "libs/task.h" #include "hal/adc.h" static ADC_HandleTypeDef hadc1; void HAL_ADC1_Init(void){ ADC_InjectionConfTypeDef sConfigInjected = {0}; ADC_ChannelConfTypeDef sConfig = {0}; hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; 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_LEFT; hadc1.Init.NbrOfConversion = 2; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure Injected Channel */ sConfigInjected.InjectedChannel = ADC_CHANNEL_1; sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1; sConfigInjected.InjectedSingleDiff = ADC_SINGLE_ENDED; sConfigInjected.InjectedNbrOfConversion = 3; sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_7CYCLES_5; sConfigInjected.ExternalTrigInjecConvEdge = ADC_EXTERNALTRIGINJECCONV_EDGE_RISING; sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T1_TRGO; sConfigInjected.AutoInjectedConv = DISABLE; sConfigInjected.InjectedDiscontinuousConvMode = DISABLE; sConfigInjected.QueueInjectedContext = ENABLE; sConfigInjected.InjectedOffset = 0; sConfigInjected.InjectedOffsetNumber = ADC_OFFSET_NONE; if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK) { Error_Handler(); } /** Configure Injected Channel */ sConfigInjected.InjectedChannel = ADC_CHANNEL_7; sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2; if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK) { Error_Handler(); } /** Configure Injected Channel */ sConfigInjected.InjectedChannel = ADC_CHANNEL_6; sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3; if (HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_2; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.SamplingTime = ADC_SAMPLETIME_61CYCLES_5; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_8; sConfig.Rank = ADC_REGULAR_RANK_2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } void HAL_ADC1_Enable(void) { ADC_TypeDef * ADCx = hadc1.Instance; /* disable IT and flags in case of LL driver usage * workaround for unwanted interrupt enabling done by LL driver */ LL_ADC_DisableIT_EOC( ADCx ); LL_ADC_ClearFlag_EOC( ADCx ); LL_ADC_DisableIT_JEOC( ADCx ); LL_ADC_ClearFlag_JEOC( ADCx ); if (LL_ADC_IsEnabled (ADCx) == 0) { if ( LL_ADC_IsInternalRegulatorEnabled(ADCx) == 0u) { /* Enable ADC internal voltage regulator */ LL_ADC_EnableInternalRegulator(ADCx); /* Wait for Regulator Startup time */ /* Note: Variable divided by 2 to compensate partially */ /* CPU processing cycles, scaling in us split to not */ /* exceed 32 bits register capacity and handle low frequency. */ volatile uint32_t wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US / 10UL) * (SystemCoreClock / (100000UL * 2UL))); while(wait_loop_index != 0UL) { wait_loop_index--; } } LL_ADC_StartCalibration( ADCx, LL_ADC_SINGLE_ENDED ); while ( LL_ADC_IsCalibrationOnGoing( ADCx) == 1u) {} /* ADC Enable (must be done after calibration) */ /* ADC5-140924: Enabling the ADC by setting ADEN bit soon after polling ADCAL=0 * following a calibration phase, could have no effect on ADC * within certain AHB/ADC clock ratio. */ while ( LL_ADC_IsActiveFlag_ADRDY( ADCx ) == 0u) { LL_ADC_Enable( ADCx ); } /* Clear JSQR from CubeMX setting to avoid not wanting conversion*/ //LL_ADC_INJ_StartConversion( ADCx ); //LL_ADC_INJ_StopConversion(ADCx); /* TODO: check if not already done by MX */ LL_ADC_INJ_SetQueueMode( ADCx, LL_ADC_INJ_QUEUE_2CONTEXTS_END_EMPTY ); /* Only the Interrupt of the first ADC is enabled. * As Both ADCs are fired by HW at the same moment * It is safe to consider that both conversion are ready at the same time*/ LL_ADC_ClearFlag_JEOS( ADCx ); LL_ADC_EnableIT_JEOS( ADCx ); } HAL_NVIC_EnableIRQ(ADC1_IRQn); //LL_ADC_INJ_StartConversion( ADCx ); } void HAL_ADC1_InJ_StartConvert(void) { ADC_TypeDef * ADCx = hadc1.Instance; while(LL_ADC_INJ_IsConversionOngoing( ADCx ) == 0) { LL_ADC_INJ_StartConversion( ADCx ); } } void HAL_ADC1_ChanConfig(u32 channel) { if (LL_ADC_IsEnabled(hadc1.Instance) == 0 ) { LL_ADC_DisableIT_EOC(hadc1.Instance); LL_ADC_ClearFlag_EOC(hadc1.Instance); LL_ADC_DisableIT_JEOC(hadc1.Instance); LL_ADC_ClearFlag_JEOC(hadc1.Instance); LL_ADC_StartCalibration( hadc1.Instance, LL_ADC_SINGLE_ENDED ); while ( LL_ADC_IsCalibrationOnGoing( hadc1.Instance ) ) { } LL_ADC_Enable( hadc1.Instance ); } /* reset regular conversion sequencer length set by cubeMX */ LL_ADC_REG_SetSequencerLength( hadc1.Instance, LL_ADC_REG_SEQ_SCAN_DISABLE ); /* configure the sampling time (should already be configured by for non user conversions)*/ LL_ADC_SetChannelSamplingTime ( hadc1.Instance, __LL_ADC_DECIMAL_NB_TO_CHANNEL(channel) ,ADC_SAMPLETIME_61CYCLES_5); } u16 HAL_ADC1_ReadValue(u32 channel) { u16 retVal; LL_ADC_REG_SetSequencerRanks( hadc1.Instance, LL_ADC_REG_RANK_1, __LL_ADC_DECIMAL_NB_TO_CHANNEL( channel ) ); LL_ADC_REG_ReadConversionData12(hadc1.Instance); LL_ADC_REG_StartConversion(hadc1.Instance); /* Wait until end of regular conversion */ u64 StartTime = get_mseconds(); while ( LL_ADC_IsActiveFlag_EOC(hadc1.Instance) == 0u ) { if (get_mseconds() - StartTime >= 1) { LL_ADC_REG_StartConversion(hadc1.Instance); StartTime = get_mseconds(); } } retVal = LL_ADC_REG_ReadConversionData12(hadc1.Instance); return retVal; }