C语言中的volatile
volatile的定义:
Indicates that a variable can be changed by a background routine.
Keyword volatile is an extreme opposite of const.It
indicates that a variable may be changed in a way which is absolutely unpredictable by analysing the normal program flow (for example, a variable which may be changed by an interrupt handler). This keyword uses the following syntax:
翻译为表示一个变量也许会被后台程序改变,关键字 volatile 是与 const 绝对对立的。它指示一个变量也许会被某种方式修改,这种方式按照正常程序流程分析是无法预知的(例如,一个变量也许会被一个中断服务程序所修改)。
变量如果加上volatile,就会从内存中重新装载内容,而不是从寄存器中拷贝内容。volatile 的作用 是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
volatile主要由一下几种应用场合:
1). 并行设备的硬件寄存器(如:状态寄存器)
#define GPC1CON *((volatile unsigned int*)0xE0200080)
#define GPC1DAT *((volatile unsigned int*)0xE0200084)
#define GPC1PUD *((volatile unsigned int*)0xE0200088)
...........
typedef const int16_t sc16; /*!< Read Only */
typedef const int8_t sc8; /*!< Read Only */
typedef __IO int16_t vs16;
typedef __IO int8_t vs8;
typedef __I int16_t vsc16; /*!< Read Only */
typedef __I int8_t vsc8; /*!< Read Only */
typedef uint16_t u16;
typedef uint8_t u8;
typedef const uint16_t uc16; /*!< Read Only */
typedef const uint8_t uc8; /*!< Read Only */
typedef __IO uint16_t vu16;
typedef __IO uint8_t vu8;
typedef __I uint16_t vuc16; /*!< Read Only */
typedef __I uint8_t vuc8; /*!< Read Only *
#define __I volatile const /*!< defines 'read only' permissions */
#endif
#define __O volatile /*!< defines 'write only' permissions */
#define __IO volatile /*!< defines 'read / write' permissions */
一个参数既可以是const还可以是volatile吗?
可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。软件不能改变,并不意味着我硬件不能改变你的值,这就是单片机中的应用。
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
/* main.c */ int flag=0; int main(void) { if(flag==1) {do somethings} if(flag==2) {do somethings} return 0; } /* interrupt*/ void NVIC_Handler(void) { flag=1; }
在这种情况下,编译器可能会对其做优化,虽然中断服务函数改变了flag的值,但是编译器并没有在变量内存中去读取,而是在寄存器中读取了flag之前的缓存数据。在中断函数中的交互变量,一定要加上volatile关键字修饰,这样每次读取flag的值都是在其内存地址中读取的,确保是我们想要的数据。
3). 多线程应用中被几个任务共享的变量
原因其实和上面中断一样,要共享标志,又不想让编译器优化了这一点,需要加上该修饰词。
简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错