# ATMega328P timer interrupt simulation problem

Status
Not open for further replies.

#### Cantafford

##### Member
Hello,

I'm trying to use the timer0 interrupt of ATMega328P MCU to flash an LED every second.
I have used this calculator and concluded that for a 20Mhz crystal 195 timer ticks will give an interrupt at every 0.01 seconds. So I'm using a variable counter up to 100 to flash the LED when it reaches 100(so one second has elapsed).

I have written this code:
Code:
/*
* AVRGCC1.c
*
* Created: 10/19/2016 5:20:34 PM
*  Author: Paul
*/

#include <avr/io.h>
#include <avr/interrupt.h> // quick way to include interrupts in the code

int extraTime = 0;

int main(void)
{
DDRB = 0x01; // setting the LED as an output

TCCR0A = (1 << WGM01); // Set CTC Bit
OCR0A = 195; // number of ticks we need for our specific time
TIMSK0 = (1 << OCIE0A);

TCCR0B = (1 << CS02) | (1 << CS00); // use 1024 prescaler
sei(); // setting the interrupt???(setting the i bit)

while(1)
{
}
}

ISR(TIMER0_COMPA_vect) // the interrupt service routine(see list of vectors for all interrupt sources!!!!
{
extraTime++;

if(extraTime > 100)
{
PORTB ^= (1<<PORTB0); // toggle LED
extraTime = 0;
}
}
Now when I simulate this my led flashes every 30 seconds instead of every second. Now I can increase it's frequency by just reducing the number of ticks but that's just playing around with it no precision at all.

The code above is from a tutorial and in that tutorial the LED flashes exactly at one second interval. The code is basically identical. However I'm simulating the application in proteus whereas that guy who made that tutorial is implementing it in hardware. Can this be an issue from Proteus simulator? I've been told in the past that it has some problems when it comes to modelling the oscillators(or something like that). And if is indeed a proteus problem any way I can fix it so the oscillator and the program are synced? Thank you for reading.

Here is the proteus schematic:

#### Jon Wilder

##### Active Member
You're using the timer 0 compare interrupt vector. You need to use the overflow vector instead.
Code:
ISR(TIMER0_OVF_vect){
// interrupt  code
}
Further, timer 0 free running and prescaled at 1:1024 overflows once every 13 milliseconds. Loading your counter with 77 will get you 1 second.

Last edited:

#### Jon Wilder

##### Active Member
Code:
#include <avr/io.h>
#include <avr/interrupt.h>

uint8_t extratime = 0;

int main(void){
TCCR0A = 0b00000000;    // timer 0 normal mode
TCCR0B = 0b00000101;    // 1:1024 prescale
TIMSK0 = 0b00000001;    // timer 0 overflow interrupt enable
SREG |= 0b10000000;    // global interrupt enable
PORTB &= ~_BV(PB0);    // PB0 low
DDRB |= _BV(PB0);    // PB0 output for LED
while(1);     // loop forever
return 0;
}

ISR(TIMER0_OVF_vect){    // timer 0 overflow interrupt vector
if(extratime > 77){    // if post scaler > 77
PORTB ^= _BV(PB0);    // toggle state of PB0
extratime = 0;    // reset post scaler
}
}
This init code will set timer 0 up with 1:1024 prescale. Load your post scale counter with 77 to get a 1 second timer. Then use ISR(TIMER0_OVF_vect) for your interrupt handler.

Last edited:

#### Cantafford

##### Member
Ok thanks guys will try and let you know.

#### Cantafford

##### Member
Another question. I just started with AVR MCU's and I'm trying to calibrate my internal oscillator as 8Mhz. Now I have to program the fuse low bite. For example I tried clearing the "prescale oscillator by 1/8" factory setting by doing: CKDIV8 = 1(unprogrammed). But if I try to run that in code I get an error the compiler won't recognize CKDIV8.
My question is kinda silly but I can't figure this out. What is the fuse name? For example when you are working with PICs you have registers names(e.g: OSCCON) that you can access for example OSCCON |= (1<<7) to set bit 7. But in my case how can I set the bits of the fuses? What is the fuses name? I'm not sure if you understand what I mean (yeah I'm guessing it sounds stupid).

Also I know there are fuses calculators online I just want to know how can I do this manually. Then I'll use those. Thanks.

#### Cantafford

##### Member
I calibrated my microcontroller via AVR Studio's fuse programming to use a 8Mhz oscillator internal oscillator(at least I think I did).
I have selected no prescale option.
So my timer0 beiing a 8 bit timer should give an overflow every 0.0318 ms. So I used a counter variable and when that reaches 31 I toggle an LED. So by my calculations the LED should flash every second but instead it flashes 4 times per 0.9 seconds....am I missing something?

This is the code:
Code:
/*
* AVRGCC1.c
*
* Created: 10/19/2016 5:20:34 PM
*  Author: Paul
*/

#define F_CPU 8000000L

#include <avr/io.h>
#include <avr/interrupt.h> // quick way to include interrupts in the code
#include <avr/delay.h>

int extraTime = 0;

int main(void)
{
DDRB = 0x01; // setting the LED as an output

TIMSK0 |= (1<<0); // enable TIMER0 overflow
TCCR0B |= (1<<0); // set bit0(clk/1 no prescaling)
TCNT0=0x00; // timer0=0

sei(); // enable interrupts

while(1)
{

}
}

ISR(TIMER0_OVF_vect)
{
extraTime++;

if(extraTime == 31)
{
PORTB ^= (1 << PORTB0); // toggle LED
extraTime = 0; // and reset counter
}

}

#### Ian Rogers

##### User Extraordinaire
Forum Supporter
When I do Proteus simulations, I always include a Nop(); which generates a single nop.. This tells me the speed when I single step... I then know the frequency of the oscillator block is correct!!

#### Jon Wilder

##### Active Member
Show your calculations cause that's way off.

I gave you example code above. Why are you against using a prescaler?

Timer math is really simple. AVRs run at one instruction per clock cycle so long as the DIV8 fuse is unprogrammed and the system clock prescaler is 1:1. The timer math then becomes -

Time = ((1/Fosc) x Timer Prescale Value) x 256

So at 8MHz and a 1:1 timer prescale, you overflow every 320uS. With a 1:1024 prescale, you overflow every 32.768mS. So you need a 1:1024 prescale to get a 1 second timer with a counter value of 31.

Last edited:

#### Cantafford

##### Member
Show your calculations cause that's way off.

I gave you example code above. Why are you against using a prescaler?

Timer math is really simple. AVRs run at one instruction per clock cycle so long as the DIV8 fuse is unprogrammed and the system clock prescaler is 1:1. The timer math then becomes -

Time = ((1/Fosc) x Timer Prescale Value) x 256

So at 8MHz and a 1:1 timer prescale, you overflow every 320uS. With a 1:1024 prescale, you overflow every 32.768mS. So you need a 1:1024 prescale to get a 1 second timer with a counter value of 31.
Ok then I'm guess I'm doing something wrong in my calculations. This is how I calculated everything:

8 Mhz oscillator => Fosc = 1/8Mhz = 0.000125 ms per instruction
Tmr0 overflow = 256 * Fosc = 0,032 ms

S0: Tmr0 overflow * 32 = 1 second.
Isn't this correct?

Also I have not anything against using a prescaler I just don't think I need it in my case and I want to see where my mistake was. Thanks for answering.

#### Jon Wilder

##### Active Member

8MHz = 8,000,000Hz

1 / 8MHz = 125nS (nanoseconds), or 0.125uS (microseconds) or 0.000000125 seconds

125nS x 256 = 32uS (microseconds)

With no prescaler you'd overflow every 32uS...nowhere near your calculations.

Now let's plug in the 1:1024 prescaler -

125nS x 1024 = 128uS

128uS x 256 = 32.768mS or 0.032768 seconds

32.768mS x 31 = 1.016 seconds

#### Cantafford

##### Member

8MHz = 8,000,000Hz

1 / 8MHz = 125nS (nanoseconds), or 0.125uS (microseconds) or 0.000000125 seconds

125nS x 256 = 32uS (microseconds)

With no prescaler you'd overflow every 32uS...nowhere near your calculations.

Now let's plug in the 1:1024 prescaler -

125nS x 1024 = 128uS

128uS x 256 = 32.768mS or 0.032768 seconds

32.768mS x 31 = 1.016 seconds
Ok thanks man. Gotta be more carefull with the math

Status
Not open for further replies.