cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F0 Analog Window Watchdog (AWD) firing all the time

Benedikt Rank
Associate II
Posted on June 21, 2018 at 18:31

I try to use the Analog Window Watchdog of a STM32F030F4. For starting I wanted to keep it as simple as possible therefore I started with a single channel conversion in continous mode. The window when an interrupt should be triggered is from 3.0V to 3.3V. The ADC is working as expected and holds the correct values, but the AWD ISR is getting triggered all the time, it seems to be a ISR loop. I can't understand why cause the levels are in the correct order and threshold values are also correct. After clearing the interrupt flag and leaving the ISR the programm jumps imediately back into the ISR, grrr!!! This happens even when I connect GND to the Input Pin (AN0 --> Channel0), I can read zero in the ADC result inside the ISR, but why is getting the ISR fired because 0V is not between the analog window specified???

Very appreshiate every help on this!!!!!!

uint8_t ISR_Bit = 0;

int main(void)

{

  /*!< At this stage the microcontroller clock setting is already configured,

       this is done through SystemInit() function which is called from startup

       file (startup_stm32f0xx.s) before to branch to application main.

       To reconfigure the default setting of SystemInit() function, refer to

       system_stm32f0xx.c file

     */

  /* GPIOC Periph clock enable */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

  GPIO_DeInit(GPIOA);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure PC8 and PC9 in output pushpull mode*/

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* To achieve GPIO toggling maximum frequency, the following  sequence is mandatory.

     You can monitor PC8 and PC9 on the scope to measure the output signal.

     If you need to fine tune this frequency, you can add more GPIO set/reset

     cycles to minimize more the infinite loop timing.

     This code needs to be compiled with high speed optimization option.  */

  uint32_t ADC1ConvertedValue = 0, ADC1ConvertedVoltage= 0;

  uint32_t voltage;

  /* Configure ADC1 Channel 11 */

  ADC_Config();

  while (1)

  {

        /* Compute the voltage */

        ADC1ConvertedVoltage = (ADC1ConvertedValue *3300U);

        ADC1ConvertedVoltage >>= 12;

        /*

        ADC_StartOfConversion(ADC1);

        while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

        //ADC1ConvertedValue = ADC_GetConversionValue(ADC1); //Read ADC value

        //ADC_ClearFlag(ADC1, ADC_FLAG_EOC); //Clear EOC flag

        /* will contain the temperature in degrees Celsius

        voltage = (3300 * ADC1ConvertedValue );

        voltage >>= 12;  // 1751 is the factory stored setting for 30°C

        */

        if(ISR_Bit == 1)

        {

          GPIO_SetBits(GPIOA, GPIO_Pin_3);

        }

        else

        {

          GPIO_ResetBits(GPIOA, GPIO_Pin_3);

        }

  }

}

void ADC1_COMP_IRQHandler(void)

{

    uint16_t Result = 0;

    if(ADC_GetITStatus(ADC1, ADC_IT_AWD) != RESET)

    {

        /* Clear ADC1 AWD pending interrupt bit */

        ADC_ClearITPendingBit(ADC1, ADC_IT_AWD);

        Result = ADC_GetConversionValue(ADC1); //Read ADC value

        ISR_Bit =  0x01;

    }

}
4 REPLIES 4
Benedikt Rank
Associate II
Posted on June 21, 2018 at 18:37

Sorry, here the ADC_Config:

void ADC_Config(void)

{

  ADC_InitTypeDef     ADC_InitStructure;

  /* ADC1 Periph clock enable */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  /* ADCs DeInit */

  ADC_DeInit(ADC1);

  /* Initialize ADC structure */

  ADC_StructInit(&ADC_InitStructure);

  /* Configure the ADC1 in continuous mode with a resolution equal to 12 bits*/

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;

  ADC_Init(ADC1, &ADC_InitStructure);

  ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_239_5Cycles);

  ADC_GetCalibrationFactor(ADC1);

 //ADC_WaitModeCmd(ADC1, ENABLE);

  /* Analog Watchdog configuration functions ************************************/

  ADC_AnalogWatchdogThresholdsConfig(ADC1, WindowVoltHi, WindowVoltLo);

  /* Enable the ADC1 single channel  */

  ADC_AnalogWatchdogSingleChannelCmd(ADC1, ENABLE);

  ADC_OverrunModeCmd(ADC1, ENABLE);

  /* Enable the ADC1 analog watchdog */

  ADC_AnalogWatchdogCmd(ADC1,ENABLE);

 /* Select a single ADC1 channel */

  ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_0);

  /* Enable AWD interrupt */

  ADC_ClearFlag(ADC1, ADC_IT_AWD);

  ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);

  /* Configure and enable ADC1 interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = ADC1_COMP_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

  ADC_DMACmd(ADC1, DISABLE);

  /* Enable the ADC1 Calibration */

  ADC_GetCalibrationFactor(ADC1);

  /* Enable the ADC peripheral */

  ADC_Cmd(ADC1, ENABLE);

  /* Wait the ADRDY flag */

  while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADRDY));

  /* ADC1 regular Software Start Conv */

  ADC_StartOfConversion(ADC1);

}
stm322399
Senior
Posted on June 21, 2018 at 20:32

Could it be that AWD is triggering when conversion is *outside* the window, while you expect the opposite ?

RM says:

'The AWD analog watchdog status bit is set if the analog voltage converted by the ADC is

below a lower threshold or above a higher threshold'
Posted on June 21, 2018 at 21:59

Hi Gonzales,

thanks for your post, I saw that phrase in the RM too. I have applied voltages to PA0 between GND and 3.3V. The result is always the

same --> Breakpoint inside ISR is reached. The result I read inside ISR is always correct e.g. 1V applied is approx. 1200.

The thresold for my window is from 3722 to 4095 wich should be betwenn 3.0V..3.3V.

I tried to rescue the status flags with a variables to see the status befor it ends up at the breakpoint and it looks

also fine. I confirmed that the AWD flag was set, I was able to clear it, and after doing a further single step from the breakpoint (still inside the ISR) i 

observed that the AWD flag was set again. Somehow the flag gets fired all the time.... Running out of ideas,

regards

Posted on June 21, 2018 at 23:00

Yeahh I found it!

The problem was here:

  ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_0);

The channel ♯ define has only to be used for ADC, there are special deinitions for the AWD, with that line it worked:

ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_AnalogWatchdog_Channel_0);

AWD stats counting at '0' whereas the ADC channels start at '1'