volatile

[Variablenscope und Bezeichner]

Beschreibung

volatile ist ein Variablenkennzeichner. Dieser wird normalerweise vor dem Datentyp der Variable angegeben. Der Compiler behandelt je nach Kennzeichner dann die Variable auf andere Art.

Eine volatile- Variable ist eine Direktive für den Compiler. Der Compiler ist eine Software, die deinen C/C++-Code in Maschinencode übersetzt, der dann die "richtigen" Anweisungen für den Arduino enthält.

Im Detail zeigt volatile dem Compiler, dass er die Variable aus dem RAM und nicht aus dem Speicherregister laden soll. Unter bestimmten Bedingungen können die Variablen in den Registern ungenau sein.

Eine Variable sollte als volatile deklariert werden, wenn sie von irgendwo anders geändert werden kann außer in dem Codeteil, in dem sie auftaucht. Beispiele dafür sind Threads, die parallel ausgeführt werden. Im Arduino kann das nur bei Interrupts vorkommen, in sogennanten Interrupt Service Routinen.

int oder long volatile Variablen

Wenn die Variable größer als Byte ist (also z.B. ein 16-Bit-Integer oder ein 32-Bit-Long), kann der Mikrocontroller sie nicht in einem Durchgang lesen, da es ein 8-Bit-Mikrocontroller ist. Das bedeutet, das während das Hauptprogramm die ersten 8 Bit der Variable liest, kann der Interrupt bereits die zweiten 8 Bit geändert haben. Das kann zufällig und unvorhersehbare Ergebnisse liefern.

Gegenmaßnahme:

Während die Variable gelesen wird, müssen Interrupts deaktiviert werden, sodass diese die Bits nicht verändern können während sie gelesen werden.

Es gibt mehrere Möglichkeiten, das zu tun:

  1. SPRACHE noInterrupts

  2. Das ATOMIC_BLOCK-Makro. Atomare Operationen sind einzelne MCU-Operationen-Die kleinste mögliche Einheit.

Beispielcode

Die LED wird angeschaltet, wenn der Interruptpin den Status ändert.

// Initialisiere den Pin der LED auf Pin 13
int pin = 13;
// Intitialisiere den Status als volatile auf LOW
volatile int state = LOW;

void setup() {
  // Deklariere den Pin als Outputpin
  pinMode(pin, OUTPUT);
  // Setze einen Interrupt auf Pin 0, wenn
  attachInterrupt(digitalPinToInterrupt(2), blink, CHANGE);
}

void loop() {
  // Schreibe den Status auf den Pin zurück
  digitalWrite(pin, state);
}

void blink() {
  // Invertiere den Status, dass die LED blinkt
  state = !state;
}
#include <util/atomic.h> // Diese Bibliothek fügt das ATOMIC_BLOCK-Makro ein.
volatile int input_from_interrupt;

ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
  // Code mit geblockten Interrupts hier (Mehrere atomare Operationen hintereinander werden nicht durch Interrupts unterbrochen)
  int result = input_from_interrupt;
}

Siehe auch

  • Sprache const

  • Sprache scope

  • Sprache static