AnsweredAssumed Answered

ADC DR alignment

Question asked by sunny on Nov 6, 2012
Latest reply on Dec 23, 2012 by Clive One

Hi: I am using an an STM32F217, and have some difficulty understanding the behaviour of the ADC peripheral. I want to set up ADC1 on pin PA7 to convert on-demand i.e. would like to poll the ADC pin when I want to, otherwise leaving the ADC idle.

I initially tried following the example given in the STM32F2xx firmware library, however as soon as a conversion is started, the OVR flag is set, and that somehow causes the EOC flag to never be set, thus hanging my thread.

Once I started deliberately clearing the OVR flag, I could get the conversions started. However, this time all the data seemed to be left-aligned, although I set it to right-alignment. Furthermore, in the firmware library example, the parameter ADC_ExternalTrigConv is not being set. When I assigned any acceptable value to this parameter e.g. ADC_ExternalTrigConv_T1_CC1, I managed to get right-aligned data in the DR. I still get OVR errors ( with ADC1_CR2_DMA = 0 and ADC1_CR2_ECOS = 1 ).

Could someone kindly shine some light on what I could be doing wrong here? Here's my configuration code as it is right now, with proper data alignment but OVR being generated every time. Thanks for any comments.

void adc1_init( void )
  GPIO_InitTypeDef gpio;
  ADC_CommonInitTypeDef adc_common;
  ADC_InitTypeDef adc;
  // Enable GPIO clock
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE );
  // Configure PA7 as ADC input
  gpio.GPIO_Pin = GPIO_Pin_7;
  gpio.GPIO_Mode = GPIO_Mode_AN;
  GPIO_Init( GPIOA, &gpio );

  // Enable ADC1 clock and reset ADC1 peripheral
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_ADC1, ENABLE );
  RCC_APB2PeriphResetCmd( RCC_APB2Periph_ADC1, ENABLE );
  RCC_APB2PeriphResetCmd( RCC_APB2Periph_ADC1, DISABLE );
  // Configure ADC1
  adc.ADC_Resolution = ADC_Resolution_12b;
  adc.ADC_ScanConvMode = DISABLE;
  adc.ADC_ContinuousConvMode = DISABLE;
  adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
  adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
  adc.ADC_DataAlign = ADC_DataAlign_Right;
  adc.ADC_NbrOfConversion = 1;
  ADC_Init( ADC1, &adc );
  ADC_RegularChannelConfig( ADC1, ADC_Channel_7, 1, ADC_SampleTime_480Cycles );
  ADC_EOCOnEachRegularChannelCmd( ADC1, ENABLE );
  ADC_Cmd( ADC1, ENABLE );

unsigned short read_adc1( void )
  // ignore overrun
  // - ADC_SR->OVR gets set despite disabling DMA
  ADC_ClearFlag( ADC1, ADC_FLAG_OVR );
  // start conversion
  ADC_SoftwareStartConv( ADC1 );
  // wait until conversion complete
  while( ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC ) == RESET );
  // return measured value
  return ADC_GetConversionValue( ADC1 );