volatile的本意是一般有两种说法--1.“暂态的”;2.“易变的”。 这两种说法都有可行。但是究竟volatile是什么意思,现举例说明(以Keil-c与a51为例 例子来自Keil FQA),看完例子后你应该明白volatile的意思了,如果还不明白,那只好 再看一遍了。 例1. void main (void) { volatile int i; int j; i = 1; //1 不被优化 i=1 i = 2; //2 不被优化 i=1 i = 3; //3 不被优化 i=1 j = 1; //4 被优化 j = 2; //5 被优化 j = 3; //6 j = 3 } --------------------------------------------------------------------- 例2. 函数: void func (void) { unsigned char xdata xdata_junk; unsigned char xdata *p = &xdata_junk; unsigned char t1, t2; t1 = *p; t2 = *p; } 编译的汇编为: 0000 7E00 R MOV R6,#HIGH xdata_junk 0002 7F00 R MOV R7,#LOW xdata_junk ;---- Variable 'p' assigned to Register 'R6/R7' ---- 0004 8F82 MOV DPL,R7 0006 8E83 MOV DPH,R6 ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 注意 0008 E0 MOVX A,@DPTR 0009 F500 R MOV t1,A 000B F500 R MOV t2,A ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 000D 22 RET 将函数变为: void func (void) { volatile unsigned char xdata xdata_junk; volatile unsigned char xdata *p = &xdata_junk; unsigned char t1, t2; t1 = *p; t2 = *p; } 编译的汇编为: 0000 7E00 R MOV R6,#HIGH xdata_junk 0002 7F00 R MOV R7,#LOW xdata_junk ;---- Variable 'p' assigned to Register 'R6/R7' ---- 0004 8F82 MOV DPL,R7 0006 8E83 MOV DPH,R6 ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 0008 E0 MOVX A,@DPTR 0009 F500 R MOV t1,A a处 000B E0 MOVX A,@DPTR 000C F500 R MOV t2,A ;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 000E 22 RET 比较结果可以看出来,未用volatile关键字时,只从*p所指的地址读一次 如在a处*p的内容有变化,则t2得到的则不是真正*p的内容。 --------------------------------------------------------------------- 例3 volatile unsigned char bdata var; // use volatile keyword here sbit var_0 = var^0; sbit var_1 = var^1; unsigned char xdata values[10]; void main (void) { unsigned char i; for (i = 0; i < sizeof (values); i++) { var = values[i]; if (var_0) { var_1 = 1; //a处 values[i] = var; // without the volatile keyword, the compiler // assumes that 'var' is unmodified and does not // reload the variable content. } } } 在此例中,如在a处到下一句运行前,var如有变化则不会,如var=0xff; 则在 values[i] = var;得到的还是values[i] = 1; --------------------------------------------------------------------- 应用举例: 例1. #define DBYTE ((unsigned char volatile data *) 0) 说明:此处不用volatile关键字,可能得不到真正的内容。 --------------------------------------------------------------------- 例2. #define TEST_VOLATILE_C //*************************************************************** // verwendete Include Dateien //*************************************************************** #if __C51__ < 600 #error: !! Keil 版本不正确 #endif //*************************************************************** // 函数 void v_IntOccured(void) //*************************************************************** extern void v_IntOccured(void); //*************************************************************** // 变量定义 //*************************************************************** char xdata cvalue1; //全局xdata char volatile xdata cvalue2; //全局xdata //*************************************************************** // 函数: v_ExtInt0() // 版本: // 参数: // 用途:cvalue1++,cvalue2++ //*************************************************************** void v_ExtInt0(void) interrupt 0 { cvalue1++; cvalue2++; } //*************************************************************** // 函数: main() // 版本: // 参数: // 用途:测试volatile //*************************************************************** void main() { char cErg; //1. 使cErg=cvalue1; cErg = cvalue1; //2. 在此处仿真时手动产生中断INT0,使cvalue1++; cvalue2++ if (cvalue1 != cErg) v_IntOccured(); //3. 使cErg=cvalue2; cErg = cvalue2; //4. 在此处仿真时手动产生中断INT0,使cvalue1++; cvalue2++ if (cvalue2 != cErg) v_IntOccured(); //5. 完成 while (1); } //*************************************************************** // 函数: v_IntOccured() // 版本: // 参数: // 用途: 死循环 //*************************************************************** void v_IntOccured() { while(1); } 仿真可以看出,在没有用volatile时,即2处,程序不能进入v_IntOccured(); 但在4处可以进入v_IntOccured();

评论