如何在Arduino中使用易失變數?
就像在 C 和 C++ 中一樣,如果變數可以在中斷例程中修改,則需要使用 volatile 關鍵字限定該變數。
將變數限定為 volatile 時,後臺會發生以下情況:
編譯器會收到指令,將變數載入到 RAM 中,而不是儲存暫存器(程式變數通常儲存/操作的地方)。
這確保了在 **loop()** 函式外部(例如,在中斷服務例程中)對變數的任何更改都會立即反映在 **loop()** 函式中。
如果變數的大小大於一個位元組(**int** 或 **long**),那麼像 Arduino Uno 這樣的 8 位微控制器將每次讀取 8 個位元組的變數。這可能會導致問題(在微控制器讀取前 8 個位元組時,變數的下一個 8 個位元組可能已更改)。這可能會導致一些隨機錯誤。為避免這種情況,您可以使用以下方法之一:
使用 ATOMIC_BLOCK 宏(這會將讀取操作轉換為原子操作,在讀取過程中內容不會更改)。為此,您需要包含 **<util/atomic.h>**,語法如下所示 這裡。
在讀取變數時,使用 **noInterrupts()** 停用中斷。
示例
下面給出了一個包含易失變數的示例:
#include <util/atomic.h>
volatile int flag = 0;
int flagValue = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), interruptFunction, CHANGE);
}
void loop() {
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
// code with interrupts blocked (consecutive atomic operations will
not get interrupted)
flagValue = flag;
}
if (flagValue == 1) {6305298009
flag = 0;
flagValue = 0;
Serial.println("Interrupt encountered!");
}
}
void interruptFunction() {
flag = 1;
}請注意,只有 **flag** 被定義為 volatile,因為它是在中斷中唯一值會改變的變數。使用 **noInterrupts()** 的相同程式碼如下所示:
volatile int flag = 0;
int flagValue = 0;
void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), interruptFunction, CHANGE);
}
void loop() {
noInterrupts();
flagValue = flag;
interrupts();
if (flagValue == 1) {
flag = 0;
flagValue = 0;
Serial.println("Interrupt encountered!");
}
}
void interruptFunction() {
flag = 1;
}
廣告
資料結構
網路
關係資料庫管理系統 (RDBMS)
作業系統
Java
iOS
HTML
CSS
Android
Python
C語言程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP