简体   繁体   English

STM32 ADC值读数过高

[英]STM32 ADC values reading too high

I am using an STM3240G-EVAL board to read in values from the ADC. 我正在使用STM3240G-EVAL板读取ADC的值。 I print the values from the ADC to the LCD on my board using the print function below. 我使用下面的打印功能将ADC中的值打印到我板上的LCD上。 I physically connected the temperature sensor to 3.3V, ADC3, and GND on the eval board. 我将温度传感器物理连接到评估板上的3.3V,ADC3和GND。 The values that are being returned are too large. 返回的值太大。 The ADC Resolution is supposed to be 12 bit so 4096 should be the maximum value output by the ADC_GetConversionValue function. ADC分辨率应为12位,因此4096应为ADC_GetConversionValue函数输出的最大值。 I am receiving 5000+ values at room temperature! 我在室温下接收5000+值! Does anyone have any intuition as to why the ADC values could be getting scaled? 有没有人对为什么ADC值可以缩放有任何直觉?

////// stm324xg_eval.c
// to configure the ADC
void STM_EVAL_TEMPInit(Temp_TypeDef Temp) 
{

RCC_PCLK2Config(RCC_HCLK_Div8);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
/* Enable the GPIO_TEMP Clock */
RCC_AHB1PeriphClockCmd(GPIO_TEMP_CLK[Temp], ENABLE);

/* Configure the GPIO_TEMP pin */
GPIO_InitTypeDef  GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_TEMP_PIN[Temp];
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIO_TEMP_PORT[Temp], &GPIO_InitStructure);


/* Enable ADC3 Clock */
ADC_InitTypeDef           ADC_InitStructure;
ADC_CommonInitTypeDef     ADC_CommonInitStructure;

ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = 0;
ADC_CommonInit(&ADC_CommonInitStructure);

ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;      
ADC_Init(ADC3, &ADC_InitStructure);

ADC_RegularChannelConfig(ADC3, ADC_Channel_4, 1, ADC_SampleTime_144Cycles);
ADC_Cmd(ADC3, ENABLE);
}


////// main.cpp
// to print to lcd  
ADC_SoftwareStartConv(ADC3);
temp_value = ADC_GetConversionValue(ADC3);
uint8_t mymsg[20];
sprintf((char *)mymsg, "ADC = %d",(int)temp_value);
LCD_DisplayStringLine(Line6, mymsg);


////// stm32f4xx_adc.c
// ADC_GetConversionValue function
/**
* @brief  Returns the last ADCx conversion result data for regular channel.
* @param  ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval The Data conversion value.
*/
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)
{
   /* Check the parameters */
   assert_param(IS_ADC_ALL_PERIPH(ADCx));
   /* Return the selected ADC conversion value */
   return (uint16_t) ADCx->DR;
}

I was missing an ADC configuration; 我错过了ADC配置;

ADC_InitStructure.ADC_NbrOfConversion = 1;

Make sure when you are using the ADC you are using all the configurations and not missing any. 确保在使用ADC时,您正在使用所有配置而不会遗漏任何配置。 After including this I was able to get the same voltage using a multimeter as the ADC values read by the sensor. 在包括这个之后,我能够使用万用表获得与传感器读取的ADC值相同的电压。

Added description : 添加说明:

And this is because of you have defined the following structures as a local one : 这是因为您已将以下结构定义为本地结构:

ADC_InitTypeDef           ADC_InitStructure;

ADC_CommonInitTypeDef     ADC_CommonInitStructure;

and a local variable has an unreliable(random) initial value so that it may cause for example ADC_NbrOfConversion becomes inappropriate number that makes such a problem when it has been written in the corresponding register. 并且局部变量具有不可靠(随机)的初始值 ,因此可能导致例如ADC_NbrOfConversion变为不适当的数字,当它被写入相应的寄存器时会产生这样的问题。

You do have to wait for the conversion to complete: 您必须等待转换完成:

ADC_SoftwareStartConv(ADC3);

while( ADC_GetFlagStatus( ADC3, ADC_FLAG_EOC ) == RESET )
{
    // do nothing (or something useful perhaps)
}

temp_value = ADC_GetConversionValue(ADC3);

Did you measure the voltage at the temperature sensor and the voltage on your ACD input and VCC voltage on your device? 您是否测量了温度传感器上的电压以及ACD输入端的电压和设备上的VCC电压? It is better to include their run-time values at the moment you are taking this 5000+ output. 在您使用5000+输出时,最好包括它们的运行时值。

Did you try to feed known in advance voltage (say 3.3 V) to the same ADC input and compare measured/obtained values? 您是否尝试将已知的预先电压(例如3.3 V)馈送到相同的ADC输入并比较测量/获得的值? Because it seems the voltage you measure taking 5000+ is like 4+V. 因为看起来你测量5000+的电压似乎是4 + V.

As for code, it is probably better to mask returning value in order to take only 12 bit into account: 至于代码,最好掩盖返回值以便只考虑12位:

return (uint16_t) ((ADCx->DR) & 0xFFF)

The following code has worked for me: 以下代码对我有用:


#define HW_DIVIDE      2
#define VREF_IN_mV     2500
#define MAX_RESOLUTION 255

static void _setup_rcc()
{
    // Enable the ADC interface clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

    // Enable the clock for the ADC GPIOs
    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE);
}

static void _setup_gpio()
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // Configure source 1
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure source 2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure source 3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // Configure source 4
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

static void _setup_adc()
{
    ADC_InitTypeDef ADC_InitStructure;
    ADC_DeInit();
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_Resolution = ADC_Resolution_8b;
    ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 16;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_Init(ADC1, &ADC_InitStructure);

    // Enable ADC
    ADC_Cmd(ADC1, ENABLE);
}

void drv_adc_init()
{
    _setup_rcc();
    _setup_gpio();
    _setup_adc();
}

uint16_t drv_adc_get_voltage(ADC_CHANNEL_IN type)
{
    uint16_t val;

    switch (type)
    {
    case ADC_3V3:
        ADC_RegularChannelConfig(ADC1,ADC_Channel_4,1,ADC_SampleTime_15Cycles);
        break;
    case ADC_1V2:
        ADC_RegularChannelConfig(ADC1,ADC_Channel_5,1,ADC_SampleTime_15Cycles);
        break;
    case ADC_3VA:
        ADC_RegularChannelConfig(ADC1,ADC_Channel_6,1,ADC_SampleTime_15Cycles);
        break;
    case VIB_CUR:
        ADC_RegularChannelConfig(ADC1,ADC_Channel_7,1,ADC_SampleTime_15Cycles);
        break;
    }

    do
    {
        // Start the conversion
        ADC_SoftwareStartConv(ADC1);

        // Processing the conversion
        if (ADC_GetFlagStatus(ADC1, ADC_FLAG_OVR))
        {
            ADC1->SR &= ~ADC_FLAG_OVR;
        }
    }
    while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

    // Calculate the converted data
    val = ADC_GetConversionValue(ADC1);

    // Return voltage in millivolts
    return HW_DIVIDE * VREF_IN_mV * val / MAX_RESOLUTION;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM