Causing a delay while in an interrupt

Hi Guys

I need to be able to cause a small delay while in an interrupt because the IC I am trying to clock cannot detect the 0.1uS wide clock pulse.

I am not sute what the best practice is.

void DataRead()
{
  PORTB |= (1 << In_Load);          // Sets Pin High (1) to Load the Data into the Register
  PORTB &= ~(1 << In_Load);         // Sets Pin Low (0) again

This is my code which toggles the pin High and Low again. Works fine to generate the 0.1uS wide pulse, but it is just too fast for the IC, which requires a 0.8uS wide pulse.

Obviously I cannot use delay() because this is within an ISR.

I could possibly split the PORT code between other code, making it to run the other in between, thus making a wider pulse, but I would rather not.

Is there a way to tell the processor to wait for 10 clock cycles before continuing? I know that the PDP8e's could but this is slightly different.

Whilst I don't recommend doing delays inside an ISR, under a microsecond sounds OK. You could do 13 NOPs which would give you 812.5 ns.

Code for one NOP:

#define NOP asm volatile ("nop\n\t")

Maltelec:
Is there a way to tell the processor to wait for 10 clock cycles before continuing?

You can include inline instructions with Assembler op-codes.
For example "NOP", which means "no operation", that is once clock cycle of doing nothing.

Do one NOP delay:

__asm__("nop\n\t");

Do four NOP delays in a row:

 __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");

On 16 MHz boards, one NOP is a 62.5 ns (nanoseconds) delay.

Newer versions of the IDE have a macro function that lets you generate precise delays in terms of clock cycles. For example:

void setup() 
  {
  pinMode (10, OUTPUT);
  }
void loop() 
  {
  PINB = bit (2);   // toggle D10
  __builtin_avr_delay_cycles (11);
  PINB = bit (2);   // toggle D10
  }

That gives me an on cycle of 812.5 ns (13 cycles). Probably toggling the pin takes 2 cycles.

You could use digitalWrite()... :slight_smile:

Not a macro, but a GCC built-in function.

Which IC is it ? Most if not all chips use the edge not the width.

Mark

You can use delayMicroseconds() in an ISR but you should not delay more than a few microseconds. In your case it appears that 1 microsecond will be more than enough.

oqibidipo:
Not a macro, but a GCC built-in function.
AVR Built-in Functions - Using the GNU Compiler Collection (GCC)

Point taken, I have amended the post. I think they built a macro around that function. I can't find the reference right now, but it probably avoided typing those leading underscore. And did a couple of other things, like checking the number was in range or something.