当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Arduino volatile用法及代码示例


[变量范围和限定符]

说明

volatile 是一个被称为变量qualifier 的关键字,它通常用在变量的数据类型之前,以修改编译器和后续程序对变量的处理方式。

声明变量volatile 是编译器的指令。编译器是将您的 C/C++ 代码翻译成机器代码的软件,机器代码是 Arduino 中 Atmega 芯片的真实指令。

具体来说,它指示编译器从 RAM 而不是从存储寄存器加载变量,存储寄存器是存储和操作程序变量的临时内存位置。在某些情况下,存储在寄存器中的变量的值可能不准确。

只要变量的值可以通过超出其出现的代码部分的控制范围(例如并发执行的线程)来更改,则应声明变量volatile。在 Arduino 中,唯一可能发生这种情况的地方是与中断相关的代码段,称为中断服务程序。

int 或长挥发物

如果 volatile 变量大于一个字节(例如 16 位 int 或 32 位长),则微控制器无法一步读取它,因为它是 8 位微控制器。这意味着当您的主代码部分(例如您的循环)读取变量的前 8 位时,中断可能已经更改了后 8 位。这将为变量生成随机值。

补救:

在读取变量时,需要禁用中断,因此它们在读取时不会弄乱这些位。做这件事有很多种方法:

  1. LANGUAGE 无中断

  2. 使用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.cc大神的英文原创作品 volatile。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。