Timer1 Question

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

I am trying to learn how to use Timer1 on the butterfly in output compare mode. This test code compiles and runs fine on an atmega 8 or 32 but fails with messages shown in the gif below on a 169...why does it fail? it seems not to recognize TIMSK, TIFR. Is there a difference in using Timer1 on the 169???

//timer1-6.c for atmega8

#include 
#include 
#include 
#include 

int main( void)
{
sei(); //enable interrupts
DDRD = 0xFF; //PORTD set as output
TCNT1L = 0;
TCNT1H = 0;
OCR1AH = 0x01; //output compare High and Low bytes
OCR1AL =0x0E; 
TCCR1A = 0x00; //timer counter control register
TCCR1B &= ~(0 <<WGM13); //Clear on compare
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11);
TCCR1B |= (1 << CS10);
TIMSK |= ( 1 << OCIE1A); //Timer1 Output Compare Enable
TIFR |= (1 << OCF1A); //Timer1 Output compare A match flag
while(1);
}

//toggles PORTD as test
SIGNAL(SIG_OUTPUT_COMPARE1A) 
{
PORTD = ~PORTD;
} 

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

The "Bitnames" are taken from the datahsheet , so check the datasheet.

If they are in the DS , then file a "BUG"

/Bingo

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

Thanks Bingo..

I checked the datasheet and they list as TIMSK1, TIFR1
and when I paste that in the code compiles...

So I guess that was the problem...just that little
difference in the names.

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

Hey!

That timer1 code above runs fine in the simulator but when loaded
into an actual atmega169 or 168 the code in

SIGNAL(SIG_OUTPUT_COMPARE1A) 
{ 
PORTD = ~PORTD; 
}

never runs!

Is there something wrong with my code??
If so why does it run in the simulator?

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

How do You make sure it never runs? Have You measured the pins on PORTD with a scope?

Or have You connected some LEDs to PORTD? (This wil not work as PORTD will flicker much to fast for You to see, and depending on how the LEDs react to a 50/50 duty cycle they might not light up at all. To get a distinguashable flicker on a LED You have to come down under 10 Hz or so. Remeber that ordinary television is 25 still frames per second or so but You percieve motion rather than "stop motion").

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

No..I did not measure it with a scope..
Just as you said, LEDs on PORTD.

Maybe I calculated the values wrong and it is
blinking way too fast to notice...I will try some
different values out and also maybe add in a prescale
value. :)

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

I think I have it now :)
I have set up timer1 to hit 10,000x a second
and I have a bit of code that scales this down to
10 hits a second...this code blinks LEDs on PORTD
for a rate of 5/second and that is what they are indeed
blinking at.

Here is the code..please look it over and see if it looks
OK to you. Is there anything missing? Or anything in here
I don't really need for a simple interrupt demo?
In particular..are these lines needed or not?
Do these bits default to 0 even if not explicitly set to 0 ???

TCCR1B &= ~(1 << CS12);
TCCR1B &= ~(1 << CS11);

Here is the complete code

//timer1-12.c for atmega168
//LEDs on PORTD connected to Gnd

#include 
#include 
#include 
#include 

volatile unsigned int tickcount;
 
int main( void)
{
sei(); //enable interrupts
DDRD = 0xFF; //PORTD set as output
PORTD = 0xFF;//turn off LEDs
TCNT1L = 0;
TCNT1H = 0;
OCR1AH = 0x03; //output compare High and Low bytes
OCR1AL = 0x20; //0x0320 gives 10,000/sec at 8mhz
TCCR1A = 0x00; //timer counter control register
TCCR1B &= ~(0 <<WGM13); //Clear on compare
TCCR1B |= (1 << WGM12);
TCCR1B &= ~(1 << CS12); //prescaler to 0 CS12/11/10 (0 0 1) -0
TCCR1B &= ~(1 << CS11); //-0
TCCR1B |= (1 << CS10);  //-1
TIMSK1 |= ( 1 << OCIE1A); //Timer1 Output Compare Enable
TIFR1 |= (1 << OCF1A); //Timer1 Output compare A match flag
while(1);
}

//toggles PORTD as test
SIGNAL(SIG_OUTPUT_COMPARE1A) //this code runs 10,000/sec
{

tickcount++;
if (tickcount == 1000)//this hits every 10th/second
{
tickcount = 0;
PORTD = ~PORTD; //this code runs 10/second for a flash rate of 5/second
}
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Some things which probably aren't affecting your program now, but will get
you into trouble eventually as your program grows:
-------

TCNT1L = 0;
TCNT1H = 0; 

These should be done in the opposite order (H, then L). It probably doesn't
matter in this context, but it makes a big difference in others. WinAVR also
defines a 16-bit TCNT1 (as well as an OCR1A) register; if you use that the
compiler will get the order correct for you.
-------

TCCR1B &= ~(0 <<WGM13); //Clear on compare
TCCR1B |= (1 << WGM12);
TCCR1B &= ~(1 << CS12); //prescaler to 0 CS12/11/10 (0 0 1) -0
TCCR1B &= ~(1 << CS11); //-0
TCCR1B |= (1 << CS10);  //-1 

A TCCR is typically something you'll want to set all at once, rather
than one bit at a time, since the settings are interrelated. I'd say it's
also easier to read:

TCCR1B = (0 << WGM13)|(1 << WGM12)|(0 << CS12)|(0 << CS11)|(1 << CS10); /* WGM1=4, prescale /1 */

----------------------

TIFR1 |= (1 << OCF1A);

Don't use "|=" to clear an interrupt flag, since it may clear flags you don't intend. Use "=":

TIFR1  = (1 << OCF1A);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks mckenny :)
that's just the sort of advice I was looking for...

this works just fine :)

//timer1-13.c for atmega168
//LEDs on PORTD connected to Gnd

#include 
#include 
#include 
#include 

volatile unsigned int tickcount;
 
int main( void)
{
sei(); //enable interrupts
DDRD = 0xFF; //PORTD set as output
PORTD = 0xFF;//turn off LEDs
TCNT1 = 0;
OCR1AH = 0x03; //output compare High and Low bytes
OCR1AL = 0x20; //0x0320 gives 10,000/sec at 8mhz
TCCR1A = 0x00; //timer counter control register
//TCCR1B clear on compare-prescaler set to 0
TCCR1B = (0 << WGM13)|(1 << WGM12)|(0 << CS12)|(0 << CS11)|(1 << CS10);
TIMSK1 |= ( 1 << OCIE1A); //Timer1 Output Compare Enable
TIFR1  = (1 << OCF1A); //Timer1 Output compare A match flag
while(1);
}

//toggles PORTD as test
SIGNAL(SIG_OUTPUT_COMPARE1A) //this code runs 10,000/sec
{
tickcount++;
if (tickcount == 1000)//this hits every 10th/second
  {
    tickcount = 0;
    PORTD = ~PORTD; //this code runs 10/second for a flash rate of 5/second
  }
}