Your waiting loop runs much faster than once per millisecond, and even faster per second. So to get just one "event" per second, you need to detect the change of the second.
void wait_function() {
timer_init();
for (int second = 0; second < 30; ++second) { // 30 second wait
// Wait for the next second
int old_second = read_counter() / 1000;
int new_second;
do {
new_second = read_counter() / 1000;
} while (new_second == old_second);
// A LED blinking at 1 second intervals
PORTB ^= 1 << LED;
}
}
However, you may think about refactoring your timer. You can put the division in the ISR, and then set a flag if a second has past. In your waiting loop you could wait for the flag, reset it, and toggle the LED.
EDIT:
If you have your (pseudo) code like this:
while (!timed_out) {
if (timer % ticks_per_second == 0) {
do_something();
}
}
you will have the following erroneous behavior, presumed that the loop runs 1 million times per second and the timer increments 20000 times per second.
- The timer starts at 1000, for example, and has just incremented.
- The loop runs for 50 times until the timer increments to 1001.
- This happens repeatedly until the timer gets 20000, which will be after (20000 - 1001) * 50 = 949950 loops.
- Now the loop will run for 50 times, while the timer is still at 20000.
- The condition is
true
on each repetition, so do_something()
will be executed 50 times in a row.
- Next, the timer increments to 20001, and the condition becomes
false
.
This is exactly what you observe: If the condition of the if
becomes true
, its statement will be executed repeatedly.
Because the relation between the loop's repetition frequency and the timer's frequency is not the presumed value (but similar) and even depends on the instructions executed, the state of the output is subjectively random. If the XOR instruction is executed an even number, the LED does not change, and if it is executed an odd number, the LED changes.
turn the LED on and off at 5-second intervals
if (read_counter() / 5000 % 2) PINB^=(1<<LED);