Pin output toggling error.......signal tearing?

If you turn off interrupts you won't be getting any serial reads (or writes) and the timer functions will return incorrect time.

You are better off generating pulses in hardware.

DirtyBits:
would that affect any other Interrupt routine ...

If you disable interrupts then you disable all interrupts.

Nick's suggestion to use a hardware timer to do the fixed frequency output did not rely on disabling interrupts and seems like a much better approach to take.

cli (); is needed to Disable Interrupt flag.

It doesn't disable interrupt flags: it disable interrupt execution. The flags will be set as they otherwise would be, except that they don't trigger isrs anymore.

Before you disable it, think hard if you have to. If your pulses needs to be generated absolutely as you had written, without interruption, you then have no choice but to disable interrupts.

dhenry:
Before you disable it, think hard if you have to. If your pulses needs to be generated absolutely as you had written, without interruption, you then have no choice but to disable interrupts.

Even then there will be glitches at the end of loops, as I pointed out above. He has "no choice" but to use the hardware timers if he wants glitch-free pulses.

What frequency are you after? 1 MHz? This sketch does that, nice and simple:

const byte LED = 3;  // Timer 2 "B" output: OC2B

const long frequency = 1000000;  // 1 MHz

void setup() 
 {
  pinMode (LED, OUTPUT);

  TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); // fast PWM, clear OC2A on compare
  TCCR2B = _BV (WGM22) | _BV (CS20);         // fast PWM, no prescaler
  OCR2A =  (F_CPU / frequency) - 1;          // zero relative  
  OCR2B = ((OCR2A + 1) / 2) - 1;             // 50% duty cycle
  }  // end of setup

void loop()
  {
  // do other stuff here
  }

Glitch-free output:

Plus you are free to do whatever you want in the main loop, interrupts, serial send/receive, whatever.

If you have to protect the transmission, you may want to think what it is that you are trying to protect: you can protect the pulse width (high or low, or high and low); you can protect every 8 pulses; or you can protect all 24 pulses.

That will determine where / when you disable / re-enable the interrupts.

The key is to minimize the duration of disabling them.

dhenry:
That will determine where / when you disable / re-enable the interrupts.

I disagree. Nick Gammon has already demonstrated a far better approach which does not require or rely on disabling interrupts. A general rule I try to follow is to use interrupts only where necessary, and when using interrupts disable them only where necessary. In this case, neither the use of interrupt nor the disabling of interrupts are necessary.

Nick;

That's a very impressive application of a timer. I have a few questions:

  1. Can the OCR2A&B registers be changed 'on the fly' to other values without having to do anything else?
  2. What would the max and min frequencies be on a standard 16 Mhz board with retaining @ 50% duty cycle?
  3. What would be the commands to stop the timer at any time, and to restart it at any time.

Sure seems like this could be made into a nice simple general purpose function clock generator?

Lefty

Can the OCR2A&B registers be changed 'on the fly' to other values without having to do anything else?

Yes they can. They would take effect next cycle. If you are going smaller it might be best to stop the clock in case it overshoots the new limit, and then start it again.

What would the max and min frequencies be on a standard 16 Mhz board with retaining @ 50% duty cycle?

With no prescaler: 62.5 KHz to 4 MHz.
With a prescaler of 8: 7813 Hz to 1 MHz.
And so on. (With no prescaler it should go to 8 MHz but I got artifacts doing that).

What would be the commands to stop the timer at any time, and to restart it at any time.

You would turn off the clock source, eg.

Off:

  TCCR2B = 0;         // clock stopped

On:

  TCCR2B = _BV (WGM22) | _BV (CS20);         // fast PWM, no prescaler

If you just want a 50% duty cycle some of the other modes (like CTC) might be better. This one uses both "sides" of the timer. I did a bit of copy/paste on that one.

Thanks Nick!
Just woke up :wink:

I need pulses of min 250nS or max 400ns. I need to learn how to use your approach though.

dhenry:

cli (); is needed to Disable Interrupt flag.

It doesn't disable interrupt flags: it disable interrupt execution. The flags will be set as they otherwise would be, except that they don't trigger isrs anymore.

Before you disable it, think hard if you have to. If your pulses needs to be generated absolutely as you had written, without interruption, you then have no choice but to disable interrupts.

yes it disables all Interrupts...

dhenry:
If you have to protect the transmission, you may want to think what it is that you are trying to protect: you can protect the pulse width (high or low, or high and low); you can protect every 8 pulses; or you can protect all 24 pulses.

That will determine where / when you disable / re-enable the interrupts.

The key is to minimize the duration of disabling them.

...Meaning put it in "for" loop where u need it?

for(int j=0;j <5; j++)
     { cli(); 
       ....
       .....

DirtyBits:
yes it disables all Interrupts...

It disables entry into an interrupt service routine. In other words, the servicing of interrupts. However as dhenry said, if an interrupt "event" occurs (eg. a timer overflows) then that will be remembered and processed (in interrupt priority order) next time interrupts are enabled.

DirtyBits:
...Meaning put it in "for" loop where u need it?

In your case, I wouldn't be disabling interrupts. You are trying to solve a problem the wrong way by doing that.

retrolefty:
Nick;

That's a very impressive application of a timer. I have a few questions:

  1. Can the OCR2A&B registers be changed 'on the fly' to other values without having to do anything else?
  2. What would the max and min frequencies be on a standard 16 Mhz board with retaining @ 50% duty cycle?
  3. What would be the commands to stop the timer at any time, and to restart it at any time.

Sure seems like this could be made into a nice simple general purpose function clock generator?

Lefty

Lefy,
Absolutely this is what I was thinking , these Timer/Counter are great piece of kits that can be used in many more ways!
Also thanks Nick for answering the questions.

Nick,
These Timer/ Counters are great piece of kits but not much focus or references are available.
Why don't you make a guide specific to atmega328 & 32u4 for Arduino users about Timers/Counters??

P.S. would like to help you out in terms of preparing Graphics & illustrations.

PeterH:

dhenry:
That will determine where / when you disable / re-enable the interrupts.

A general rule I try to follow is to use interrupts only where necessary, and when using interrupts disable them only where necessary.

By default interrupts are Enable in Arduino, isn't it? Thats why I was getting errors. Also whenever one use Serial.Read/Write function or Delay() interrupts are Enabled, isn't it??

DirtyBits:
Nick,
These Timer/ Counters are great piece of kits but not much focus or references are available.
Why don't you make a guide specific to atmega328 & 32u4 for Arduino users about Timers/Counters??

I have quite a bit of detail here:

DirtyBits:
By default interrupts are Enable in Arduino, isn't it? Thats why I was getting errors. Also whenever one use Serial.Read/Write function or Delay() interrupts are Enabled, isn't it??

Yes interrupts are enabled by default. PeterH was saying, I think, that adding your own interrupt handlers should only be done if necessary.

However the default (enabled) interrupts are used for millis(), micros(), delay(). Also they are used for serial reading and writing.

[quote]..Meaning put it in "for" loop where u need it?[/quote]

It depends.

The following protects the width of '1':

[code]
  cli();
  clk_set();
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();
  sei();
  clk_clr();
  ...

or you can expand to protect the period of a transition:

  cli();
  clk_set();
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();
  //sei();
  clk_clr();
  NOP();
  NOP();
  NOP();
  NOP();
  NOP();
  sei();

Or to protect all 24 transmission:
cli();
for (i=0; i<24; i++) {
clk_set();
NOP();...
clk_clr();
NOP();...
}
sei();
[/code]

...

All depends on what you are trying to do.