[Arduino]关于arduino中volatile关键字的使用

Volatile:

Volatile是一个被称为变量限定符的关键字,它通常被用在变量的数据类型之前,用来修改编译器和后续程序处理变量的方式。
声明volatile变量是对编译器的指令。编译器是把你的C/ c++代码翻译成机器码的软件,机器码是Arduino中Atmega芯片的真正指令。
具体来说,它指示编译器从RAM而不是从存储寄存器加载变量,存储寄存器是存储和操作程序变量的临时内存位置。在某些条件下,存储在寄存器中的变量的值可能是不准确的。
当变量的值可能被超出其所在代码段的控制范围的东西(例如并发执行的线程)改变时,就应该将其声明为volatile。在Arduino中,唯一可能发生这种情况的地方是与中断相关的代码部分,称为中断服务例程。

int or long volatiles:
如果volatile变量大于一个字节(例如16位int或32位long),那么微控制器(MCU根据自己的Arduino具体型号确定,这里使用Arduino Mega 2560,它是8位的MCU)不能一步读取它,因为它是8位微控制器。这意味着当你的主代码部分(例如循环)读取变量的前8位时,中断可能已经改变了后8位。这将为变量产生随机值。
解决方案:
当变量被读取时,中断需要被禁用,这样它们就不会在被读取时打乱位。有几种方法可以做到这一点:

LANGUAGE noInterrupts

use the ATOMIC_BLOCK macro.

原子操作是单MCU操作-最小的可能单元

Example Code:
volatile修饰符确保对状态变量的更改在loop()中立即可见。如果没有volatile修饰符,状态变量可以在进入函数时加载到寄存器中,并且在函数结束之前不会再更新。

// 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;
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值