Updating ICR1 in ATMEGA168 on the fly

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

Hi - I need to update ICR1 on the fly in my code. I have seen the warnings in the ATMEGA168 datasheet regarding this. That doesn't change the fact that I still need to do it, however!

I am using fast PWM mode, WGM1[3:0] = 1110. Thus ICR1 is my top. I cannot use OCR1A as my top as it is being used to generate a PWM signal (if I ever rev this board, I will move the PWM signal to OCR1B, but for now I'm stuck with OCR1A).

My timer is running with no divider and with a fixed value in OCR1A. I will never try to put a value less than or equal to OCR1A in ICR1.

My question is this - what's the best (and fastest) way to update ICR1?

I'm thinking something like this:

TIFR1 &= ~(1<<TOV1); //clear TOV1
while (~(TIFR1 & (1<<TOV1))) ; //wait for TCNT1 to hit ICR1
ICR1a = foo; //update ICR1

Anybody see any problems with this?

Thanks!

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

OK - so that doesn't seem to work. I think my code is locking up in the while loop. I realized that I'm clearing TOV1 wrong, so the code, in theory, should look like this:

TIFR1 |= (1<<TOV1); //clear TOV1
while (~(TIFR1 & (1<<TOV1))) ; //wait for TCNT1 to hit ICR1
ICR1 = foo; //Output is too high, increase off time

But that is still locking up as well. Any ideas?

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

Could you update ICR1 in the overflow interrupt ?
That should be safe ?

Mike Adams
ADI Development, Inc.
http://www.adidev.com

... When it has to actually work.

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

dr.mike wrote:
Could you update ICR1 in the overflow interrupt ?
That should be safe ?

I don't have an overflow interrupt and I'm worried that it would interfere with a different interrupt.

This method should work great... except that it seems the PWM unit never sets TOV1. I just verified that my code hangs at the while loop.

Could TOV1 perhaps be active low? The datasheet doesn't seem to say that anywhere. But it's the only explanation I can come up with. Or maybe timer1 interrupts have to be enabled for TOV1 to toggle? Because I have all timer1 interrupts disabled...

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

Quote:
OK - so that doesn't seem to work. I think my code is locking up in the while loop. I realized that I'm clearing TOV1 wrong, so the code, in theory, should look like this:

TIFR1 |= (1<<TOV1); //clear TOV1
while (~(TIFR1 & (1<<TOV1))) ; //wait for TCNT1 to hit ICR1
ICR1 = foo; //Output is too high, increase off time

But that is still locking up as well. Any ideas?

Use a boolean not, rather than bitwise not in your while statement:

  while (!(TIFR1 & (1<<TOV1)));

Better still, use loop_until_bit_is_set.

Also, to clear TOV1, you should do:

  TIFR1 = (1<<TOV1);

otherwise, you'll clear other pending interrupts.

- S

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

mnehpets wrote:
Quote:
OK - so that doesn't seem to work. I think my code is locking up in the while loop. I realized that I'm clearing TOV1 wrong, so the code, in theory, should look like this:

TIFR1 |= (1<<TOV1); //clear TOV1
while (~(TIFR1 & (1<<TOV1))) ; //wait for TCNT1 to hit ICR1
ICR1 = foo; //Output is too high, increase off time

But that is still locking up as well. Any ideas?

Use a boolean not, rather than bitwise not in your while statement:

  while (!(TIFR1 & (1<<TOV1)));

Better still, use loop_until_bit_is_set.

Also, to clear TOV1, you should do:

  TIFR1 = (1<<TOV1);

otherwise, you'll clear other pending interrupts.

- S


Thanks - that was super helpful and it worked!

The bitwise/boolean thing is a function of me not getting enough sleep. I can be pretty dopey at times!!

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

Quote:

I don't have an overflow interrupt and I'm worried that it would interfere with a different interrupt.


So, instead of spending a couple microseconds to do a quick ISR, you will lock your AVR app to one spot for up to an entire timer period? (I'm confused about how one interrupt "interferes" with another, given that many of my apps have a handful or more interrupt vectors enabled and the interrupts continually firing.)

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.