AnsweredAssumed Answered

STM32L152 ADC with TIMER reads only once

Question asked by melt brink on Mar 8, 2017
Latest reply on Mar 13, 2017 by melt brink

Im trying to read a battery voltage with a  STM32L152, using timer 2 to trigger the ADC. I can see Timer 2 running (by toggling a LED in the TMR2 interrupt routine) but my ADC only reads once (when the circuit initially switch on) . I have trawled the internet for solutions but still cant find what i'm missing or where i'm going wrong. If I debug, my program never enters the ADC IRQ  function. I presume a flag is not being cleared. Any assistance will be greatly appreciated.

Below is relevant code.

 

int main(void)
{

 

RCC_Configuration();  // call clock setup
NVIC_Configuration();  // call interrupt setup
GPIO_Configuration();  // gpio config
TIM2_Configuration();  // tim2 setup
ADC_Configuration(); // adc setup
ADC_SoftwareStartConv(ADC1); /* Start ADC1 Software Conversion */

 

gpio_config(GPIO0_PORT, GPIO0_PIN, GPIO_PP); // setup GPIO0 as output
gpio_config(GPIO1_PORT, GPIO1_PIN, GPIO_PP); // setup GPIO1 as output
gpio_config(GPIO3_PORT, GPIO3_PIN, GPIO_PP); // setup GPIO3 as output
gpio_set_state(GPIO3_PORT, GPIO3_PIN, SET);// set led high, turn led off

 

while (1) // check battery voltage here at TMR2 interrupt
{
AD_value=ADC_GetConversionValue(ADC1);

if (AD_value<=0xE00)

   {  gpio_set_state(GPIO3_PORT, GPIO3_PIN, RESET);     } // turn led on

         

          else gpio_set_state(GPIO3_PORT, GPIO3_PIN, SET);// turn led off
}
}

 

Void RCC_Configuration(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_HSICmd(ENABLE); /* Enable the HSI */
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET); /* Wait until HSI oscillator is ready */
}

 

void GPIO_Configuration(void) // setup pin 12 for ADC
{

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}


void ADC_Configuration(void) // setup ADC to t start on TMR2 interrupt
{
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
/* ADC Common Init */
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE; // 1 Channel
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // Conversions Triggered
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_TempSensorVrefintCmd(ENABLE); // reference enable

ADC_RegularChannelConfig(ADC1, ADC_Channel_18, 1, ADC_SampleTime_16Cycles); // PORT B12 is ADC_IN18
ADC_ITConfig(ADC1 , ADC_IT_EOC , ENABLE);

ADC_Cmd(ADC1, ENABLE);

}

 

 

void TIM2_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 500;
TIM_TimeBaseStructure.TIM_Prescaler = 5000;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); /* TIM2 TRGO selection */
TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T2_TRGO
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);/* TIM IT enable */
TIM_Cmd(TIM2, ENABLE);/* TIM2 enable counter */
}

 

void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

 

void ADC1_IRQHandler(void)
{
if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET)
AD_value=ADC_GetConversionValue(ADC1); // Store ADC value
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); // Clear ADC1 EOC pending interrupt bit 

}
void TIM2_IRQHandler()

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

GPIO_ToggleBits(GPIO0_PORT,GPIO0_PIN); // toggle led to show timer running
AD_value=ADC_GetConversionValue(ADC1); // store ADC value
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}

}

Outcomes