Short pulse generation with Arduino Uno Part 3: Varying pulse width using "nop" instruction

In our previous post Short pulse generation with Arduino Uno Part 2: GPIO register access pulse width we detailed how to generate extremely short 125ns pulses using direct GPIO port register writes.

Given the code from our previous post, the pulse length can be varied with fairly high resolution using a NOPinstruction.

NOP instruction is a machine instruction for the microcontroller which does nothing (but doing nothing via NOP takes exactly one CPU cycle, which in effect leads to a very small delay). The delay is equivalent to one clock cycle - at 16 MHz master clock frequency such as for the Arduino Uno, this equates to 1/16MHz = 62.5ns.

We can integrate NOP into our code from the previous post by using the _NOP() macro which is available in #include <avr/cpufunc.h>

#define PORT11 PORTB
#define PIN11 3
#define PIN11_MASK (1 << PIN11)


void loop() {
    cli(); // Disable interrupts
    PORT11 |= PIN11_MASK; // Turn pin 11 on
    _NOP();
    PORT11 &= ~PIN11_MASK; // Turn pin 11 off
    sei(); // Enable interrupts again

    delay(10); // Wait 10ms
}

The original code without NOPs generated pulsed 125ns in width.

With one NOP instruction, it generates pulses 125ns + 62.5ns = 187.5ns in width:

Similarly, if we use two NOPs:

cli(); // Disable interrupts
PORT11 |= PIN11_MASK; // Turn pin 11 on
_NOP();
_NOP();
PORT11 &= ~PIN11_MASK; // Turn pin 11 off
sei(); // Enable interrupts again

we will obtain pulses  125ns + 2*62.5ns = 250ns in width:

With three NOPs we’ll se pulses 125ns + 3*62.5ns = 312.5ns in width

Full example

#include <Arduino.h>
#include <avr/io.h>

#define PORT11 PORTB
#define PIN11 3
#define PIN11_MASK (1 << PIN11)

void setup() {
    pinMode(11, OUTPUT);
}

void loop() {
    cli();
    PORT11 |= PIN11_MASK;
    _NOP();
    _NOP();
    _NOP();
    PORT11 &= ~PIN11_MASK;
    sei();

    delay(10);
}