ATMega2560 timer not increasing again after overflow

cmicrocontrollertimer

I want to generate waveform with f = 196 Hz using only normal mode.
Here is the code I use. Whenever the timer overflows TOV1 is set and PIND0 will toggle. TOV1 is cleared after that and I wait for another overflown to happen so PIND0 will toggle again.

I tried my code, with PIND0 connected to the LED. On power up, the LED turned on and off a short time after that but it didn't turn on again. Because it had turned off means that the overflown happened so PIND is toggled but I don't know why it didn't turn on again. I even tried to not clear TOV1 but get the same result as TOV1 is cleared.

#include <avr/io.h>
#define F_CPU 25690112UL
int main(void)
{
    TIFR1 |= (1<<TOV1); // clear timer 1 overflown flag
    DDRD = 0xFF; // set port D as output
    TCCR1B = 0b00000001; // using internal I/O clock with prescaler 1
    while(1){
        while(TIFR1 & (1<<TOV1)){
            PIND ^= (1<<PD0); // toggle bit 0 on port D
            TIFR1 |= (1<<TOV1); // clear TOV1 by adding 1 to TOV1
        }
    }
}

Can anyone see an error in my code?

Best Answer

The PIND ^= (1 << PD0) line is off.

The PIN register holds the actual physical state pins, and would not normally be written. The PORT register sets the state of the pin drivers.

However, as a common read-only register is a waste of I/O address space, Atmel added a neat feature to the pin register: Writing a bit mask to PIN will toggle the corresponding bits in PORT. The line 'PIND ^= mask' is then approximately the same as PORTD XOR PIND XOR mask. Since PIND reads the pins PORTD drives, PIND is usually = PORTD, which results in this being equivalent to 'PORTD = mask'.

Try substituting 'PIND' with 'PORTD', -or- '^=' with just '='