Kurzimpuls-Erzeugung mit Arduino Uno Teil 3: Variierende Impulsbreite mit "nop"-Befehl
In unserem vorherigen Beitrag Kurzimpuls-Erzeugung mit Arduino Uno Teil 2: GPIO-Register-Zugriff Impulsbreite haben wir detailliert beschrieben, wie man extrem kurze 125ns-Impulse mit direkten GPIO-Port-Register-Schreibvorgängen erzeugt.
Mit dem Code aus unserem vorherigen Beitrag kann die Impulslänge mit einer NOP-Befehl mit recht hoher Auflösung variiert werden.
Ein NOP-Befehl ist ein Maschinenbefehl für den Mikrocontroller, der nichts tut (aber nichts tun via NOP dauert exakt einen CPU-Zyklus, was effektiv zu einer sehr kleinen Verzögerung führt). Die Verzögerung entspricht einem Taktzyklus - bei 16 MHz Master-Taktfrequenz wie beim Arduino Uno entspricht dies 1/16MHz = 62.5ns.
Wir können NOP in unseren Code aus dem vorherigen Beitrag integrieren, indem wir das _NOP()-Makro verwenden, das in #include <avr/cpufunc.h> verfügbar ist
#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
}Der ursprüngliche Code ohne NOPs erzeugte Impulse von 125ns Breite.
Mit einem NOP-Befehl erzeugt er Impulse von 125ns + 62.5ns = 187.5ns Breite:

Ebenso, wenn wir zwei NOPs verwenden:
cli(); // Disable interrupts
PORT11 |= PIN11_MASK; // Turn pin 11 on
_NOP();
_NOP();
PORT11 &= ~PIN11_MASK; // Turn pin 11 off
sei(); // Enable interrupts again
erhalten wir Impulse von 125ns + 2*62.5ns = 250ns Breite:

Mit drei NOPs sehen wir Impulse von 125ns + 3*62.5ns = 312.5ns Breite

Vollständiges Beispiel
#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);
}