Electronic – Prescaled Timers Problem

avrmicrocontrollertimer

I'm using a attiny2313a, and I'm having a lot of trouble figuring out what's going on with the timer. It's very simple, yet it simply refuses to work.

I have a 16Mhz clock.
When I put in a 1024 prescaler, then the TCNT1 clock will increment at the frequency 16Mhz/1024= 0.0156MHz, This means that I get an increment every 64uS.

So, for one second, I should expect 1000000/64 = 15625

This is ok, because TCNT1 is a 16-bit counter.

However, when I set up a testing program, what I get is a very long beep somewhere closer to 15-16 seconds.

When I set the prescaler at 64, then 15624 gives me exactly one second.

In my mind, my crystal is behaving like I would expect a 1Mhz crystal to. Is my thought process wrong, or is there something else that might be wrong?

Here is my testing code, the important parts:

#include <avr/io.h>
#include <avr/interrupt.h>


#define Echo    PINB0
#define Trig    PINB1
#define Buzz    PINB4
#define Led PIND4

int main(void)
{
DDRD = (1<<Led);
PORTD = 1<<Led;

DDRB = 1<<Trig | 1<<Buzz;
DDRB &= ~(1<<Echo);


TCCR1B = (1<< CS10) |  (1<<CS12); // prescaler = 1024

    while(1) {      
        beep();
        wait(1);
    }
}

void wait(int t){
    TCNT1 = 0;
    while(TCNT1 <= 15624*t){

    }
}
void beep(){
    TCNT1 = 0;
    PORTB = 1<<Buzz;
    while(TCNT1 <= 15624){

    }
    PORTB &= ~(1<<Buzz);
}

Best Answer

It looks your MCU is running at 1MHz like alexan_e describes. Check your fuses - select external crystal as a clock source and unset CKDIV8 fuse.

Regarding your code - you are doing it wrong. You should use interrupts to detect timer events. In this particular case - an Output Compare Match interrupt.

You have to set your magic number to OCR1A and set bit OCIE1A in TIMSK register to enable the interrupt. Don't forget to provide timer1 overflow interrupt A handler in your code.

This way your code will not be stuck in closed loop while timer is counting. That's the beauty of using peripherals in MCU - they are trully running in parallel - while the timer is counting, the processor can do other usefull stuff or conserve power sleeping.

Please note, that you either have to reset the timer to 0 yourself in the interrupt handler or set timer to CTC mode (WGM12 bit in TCCR1B)

Related Topic