2012-02-27 02:29 AM
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.2012-02-27 05:11 AM
Provide the ADC_config() and NVIC_config() code.
Cheers, Hal2012-02-27 07:28 AM
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 me2012-02-27 10:48 AM
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, Hal2012-02-28 01:53 AM
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.??2012-02-28 07:06 AM
..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.
2012-02-28 07:59 PM
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??2012-02-29 03:52 AM
Hi..
I would like to know how DMA works..Can i implement ADC with DMA. insted of using ADc in polled mode?? Please suggest...2012-02-29 05:06 AM
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, Hal2012-02-29 06:17 AM
You'll definitely want to look at DMA, 150 timer cycles between interrupts is awfully tight, and compounded by the while() spin loop.