Menu
CoddyTech

Compartir con volatile

Parte de la sección Temporización sin delay del Journey de Arduino de Coddy. Lección 14 de 18.

Una ISR debería hacer una sola cosa rápida, así que normalmente establece una variable para que el resto del sketch la lea. Una variable que ambos usan debe declararse volatile:

volatile bool started = false;

void onPress() {
  started = true;
}

Para ahorrar tiempo, el compilador (el programa que convierte tu C++ en las instrucciones del chip) puede guardar una copia de una variable dentro del procesador en lugar de leer la memoria. No sabe que una interrupción puede cambiar la variable, así que el sketch podría usar la copia antigua para siempre. volatile hace que lea la variable de nuevo cada vez.

Este sketch espera en setup() con un bucle while: while (condition) { } repite las instrucciones entre llaves mientras la condición sea verdadera, aquí !started. Como en la sección Inputs, ! significa «no»: el bucle se repite mientras started sea falso. Sin volatile, podría esperar para siempre, incluso después de presionar el botón.

challenge icon

Desafío

Fácil

Este sketch debe esperar hasta que se presione el botón y después hacer parpadear el LED. Ahora mismo espera para siempre. Corrígelo:

  • en onPress(), establece started en true
  • declara started como volatile

Presiona Run, presiona el botón y después Check. Pruébalo una vez sin volatile para ver cómo la placa se queda atascada.

Pruébalo tú mismo

const int ledPin = 13;
const int buttonPin = 2;

bool started = false;   // establecido por la interrupción, leído por el sketch

unsigned long previousMillis = 0;
int ledState = LOW;

void onPress() {
  // establece started en true aquí
}

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);

  // espera aquí hasta que se pulse el botón
  while (!started) {
  }
}

void loop() {
  // parpadea cada 250 ms
  unsigned long now = millis();
  if (now - previousMillis >= 250) {
    previousMillis = now;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Temporización sin delay

Practica por tu cuenta: Playground de Arduino