timer0, atmega 328p, 16 MHz

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I use atmega 328p with 16 MHz, i want to make my led blink every second with output compare timer0, but somehow my code wont work?

 

#include <avr/interrupt.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <util/delay.h>

uint8_t counter;

ISR(TIMER0_OVF_vect){
	counter++;
	if(counter > 100){ //1 sec
		PORTB ^= (1 << PINB0);
	}
	counter = 0;
}

void main (void) {
		DDRB = (1 << PORTB);

		TCCR0A = (1 << WGM01);
		OCR0A = 156; //0.01 sec
		TIMSK0 = (1 << OCIE0A);
		sei();
		TCCR0B = (1 << CS02) | (1 << CS00); // prescaler 1024

	while (1) {

	}
}

 

Last Edited: Mon. Nov 25, 2019 - 10:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You’ve enable the output compare interrupt but the isr is for the overflow. Change the isr vector name to output compare. The precise naming escapes me at the monent.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh my bad i hade already changed it to COMPA_vect, but it still doesnt work?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, maybe you want "counter = 0" inside the braces of " if (counter > 100) { ... }"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes small mistake! thx alot

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the timer0 overflow ISR, you don't want to toggle the PINB value: you want to toggle the value that is presently in PORTB0.  That value is what the code wrote into bit0 on the last ISR.

 

In main(), you don't want to use (1<<PORTB).  Instead use the unusual-looking DDRB = (1<<0).  This means bit 0 of DDRB gets set when a logic 1 is shifted zero times inside DDRB, resulting in DDRB being 0b00000001.

 

Your timer0 set-up is not for overflow, but you're using the overflow ISR vector.   The period of the timer is (16000000/1024); 64 microseconds,  15625 counts per second.  Timer0 counts only up to 255, then the overflow ISR happens.  The max interval is 0.016384 seconds [@61 overflows per second].  If you count the previous interrupts up to 30  inside the ISR and then toggle the PORTB0 pin, you should be seeing a 1 Hz signal on that pin.

 

When I see 16MHz clock and Mega328P, I assume that an Arduino UNO or Nano is being used.  Arduino uses Timer0 for the millis() function,  which triggers every 0.001 seconds and increments an internal unsigned long variable.

Last Edited: Mon. Nov 25, 2019 - 10:32 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Incidentally, you probably do not really run at 16000000 mhz, since "m" is "milli"; that would mean 16000 Hertz which is pretty unlikely. Even more unlikely that you run at 16000000 MHz which would be 16000 GHz; do not know ANY MCU that runs that fast. Most likely is 16000000 Hz which is 16.000000 MHz.

 

If you write

 

#define F_CPU 16000000

It will run at 16000000 Hz = 16MHz, in spite of any comments, but you really should get the right comment in there!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Mon. Nov 25, 2019 - 10:31 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:

If you write

 

#define F_CPU 16000000

It will run at 16000000 Hz = 16MHz

No it won't Just putting a #define in code does not change the speed of the CPU!

 

BTW looking at the code as it is now:

	if(counter > 100){ //1 sec
		PORTB ^= (1 << PINB0);
	}

would be more efficient as:

	if(counter > 100){ //1 sec
		PINB = (1 << PINB0);
	}

The 328P, like all modern AVR, has a pin toggle feature if bits in the PIN register are written to.