Общий доступ с volatile
Часть раздела Отсчёт времени без delay путешествия по Arduino на Coddy. Урок 14 из 18.
ISR должна выполнять одно быстрое действие, поэтому обычно она задаёт переменную, которую затем считывает остальная часть скетча. Переменная, используемая обеими частями, должна быть объявлена как volatile:
volatile bool started = false;
void onPress() {
started = true;
}Чтобы сэкономить время, компилятор (программа, которая преобразует ваш код C++ в инструкции для микросхемы) может хранить копию переменной внутри процессора, а не считывать её из памяти. Он не знает, что прерывание может изменить переменную, поэтому скетч может использовать старую копию бесконечно. volatile заставляет его каждый раз считывать актуальное значение переменной.
Этот скетч ожидает в setup() с помощью цикла while: while (condition) { } повторяет инструкции в фигурных скобках, пока условие истинно; здесь это !started. Как и в разделе «Входы», ! означает «не»: цикл повторяется, пока started имеет значение false. Без volatile ожидание может продолжаться вечно, даже после нажатия.
Задание
ЛегкоЭтот скетч должен ждать нажатия кнопки, а затем мигать светодиодом. Сейчас он ждёт бесконечно. Исправь это:
- в
onPress()присвойstartedзначениеtrue - объяви
startedкакvolatile
Нажми Run, нажми кнопку, а затем Check. Попробуй один раз без volatile, чтобы увидеть, как плата зависнет.
Попробуйте сами
const int ledPin = 13;
const int buttonPin = 2;
bool started = false; // устанавливается обработчиком прерывания, считывается скетчем
unsigned long previousMillis = 0;
int ledState = LOW;
void onPress() {
// здесь присвойте started значение true
}
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), onPress, FALLING);
// ждите здесь, пока не будет нажата кнопка
while (!started) {
}
}
void loop() {
// мигайте каждые 250 ms
unsigned long now = millis();
if (now - previousMillis >= 250) {
previousMillis = now;
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Отсчёт времени без delay
1millis()
Часы на millis()Время в unsigned longМигание без задержкиДва светодиода, две скоростиМигание и переключение кнопкойСвет по таймеру4Точное измерение времени
Измерение с помощью micros()Когда millis() переполняетсяСекундомер с кнопкой3Прерывания
Нажатие, которое пропускает циклFALLING, RISING и CHANGEОбщий доступ с volatileПодсчёт нажатий с помощью прерыванияПотренируйтесь самостоятельно: Песочница Arduino