1
\$\begingroup\$

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);
}
\$\endgroup\$
2
  • \$\begingroup\$ What are your fuses set to? \$\endgroup\$ Commented Jan 2, 2014 at 5:46
  • \$\begingroup\$ Are you definite that the 16 MHz clock is actually being used by the microcontroller, rather than the internal oscillator running at 1 MHz for instance? Also, as @IgnacioVazquez-Abrams pointed out, what is the clock source / divider as per the MCU's fuse settings? \$\endgroup\$ Commented Jan 2, 2014 at 6:56

2 Answers 2

1
\$\begingroup\$

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)

\$\endgroup\$
1
\$\begingroup\$

The default clock source of the microcontroller is internal RC set to 8MHz.
The device also comes with the CKDIV8 fuse programmed which divides the clock by 8 and results to 1MHz that seems to match what you describe.

A simple test you can do is remove the crystal and power the circuit, if the mcu works then you are using the internal RC so you need to change the fuses to use the crystal as the clock source. If not then it's probably only related to the clock divider.

Regarding the clock divider please read my reply here

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.