Timer programming

Hi all,
I'm new on Arduino and I'm trying to program TIMER2 for a fast pulse output.
This is the code:

unsigned int n;
byte m;

void setup() 
{
  pinMode(13,OUTPUT);  
  PORTB&=~32;
  m=1;
  cli();  
  TCCR1B= 0x00;
  TCCR0B= 0x00; //stop    
  TCCR2B= 0x00;
  
  TCNT0= 0x00;  
  
  OCR2A= 10;	  //  16 MHz clock - prescaler=1
  OCR2B= 54;
    
  TCCR2A= 0x00;
  
  n=0;

  TIMSK0= 0;	
  TIMSK1= 0;
  TIMSK2= 6;    // timer2 output compare A & B match enabled
  TCCR2B= 1;    // start timer2 - prescaler=1
  
  EIMSK=0;

  sei();
}


ISR(TIMER2_COMPA_vect)
{
    PORTB|=32;      
}

ISR(TIMER2_COMPB_vect)
{
    PORTB&=~32;     
}

void loop() 
{
  while (n==0) {}
  n=0; 
}

the problem is changing OCR2A and OCR2B values I've no variation in pulse width output on pin 13 (PORTB.5) .
I'm sure timer's ISR is call and works because I have a pulse output on pin 13, but the width is costantly about 1.8uS not depending from the value OCR2B-OCR2A.
I need some help ...

What's the role of n and m ?

Why do you use 32 instead of 8?

What values have you tried?

Did you see this?

"The Output Compare unit can be used to generate interrupts at some given time. Using the Output
Compare to generate waveforms in Normal mode is not recommended, since this will
occupy too much of the CPU time."

Why not don't you use a CTC mode?

Sorry, n and m haves no rule, are variables of a previous program .

If I understand well the question, value 32 on PORTB set pin 13. I think it doesn't matter which one is the bit I toggle, pin 13 or another. I know programming timer for fast interrupt, occupy lot of CPU time but if all the CPU job is made by ISR, that is the faster and more precise timing we can obtain and It's what I need. In my real program ISR should update a 16bit DAC, in this code I just set pin 13 for checking the timing on oscilloscope. I haven't tried CTC mode because I don't need really to toggle a bit on a port, I need to update some port and toggle few bits in the interrupt service rountine. But I can't understand why this program doesn't works. I can suppose Arduino compiler puts some extra code on mine but I can't find any confirm to this supposition.

I'm new on Arduino and I'm trying to program TIMER2 for a fast pulse output.

I would propose a slightly different structure to your approach: use a timer overflow to set (or clear) the output pin and use the ch A or B to clear (or set) the output pin.

Something like this:

void tmr2_init(void) {
  //configure the timer
  //enable timer interrupts but not yet global interrupt
}

#define tmr2a_setdc(dc) OCR2A = (dc) //set ch a duty cycle

ISR(TIMER2_COMPA_vect) {
  //clear output pin
}

ISR(TIMER2_OVF_vect) {
  //set output pin
}

void setup(void) {
  //initialize the pins
  tmr2_init(); //reset the timer
  tmr2a_setdc(23); //ch a duty cycle to 23/256%
  interrupts(); //enable global interrupt
}

void loop(void) {
  //do something
  //change the duty cycle if desired
}

You can potentially pass the prescaler to tmr2_init(). With this approach, you can easily build up your library and duplicate it to tmr0/tmr1.

In my real program ISR should update a 16bit DAC

If that's the goal, AVR's adc module can be set up to be triggered automatically and periodically. It is fairly easy to set up. I can post a piece of code there if you want.

dhenry:
If that's the goal, AVR's adc module can be set up to be triggered automatically and periodically. It is fairly easy to set up. I can post a piece of code there if you want.

DAC != ADC...

alebit:
If I understand well the question, value 32 on PORTB set pin 13. I think it doesn't matter which one is the bit I toggle, pin 13 or another. I know programming timer for fast interrupt, occupy lot of CPU time but if all the CPU job is made by ISR, that is the faster and more precise timing we can obtain and It's what I need. In my real program ISR should update a 16bit DAC, in this code I just set pin 13 for checking the timing on oscilloscope. I haven't tried CTC mode because I don't need really to toggle a bit on a port, I need to update some port and toggle few bits in the interrupt service rountine. But I can't understand why this program doesn't works. I can suppose Arduino compiler puts some extra code on mine but I can't find any confirm to this supposition.

What you did with the 32 was set and reset 4 bytes. Not the port.

If you want to set or reset bits in the Arduino faster, this is the way.

//setting
PORTB |= 1 << 5;

//clearing
PORTB &= ~(1 << 5);

PORTB 5 is pin 13 in ARduino.

To toggle a pin:

PORTB ^= 1 << 5;

But how does this relate to a DAC???

What you did with the 32 was set and reset 4 bytes.

32 = 1 << 5.

So his code is setting / clearing a particular pin, and is identical to your code.

But how does this relate to a DAC???

For debugging purposes. He is trying to try to the code so it flips a pin - to be observed by a scope that signals that the timing portion of the code is working. He can then add the DAC portion of the code.

A fairly common way to build up and debug one's code.

dhenry:
For debugging purposes. He is trying to try to the code so it flips a pin - to be observed by a scope that signals that the timing portion of the code is working. He can then add the DAC portion of the code.

A fairly common way to build up and debug one's code.

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?
And, most importantly, if the timing part underestimates the load that driving the DAC will have on the program, then all this is useless. First, test the DAC, see how fast can the Arduino drive it without timings and then worry about triggering the times at a rate the arduino can handle. Since no PWM is really needed, go for the simplest timing arrangement, with an overflow or with an Clear to count and overflow to better adjust the desired frequency.

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?

Not really sure about the "interrupts keeping the processor busy all the time" part. Interrupts are useful precisely because they do not keep the processor busy - they interrupt the processor only when certain conditions are met.

And, most importantly, if the timing part underestimates the load that driving the DAC will have on the program, ...

I do not know how the DAC part is to be implemented. The DAC could be really fast - a parallel DAC for example, or it could be preloaded by the main loop and strobed / activated by the isr. It could be implemented without causing excessive delays in the isr, rendering your question moot.

First, test the DAC, ...

Different ways of skinning the cat. Without knowing all the details, it is impossible to assert if one approach is better than another.

dhenry:

So why the complex timing arrangement with two timed interrupts keeping the processor busy all the time?

Not really sure about the "interrupts keeping the processor busy all the time" part. Interrupts are useful precisely because they do not keep the processor busy - they interrupt the processor only when certain conditions are met.

Interrupts can keep the processor busy. If they fire too frequently and/or take too long, the CPU will have only little time to execute loop() code.

I'm really grateful to everybody for all the comments and the debate, meanwhile, unfortunately, the point of my question is fading away. My trouble is "why this code doesn't works?" I know you could write the code in a different way but this should works and generate a pulse on pin 13 at a frequency of 62.5KHz (16MHz clock/256 - and it do it exactly) but with a variable pulse width related to the value OCR2B-OCR2A, while the output pulse is about 1.8uS wide for any value of OCR2B and OCR2A I've tested.
I can't understand why . I'm going to put the same code on Arduino board using GNU Ccompiler, AVRstudio and ISP to check if I've the same problem. I'll keep you updated.

You lost me here:

n=0;

...

void loop() 
{
  while (n==0) {}
  n=0; 
}

This might help:

Thanks Nick your link is useful for timers programming even if this is not my problem at the moment.
As I say in previous post I've tested the code compiled with WInAVR and put on the same Arduino Uno with ISP .
This is the adapted code

unsigned int n;
char m;

void setup() 
{
  DDRB=255;  
  PORTB&=~32;
  m=1;
  cli();  
  TCCR1B= 0x00;
  TCCR0B= 0x00; //stop    
  TCCR2B= 0x00;
  
  TCNT0= 0x00;  
  
  OCR2A= 20;	  //  
  OCR2B= 40;
    
  TCCR2A= 0x00;
  
  n=0;

  TIMSK0= 0;	
  TIMSK1= 0;
  TIMSK2= 6;    // timer2 output compare A & B match enabled
  TCCR2B= 1;    // start timer2 - prescaler=1 - 16 MHz clock 
  
  EIMSK=0;

  sei();
}


ISR(TIMER2_COMPA_vect)
{
    PORTB|=32;   
}

ISR(TIMER2_COMPB_vect)
{
    PORTB&=~32;     
}

void main() 
{
  setup();
  while (n==0) {}
  n=0; 
}

In this case it works fine and if( OCR2A-OCR2B) > 30 we obtain a pulse width equal to ((OCR2A-OCR2B) * 62.5nS) as it should happens in previous case. The limit of 30 for OCR2A-OCR2B is probably due to the time for ISR call, the storing and retrieving of registers, ect.
What I would like to know is how Arduino waste all that time and, if is possible, where can I find the assembly code of my C source compiled in Arduino environment ? What Arduino is doing in "loop() "?

Glad it helped.

My advice is: don't use ISRs if you want accurate timer output. Use the timer hardware.

How to view assembly

Duane B

rcarduino.blogspot.com

The limit of 30 for OCR2A-OCR2B is probably due to the time for ISR call, the storing and retrieving of registers, ect.

Yes, it is due to interrupt latency: when the 1st interrupt is being serviced (the context saving takes around 20 ticks), global interrupt is disabled. But if the 2nd interrupt arrives before the exeution of the 1st isr is finished, it is not serviced until the 1st interrupt is finished and global interrupt is re-enabled.

gcc-avr, the compiler behind the arduino ide, is actually quite good. You may speed up using more optimization (-O3 for example), or naked isr (no automatic context saving).

Using isr allows you to get very accurate timing. You just need to know its limitations.

I played with it a little in gcc-avr. With naked isr, the lowest I can get between the two isrs is about 10 ticks -> <1us @ 16MIPS.

The risk with naked isrs is that you have to look at the generated assembly and perform context save (push/pop) yourself.

I repeat that to get jitter-free timer output you have to use the hardware timer output. Not an ISR.