2
votes

I'm waiting some time for a real-world event (e.g. push a button for 3 seconds) on an AVR or STM32 MCU, and I have trouble with code like:

#define PRESS_BUTTON
int waiting = 0;
int t_ms = 0; // time counter
//...

int main(void)
{           
    while(1)
    {           
        waiting = t_ms + 3000; // waiting button 3 sec

        while ((t_ms < waiting) && (!PRESS_BUTTON)) // infinite loop
        {}                  
        printf("out"); // not printed
        waiting = t_ms = 0;
    }    
}

ISR( TIMER0_OVF_vect ) // timer interrupt
{
    t_ms++;
}

But if I add a printf() inside the while loop, it works!

The same thing happens if I use a do...while loop either. What is causing this?

1
The power of volatile keyword. Change to volatile int t_ms = 0; - LPs
In addition to adding volatile, how do you de-bounce the button? This needs to be done in either software or hardware, otherwise the program will always behave poorly. - Lundin
Only once every 5 full moons do I see the volatile properly needed on stackoverflow. Good question. - Dellowar
It could be the missing volatile, but could also be the missing '\n' in the printf that could well use a buffer flush to actually print something. "It works when I add a printf" hints to that. - tofro
Thanks! @Lundin Usually for de-bounce the button I use just a small delay and repeat a survey. - Anddo

1 Answers

3
votes

You need to declare t_ms with volatile

volatile int t_ms =0;

Volatile tells the compiler that the variable may be changed due to external factors, and because of this the compiler will never assume it will stay the same.

In other words, it will force the compiler to check every loop to see if t_ms has changed instead of assuming it will never change.