jayy_nguyen
jayy_nguyen

Reputation: 3

How to correctly read the ADC values on STM32

I want to read the ADC values from the pins of the STM32F072C8U6 MCU. But the values I read are not consistent with the ones I measure with an oscilloscope, and sometimes I can read them, sometimes I cannot. I have tried to reconfigure the ADC initialization several times, but it is still unsuccessful. READ VOLTAGE

bool PM_ReadVoltage(const TestPointSpec *spec, float *val, bool raw)
{
    bool success = false;
    ADC_ChannelConfTypeDef channelConf;

    HAL_ADC_Stop(&hadc);
    HAL_ADCEx_Calibration_Start(&hadc);

    channelConf.Rank = 1;
    channelConf.SamplingTime = CONFIG_ADC_SAMPLE_TIME;
    channelConf.Channel = spec->adcChannel;

    if (HAL_ADC_ConfigChannel(&hadc, &channelConf) != HAL_OK)
    {
        return false;
    }

    HAL_ADC_Start(&hadc);
    HAL_StatusTypeDef rc = HAL_ADC_PollForConversion(&hadc, 500);

    if (rc == HAL_OK)
    {
        uint32_t res = HAL_ADC_GetValue(&hadc);

        #if CONFIG_CALIB_MODE == 1
                COM_Trace("Raw %s=%d", spec->name, res);
        #endif

        if (!raw && spec->isHalf)
        {
            *val = (float)res * gAdcResolution * 2;
        }
        else
        {
            *val = (float)res * gAdcResolution;
        }
    }
    else
    {
        goto out;
    }

    *val += *val * spec->testPointVolLinearCalib;
    success = true;
out:
    channelConf.Rank = ADC_RANK_NONE;
    HAL_ADC_ConfigChannel(&hadc, &channelConf);
    HAL_ADC_Stop(&hadc);
    HAL_Delay(100);

    return success;
}

HAL_INIT

static void ADC1_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

      hadc.Instance = ADC1;
      hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
      hadc.Init.Resolution = ADC_RESOLUTION_12B;
      hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
      hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
      hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
      hadc.Init.LowPowerAutoWait = DISABLE;
      hadc.Init.ContinuousConvMode = ENABLE;
      hadc.Init.DiscontinuousConvMode = DISABLE;
      hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
      hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
      hadc.Init.DMAContinuousRequests = DISABLE;
      hadc.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

    if (HAL_ADC_Init(&hadc) != HAL_OK)
    {
        Error_Handler();
    }

    HAL_ADCEx_Calibration_Start(&hadc);
    HAL_Delay(10);

    sConfig.Channel = ADC_CHANNEL_VREFINT;
    sConfig.Rank = 1;
    sConfig.SamplingTime = CONFIG_ADC_SAMPLE_TIME;

    const uint16_t VREFIN_CAL = *((uint16_t*)0x1FFFF7BA);

    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
        Error_Handler();
    }

    HAL_ADC_Start(&hadc);

    if (HAL_ADC_PollForConversion(&hadc, 500) == HAL_OK)
    {
        uint32_t val = HAL_ADC_GetValue(&hadc);
        uint32_t vdda = (3300UL * (uint32_t)VREFIN_CAL) / val;
        PM_SetVDDA(vdda / 1000.0f);
    }

    sConfig.Rank = ADC_RANK_NONE;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);

    HAL_ADC_Stop(&hadc);
}

CONFIG GPIO ADC

#define ADC_PIN_NUM     7

#define ADC_INPUT_3     { .port = GPIOA, .pin = GPIO_PIN_3 }
#define ADC_INPUT_4     { .port = GPIOA, .pin = GPIO_PIN_4 }
#define ADC_INPUT_5     { .port = GPIOA, .pin = GPIO_PIN_5 }
#define ADC_INPUT_6     { .port = GPIOA, .pin = GPIO_PIN_6 }
#define ADC_INPUT_7     { .port = GPIOA, .pin = GPIO_PIN_7 }
#define ADC_INPUT_8     { .port = GPIOB, .pin = GPIO_PIN_0 }
#define ADC_INPUT_9     { .port = GPIOB, .pin = GPIO_PIN_1 }

READ ADC IMAGE READ ADC IMAGE

Upvotes: 0

Views: 513

Answers (0)

Related Questions