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)