如何在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