3

STM3240G-EVAL ボードを使用して ADC から値を読み込みます。以下の印刷機能を使用して、ADC からボード上の LCD に値を印刷します。温度センサーを評価ボードの 3.3V、ADC3、および GND に物理的に接続しました。返される値が大きすぎます。ADC 分解能は 12 ビットであると想定されているため、4096 は ADC_GetConversionValue 関数によって出力される最大値である必要があります。室温で 5000 以上の値を取得しています! 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;
}
4

4 に答える 4

3

ADC 構成がありませんでした。

ADC_InitStructure.ADC_NbrOfConversion = 1;

ADC を使用しているときは、すべての構成を使用していて、欠落していないことを確認してください。これを含めた後、マルチメーターを使用して、センサーが読み取ったADC値と同じ電圧を取得できました。

追加された説明:

これは、次の構造をローカル構造として定義したためです。

ADC_InitTypeDef           ADC_InitStructure;

ADC_CommonInitTypeDef     ADC_CommonInitStructure;

また、ローカル変数の初期値が信頼できない(ランダムな)値であるため、対応するレジスタに書き込むと、 ADC_NbrOfConversionが不適切な数値になるなどの問題が発生する可能性があります。

于 2014-08-05T15:42:36.353 に答える
0

次のコードは私のために働いています:


#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;
}
于 2014-08-05T16:02:58.543 に答える
0

温度センサーの電圧、ACD 入力の電圧、およびデバイスの VCC 電圧を測定しましたか? この 5000 以上の出力を取得している時点で、実行時の値を含めることをお勧めします。

事前に既知の電圧 (たとえば 3.3 V) を同じ ADC 入力に供給して、測定値/取得値を比較しようとしましたか? 5000+ で測定した電圧は 4+V のようです。

コードに関しては、12 ビットのみを考慮するために、戻り値をマスクする方がよいでしょう。

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

于 2014-07-17T02:09:28.517 に答える