首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 单片机 >

volatile在程序中的功用!

2013-04-05 
volatile在程序中的作用!!求教volatile在程序中的作用!![解决办法]volatile 实例讲解volatile的本意是一般

volatile在程序中的作用!!
求教volatile在程序中的作用!!
[解决办法]
         volatile 实例讲解

        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();


[解决办法]
简单的说:这个关键字就是告诉编译器,这个变量不能优化。必须每次访问都真实去访问该变量的物理空间。
[解决办法]
单片机有cache的问题,请参考:
http://wenku.baidu.com/view/20f5e079168884868762d6e8.html

热点排行