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

nop_pulse.ino
#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:

Oszilloskop-Spur zeigt 187.5ns-Impuls, erzeugt durch Arduino Uno mit einem NOP-Befehl

Ebenso, wenn wir zwei NOPs verwenden:

nop_pulse_2.ino
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:

Oszilloskop-Spur zeigt 250ns-Impuls, erzeugt durch Arduino Uno mit zwei NOP-Befehlen

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

Oszilloskop-Spur zeigt 312.5ns-Impuls, erzeugt durch Arduino Uno mit drei NOP-Befehlen

Vollständiges Beispiel

full_example.ino
#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);
}

Check out similar posts by category: Arduino, Electronics