- Библиотеки
- Операторы
- Sketch
- Управляющие операторы
- Синтаксис
- Арифметические операторы
- Операторы сравнения
- Логические операторы
- Указатели доступа
- Битовые операторы
- Составные операторы
- Данные
- Типы данных
- Преобразование типов данных
- Область видимости переменных и квалификаторы
- volatile
- Утилиты
- Функции
- Цифровой ввод/вывод
- Аналоговый вход/выход
- Расширенный ввод/вывод
- Время
- Математические функции
- Тригонометрические функции
- Символы
- Случайные числа
- Биты и байты
- Внешние Прерывания
- Прерывания
- Функции передачи данных
- Функции
volatile
Описание
volatile - это ключевое слово, известное как квалификатор переменной, оно обычно используется перед типом переменной, чтобы изменить способ, которым компилятор и последующая программа обрабатывают переменную.
Объявление переменной volatile - это директива для компилятора. Компилятор - это программное обеспечение, которое переводит ваш код C / C++ в машинный код, который является набором команд для Atmega в Arduino.
В частности, он указывает компилятору загружать переменную из ОЗУ, а не из регистра хранения, который представляет собой временную ячейку памяти, в которой хранятся программные переменные и которыми ими управляют. При определенных условиях значение переменной, хранящейся в регистрах, может быть неточным.
Переменная должна быть объявлена как volatile всякий раз, когда ее значение может быть изменено чем-либо, находящимся вне участка кода, в котором она появляется, например, одновременно выполняющимся потоком. В Arduino единственное место, где это может произойти, - это участки кода, связанные с прерываниями, которые называются процедурами обработки прерываний.
int или long volatiles
Если измененная переменная больше байта (например, 16-битное int или 32-битное), то микроконтроллер не может прочитать ее за один шаг, потому что это 8-битный микроконтроллер. Это означает, что пока ваш основной участок кода (например, ваш цикл) считывает первые 8 бит переменной, прерывание может уже изменить вторые 8 бит. Это приведет к случайным значениям переменной.
Лекарство:
Пока переменная читается, прерывания необходимо отключить, чтобы они не могли вмешиваться в биты во время чтения. Есть несколько способов сделать это:
1. noInterrupts() - запрет прерываний
2. используйте макрос ATOMIC_BLOCK. Атомарные операции - это отдельные операции MCU - наименьшая возможная единица.
Пример
Модификатор volatile гарантирует, что состояние изменения переменной сразу же будут видны в loop(). Без модификатора volatile состояние переменной может быть загружено в регистр при входе в функцию и больше не будет обновляться до завершения функции.
// переключаем светодиод, когда вызывается прерывание.
// изменением состояния входного пина.
volatile byte changed = 0;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), toggle, CHANGE);
}
void loop() {
if (changed == 1) {
// toggle() has been called from interrupts!
// Reset changed to 0
changed = 0;
// Blink LED for 200 ms
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
}
}
void toggle() {
changed = 1;
}
Чтобы получить доступ к переменной, размер которой превышает 8-битную шину данных микроконтроллера, используйте макрос ATOMIC_BLOCK. Макрос гарантирует, что переменная читается в атомарной операции, то есть ее содержимое не может быть изменено во время чтения.
#include // эта библиотека включает макрос ATOMIC_BLOCK.
volatile int input_from_interrupt;
// Где-то в коде, например внутри loop()
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
// code with прерывания заблокированы
int result = input_from_interrupt;
}