Setting OCR1A affects compare interrupt

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

The goal is to generate and output square wave via pin 0 on port C and be able to change the frequency of the signal while running.
I used the 16 bit Timer1 on an ATMega16. The compare interrupt is enabled. The interrupt routine handles toggling the output pin high and low. The frequency is varied by changing the compare value OCR1A.
This works but periodically, it appears that the interrupt is not called for about 8.5ms and then continues. I observed this behavior with a logic analyzer on the output pin.
I have been through the datasheet carefully, but did not find any solution or explanation. Can anyone explain this?
Here is a simple bit of code that exhibits the behavior:

uint16_t step = 0;

void main(void)
{
  uint16_t j = 256;
  
  // Step PC0 to output
  DDRC |= BV(PC0);
  
  // Enable CTC mode and set Prescaler to 1
  TCCR1B |= (1 << CTC1) | (0 << CS12) | (0 << CS11) | (1 << CS10);
  // Enable Timer1 compare interrupt
  TIMSK |= (1 << OCIE1A);
  // Set compare value
  OCR1A = 256;
  
  asm("sei");
  
  while (1)
  {
    delay_ms(2);
    OCR1A = j; 
    
    if (j == 256)
      j = 512;
    else
      j = 256;
  };  
}

#pragma interrupt_handler TIMER1Handler:iv_TIMER1_COMPA
void TIMER1Handler(void)
{
  PORTC ^= BV(PC0);
}

The code simple changes the compare value OCR1A back and forth from 512 to 256 every 2 milliseconds. The interrupt handle toggles the output pin (PC0).

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

It's in the datasheet :)

If the value written to OCR1A is less than the current counter, the counter will have to count all the way up, through 0 and THEN it matches OCR1A

Choose your output-pin a bit wiser: then the timer will do the job all on its own, no further SW-involvement except for writing a new value of course.

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tricia, and Ulyana. You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

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

Your OCR1A changing is not synchronized to the timer. If OCR1A is changed from 512 to 256 while the counter is in between these two values, the counter will make a full round until the next interrupt.

Stefan Ernst

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

Plons wrote:
It's in the datasheet :)

If the value written to OCR1A is less than the current counter, the counter will have to count all the way up, through 0 and THEN it matches OCR1A

Thanks for the info. It makes sense...but I have looked at the datasheet again, and still can't find that information.

Plons wrote:

Choose your output-pin a bit wiser: then the timer will do the job all on its own, no further SW-involvement except for writing a new value of course.

This is a simple example. In my real application, I need to output a much more complex signal such that I cannot use hardware link to OC1A pin...if that is what you were referring to.

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

sternst wrote:
Your OCR1A changing is not synchronized to the timer. If OCR1A is changed from 512 to 256 while the counter is in between these two values, the counter will make a full round until the next interrupt.

Ah...
So what is the best solution to syncronize the changes to OCR1A? Setting TCNT1 to 0 when changing the counter value?

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

oecben wrote:
but I have looked at the datasheet again, and still can't find that information.
It is part of the description of the timer mode you use (CTC).
Datasheet wrote:
If the new value written to OCR1A or ICR1 is lower than the current value of TCNT1, the counter will miss the compare match. The counter will then have to count to its maximum value (0xFFFF) and wrap around starting at 0x0000 before the compare match can occur.

Quote:
So what is the best solution to syncronize the changes to OCR1A?
Depends on what you actually want to do. E.g. updating OCR1A in the interrupt is one good choice.

Stefan Ernst

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

CTC mode has no OCR1A Register buffer. Use fast PWM mode 15 where OCR1A sets TOP.

Data Sheet fast PWM wrote:
The OCR1A Register however, is double buffered. This feature allows the OCR1A I/O location to be written anytime. When the OCR1A I/O location is written the value written will be put into the OCR1A Buffer Register. The OCR1A Compare Register will then be updated with the value in the Buffer Register at the next timer clock cycle the TCNT1 matches TOP. The update is done at the same timer clock cycle as the TCNT1 is cleared and the TOV1 Flag is set.

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

sternst wrote:
It is part of the description of the timer mode you use (CTC).

Sorry...my mistake. I am using an ATMega163 (don't ask) and it's datasheet is pathetic (187 pages compared with 358 for ATMega16). It makes no mention of this CTC behavior. The ATMega16 datasheet does indeed have the section you quoted.

Thanks for your help.

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

Sorry, the ATmega163 is a no longer manufactured "mature" device. There is no fast PWM on the 163 :(.

This application note has migration information to the newer current generation of chips. AVR083: Replacing ATmega163 by ATmega16:
http://www.atmel.com/dyn/resourc...

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

...and then immediately take the next jump to the Mega164. Still pin compatible, less expensive, more toyz.

For "complex" waveforms with short periods, then I'd say to let the timer free-run, and update the OCR value each timie it hits. I'd still use the single pin, and have it toggle on compare match. If the next event is 100 timer ticks in the future, then you simply add 100 to OCR1A.

I started a thread on that "Two timers, three frequencies" https://www.avrfreaks.net/index.p... that does something similar. You might be crippled with the '163 however.

For real fast production of waveforms from table data see Jesper's MiniDDS.
http://www.myplace.nu/avr/minidd...

Beyond that, I guess you need to tell us more about the waveform generation (true waveform like MiniDDS with a DAC, or on/off pulse trains) and the max speeds/minimum pulse width requirements.

Note that with the newer AVRs you also (besides buffered OCR) get more modes that are more "glitch free". That (being free of glitch) may be a good thing for PWM, but a bad thing for AVRFreaks. ;)

Lee

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.