說明
volatile
是一個被稱為變量qualifier
的關鍵字,它通常用在變量的數據類型之前,以修改編譯器和後續程序對變量的處理方式。
聲明變量volatile
是編譯器的指令。編譯器是將您的 C/C++ 代碼翻譯成機器代碼的軟件,機器代碼是 Arduino 中 Atmega 芯片的真實指令。
具體來說,它指示編譯器從 RAM 而不是從存儲寄存器加載變量,存儲寄存器是存儲和操作程序變量的臨時內存位置。在某些情況下,存儲在寄存器中的變量的值可能不準確。
隻要變量的值可以通過超出其出現的代碼部分的控製範圍(例如並發執行的線程)來更改,則應聲明變量volatile
。在 Arduino 中,唯一可能發生這種情況的地方是與中斷相關的代碼段,稱為中斷服務程序。
int 或長揮發物
如果 volatile
變量大於一個字節(例如 16 位 int 或 32 位長),則微控製器無法一步讀取它,因為它是 8 位微控製器。這意味著當您的主代碼部分(例如您的循環)讀取變量的前 8 位時,中斷可能已經更改了後 8 位。這將為變量生成隨機值。
補救:
在讀取變量時,需要禁用中斷,因此它們在讀取時不會弄亂這些位。做這件事有很多種方法:
-
LANGUAGE 無中斷
-
使用ATOMIC_BLOCK 宏。原子操作是單個 MCU 操作 - 可能的最小單元。
示例代碼
volatile
修飾符確保對 state
變量的更改在 loop()
中立即可見。如果沒有volatile
修飾符,state
變量可能會在進入函數時加載到寄存器中,並且在函數結束之前不會再更新。
// Flashes the LED for 1 s if the input has changed
// in the previous second.
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 <util/atomic.h> // this library includes the ATOMIC_BLOCK macro.
volatile int input_from_interrupt;
// Somewhere in the code, e.g. inside loop()
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
// code with interrupts blocked (consecutive atomic operations will not get interrupted)
int result = input_from_interrupt;
}
相關用法
- Arduino void用法及代碼示例
- Arduino long用法及代碼示例
- Arduino Arduino_EMBRYO_2 - setLengthXY()用法及代碼示例
- Arduino ~用法及代碼示例
- Arduino ArduinoBLE - bleDevice.advertisedServiceUuidCount()用法及代碼示例
- Arduino const用法及代碼示例
- Arduino Ethernet - server.begin()用法及代碼示例
- Arduino ArduinoBLE - BLEService()用法及代碼示例
- Arduino digitalWrite()用法及代碼示例
- Arduino ArduinoBLE - bleCharacteristic.subscribe()用法及代碼示例
- Arduino Servo - attach()用法及代碼示例
- Arduino write()用法及代碼示例
- Arduino Arduino_LSM9DS1 - readGyroscope()用法及代碼示例
- Arduino ArduinoSound - FFTAnalyzer.input()用法及代碼示例
- Arduino MKRGSM - gprs.attachGPRS()用法及代碼示例
- Arduino WiFiNINA - WiFi.config()用法及代碼示例
- Arduino MKRGSM - sms.read()用法及代碼示例
- Arduino MKRNB - getCurrentCarrier()用法及代碼示例
- Arduino Scheduler - Scheduler.startLoop()用法及代碼示例
- Arduino Arduino_LSM9DS1 - magneticFieldAvailable()用法及代碼示例
- Arduino MKRWAN - available()用法及代碼示例
- Arduino ArduinoBLE - BLE.poll()用法及代碼示例
- Arduino ArduinoBLE - bleCharacteristic.hasDescriptor()用法及代碼示例
- Arduino Ethernet - EthernetUDP.parsePacket()用法及代碼示例
- Arduino WiFi101 - WiFi.subnetMask()用法及代碼示例
注:本文由純淨天空篩選整理自arduino.cc大神的英文原創作品 volatile。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。