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 NOP
instruction.
A 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);
}