cancel
Showing results for 
Search instead for 
Did you mean: 

Reading voltage -ADC

mayakk12
Associate II
Posted on February 27, 2012 at 11:29

hi..

I'm using STM32 VL microcontroller.I need to read voltage continiously..so i'm using timer 2 in interupt mode to read ADC value.below is my code.. wheneven ADCread value function is colled from TIM2 interrupt, i goes to  infine loop in while function..

Can any body tell me why its happening like that.or is that any alternate method to implement..??

int main()

{

NVIC_config(); // timer 2 interrupt

Timer2_config();

ADC_config();

While(1)

{}

}

int ADCReadValue()

{

 ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_1Cycles5);

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

// code hangs in this while loop

while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

 return ADC_GetConversionValue(ADC1);

}

void TIM2_IRQHandler()

{

    if(TIM_GetITStatus(TIM@, TIM_IT_Update) != RESET)

    {

        readADCValue();

        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

    }

}

#timer #adc #stm32 #adc-and-tim2-interrupt.
27 REPLIES 27
raptorhal2
Lead
Posted on February 27, 2012 at 14:11

Provide the ADC_config() and NVIC_config() code.

Cheers, Hal

mayakk12
Associate II
Posted on February 27, 2012 at 16:28

void NVIC_conf(void)

{

    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    

    NVIC_Init(&NVIC_InitStructure);

}

void ADC_Configuration(void)

{

ADC_InitTypeDef ADC_InitStructure;

ADCCLK = 12MHz

RCC_ADCCLKConfig(RCC_PCLK2_Div6);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

ADC_DeInit(ADC1);

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

/* Disable the scan conversion so we do one at a time */ ADC_InitStructure.ADC_ScanConvMode = DISABLE;

 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

/* Start conversin by software, not an external trigger */ ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

/* Say how many channels would be used by the sequencer */ ADC_InitStructure.ADC_NbrOfChannel = 1;

/* Now do the setup */

 ADC_Init(ADC1, &ADC_InitStructure);

 /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE);

/* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1));

 /* Start ADC1 calibaration */

 ADC_StartCalibration(ADC1);

 while(ADC_GetCalibrationStatus(ADC1));

}

I tried caling readADCValue function in while loop..Its working fine..and if i run only time function i'm getting the proper interrupt.only when i try to call readADCvalue from TIM2_IRQ function its going to infinit lopp in while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

Please help me
raptorhal2
Lead
Posted on February 27, 2012 at 19:48

Try clearing the pending interrupt before starting conversion.

I presume that somewhere you have initialized the value of ''channel'' in the ADC_RegularChannelConfig statement.

If the input is channel 0 to 15 you will have to set the input pin alternate function to analog input to get valid results.

Cheers, Hal

mayakk12
Associate II
Posted on February 28, 2012 at 10:53

hi..

I tried clearing the interrupt and also disable it..i dint work.

I have done the GPIO configuration to GPIO_Mode_AIN.

Please help to solve this..Or is there any alternate method.??

Posted on February 28, 2012 at 16:06

..Or is there any alternate method.??

 

I'd guess that most people would use the timer to trigger the conversion start, and then pick up the result in the EOC interrupt. Starting, and waiting for conversions in the interrupt is a little problematic.

You also need to post COMPLETE examples, posting incomplete fragments that fail to show the peripheral, pin, timer and clock initializations, will not result in the answers you are looking for.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
mayakk12
Associate II
Posted on February 29, 2012 at 04:59

hi..

below is my code...Requirement is like this..I need to read the voltage continuously ie is for every 6.25micro sec. So i'm calling ADC read function from Timer interrupt so that i can read the value at know time. I'm reading ADC value in polled mode..Is there any other method to implement this..??

__IO uint32_t ADCValue;

int main(void)

{

  ADC_Config();

    NVIC_Config();

    Timer_Config();

 while(1)

  {

  }

  return 1;

}

void ADC_Config(void)

{

    ADC_InitTypeDef ADC_InitStructure;

    RCC_Config();

    GPIO_Config();

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

    ADC_InitStructure.ADC_ScanConvMode = DISABLE;

    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;

    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

    ADC_InitStructure.ADC_NbrOfChannel = 1;

    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_1Cycles5);

    ADC_Cmd(ADC1, ENABLE);

    ADC_ResetCalibration(ADC1);

    while(ADC_GetResetCalibrationStatus(ADC1));

    ADC_StartCalibration(ADC1);

    while(ADC_GetCalibrationStatus(ADC1));

}

uint32_t readADCValue(void)

{

  ADC_SoftwareStartConvCmd(ADC1, ENABLE);

  /* Wait until conversion completion*/

  while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);

  return ADC_GetConversionValue(ADC1);

}

void RCC_Config(void)

{

  RCC_ADCCLKConfig(RCC_PCLK2_Div2);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE);

}

void GPIO_Config(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure PC.04 (ADC Channel14) as analog input */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

}

void NVIC_Config(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

void Timer_Config(void)

{

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

  TIM_DeInit(TIM2);

  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  TIM_TimeBaseStructure.TIM_Period = 150 - 1;

  TIM_TimeBaseStructure.TIM_Prescaler = 0;

  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  TIM_Cmd(TIM2,ENABLE);

}

void TIM2_IRQHandler(void)

{

  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)

  {

      ADCValue = readADCValue();

     TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

  }

}

Please help..Can i use DMA??

mayakk12
Associate II
Posted on February 29, 2012 at 12:52

Hi..

I would like to know how DMA works..Can i implement ADC with DMA. insted of using ADc in polled mode??

Please suggest... 

raptorhal2
Lead
Posted on February 29, 2012 at 14:06

Yes you can, and you must use DMA to convert more than one channel. See the ADC1_DMA example that comes with the Standard Peripheral Library.

Cheers, Hal

Posted on February 29, 2012 at 15:17

You'll definitely want to look at DMA, 150 timer cycles between interrupts is awfully tight, and compounded by the while() spin loop.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..