#include "drivers/adc/adc.h" #include "stm32l1xx_hal.h" #include "stm32l1xx_hal_adc.h" #include "stm32l1xx_hal_adc_ex.h" #include "core/csect.h" #include "core/config_pins.h" static bool ADC_Init( eADC_Resolution_t resolution ); static bool ADC_Start( uint32_t chid ); static bool ADC_Measure( uint32_t timeout, tADCValue_t * pResult ); static void ADC_Stop( uint32_t chid ); static uint32_t ADC_GetVoltage(tADCValue_t * pResult); static void ADC_DeInit(); static tADCValue_t ADCResult = 0; ADC_HandleTypeDef Adc1Handle; const ADC_Handle_t ADC1Handle = { ADC_Init, ADC_Start, ADC_Measure, ADC_Stop, ADC_GetVoltage, ADC_DeInit, }; static bool ADC_Init( eADC_Resolution_t resolution ) { DI(); /* Configure the ADC1 IN0 for analog input */ __HAL_RCC_HSI_ENABLE(); __HAL_RCC_ADC1_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Configure the ADC peripheral */ Adc1Handle.Instance = ADC1; Adc1Handle.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; switch( resolution ) { case eADCRes_12bit: Adc1Handle.Init.Resolution = ADC_RESOLUTION_12B; break; case eADCRes_10bit: Adc1Handle.Init.Resolution = ADC_RESOLUTION_10B; break; case eADCRes_8bit: Adc1Handle.Init.Resolution = ADC_RESOLUTION_8B; break; case eADCRes_6bit: default: Adc1Handle.Init.Resolution = ADC_RESOLUTION_6B; break; } Adc1Handle.Init.ScanConvMode = DISABLE; Adc1Handle.Init.ContinuousConvMode = DISABLE; Adc1Handle.Init.DiscontinuousConvMode = DISABLE; Adc1Handle.Init.NbrOfDiscConversion = 0; Adc1Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; Adc1Handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; Adc1Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; Adc1Handle.Init.NbrOfConversion = 1; Adc1Handle.Init.DMAContinuousRequests = DISABLE; Adc1Handle.Init.EOCSelection = DISABLE; Adc1Handle.Init.LowPowerAutoPowerOff = ADC_AUTOPOWEROFF_DISABLE; bool bRet = ( HAL_OK == HAL_ADC_Init(&Adc1Handle) ); //HAL_NVIC_SetPriority( ADC1_IRQn, ADC1_INT_PRIORITY, 0); //HAL_NVIC_EnableIRQ( ADC1_IRQn ); EI(); return bRet; } static bool ADC_Start( uint32_t chid ) { ADC_ChannelConfTypeDef sConfig; DI(); /* Configure ADC regular channel */ sConfig.Channel = chid; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_4CYCLES; bool bRet = ( HAL_OK == HAL_ADC_ConfigChannel(&Adc1Handle, &sConfig) ); EI(); return bRet; } static bool ADC_Measure( uint32_t timeout, tADCValue_t * pResult ) { bool bResult = false; if( HAL_OK == HAL_ADC_Start( &Adc1Handle ) ) { // ADC performs fast conversion within 4 cycles: 2ms timeout is enough if no high-priority interrupts fires if( HAL_OK == HAL_ADC_PollForConversion( &Adc1Handle, timeout ) ) { DI(); if( HAL_ADC_ERROR_NONE == HAL_ADC_GetError( &Adc1Handle ) ) { ADCResult = (tADCValue_t)HAL_ADC_GetValue( &Adc1Handle ); bResult = true; } else { ADCResult = (tADCValue_t)(-2L); } if( bResult ) { if( pResult ) *pResult = ADCResult; } EI(); } } return bResult; } static void ADC_Stop( uint32_t chid ) { // To deconfigure the channel the ADC_DeInit() call is required. (void)chid; // no operations performed } static void ADC_DeInit() { DI(); HAL_NVIC_DisableIRQ( ADC1_IRQn ); HAL_ADC_Stop( &Adc1Handle ); HAL_ADC_DeInit( &Adc1Handle ); __HAL_RCC_ADC1_CLK_DISABLE(); EI(); } static uint32_t ADC_GetVoltage(tADCValue_t * pResult) { return (uint32_t)((float)(*pResult * ADC_VRED_V / 0xFFF) * 10 / KDIVIDER()); } void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc) { } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { }