volatile

        volatile a不稳定的;易变的;结合程序,我更愿意理解为“不优化的”。volatile类型的变量,程序每次读取时都会到原地址读取变量值,而不是直接获取寄存器内缓存的变量副本。这一点,我还没有深切的感受。但是“不优化”概念在Os优化等级下,我有些理解。

        GCC编译器存在四个优化等级(optimization level),从低到高依次为O0(不优化)、O1(默认优化等级)、O2、Os、O3。以嵌入式开发为例,在main.c中声明变量 int temp=0,在主循环中判断 temp是否等于255,在不同优化等级下程序执行会存在不同的结果。

全局头文件 #includes.h文件

//(4)声明全局变量。命名规范见注2。
//【不动】宏定义全局变量前缀G_VAR_PREFIX。实现原理见注3。
#ifdef GLOBLE_VAR              //GLOBLE_VAR在main.c文件中有宏定义
  #define G_VAR_PREFIX         //前缀G_VAR_PREFIX定义为空
#else                          //GLOBLE_VAR在非main.c文件中无定义
  #define G_VAR_PREFIX extern  //前缀G_VAR_PREFIX定义为"extern"
#endif
//(在此增加全局变量)
//(系统保留)
G_VAR_PREFIX vuint16_t gcRecvLen;
G_VAR_PREFIX vuint16_t gcRecvDCLen;
G_VAR_PREFIX vuint8_t  gcReccrc32[4];
G_VAR_PREFIX vuint8_t  gcRecvBuf[MCU_SECTORSIZE];
//(用户增加)

G_VAR_PREFIX vuint8_t  temp;

中断处理程序源文件isr.c文件

//======================================================================
//程序名称:UART_User_Handler
//触发条件:UART_User串口收到一个字节触发
//备    注:进入本程序后,可使用uart_get_re_int函数可再进行中断标志判断
//          (1-有UART接收中断,0-没有UART接收中断)
//======================================================================
void UART_User_Handler(void)
{
     //(1)变量声明
    uint8_t flag,ch;
    DISABLE_INTERRUPTS;      //关总中断            防止其他中断程序影响串口接收中断程序
    //(2)未触发串口接收中断,退出
    if(!uart_get_re_int(UART_User)) goto UART_User_Handler_EXIT;
    //(3)收到一个字节,读出该字节数据
    ch = uart_re1(UART_User,&flag);        //调用接收一个字节的函数
    if(!flag) goto UART_User_Handler_EXIT; //实际未收到数据,退出
  //(4)接收到数据后,对temp变量重新赋值

    if(ch=='P'||ch=='p')
    {
           temp=255;

    }

     //(5)【公共退出区】
       UART_User_Handler_EXIT:
       ENABLE_INTERRUPTS;//开总中断

 }

main.c 文件  

//(1.1)声明main函数使用的局部变量

    uint32_t mMainLoopCount;  //主循环次数变量
    uint8_t  mFlag;           //灯的状态标志
    uint32_t mLightCount;     //灯的状态切换次数

//(1.2)【不变】关总中断
    DISABLE_INTERRUPTS;

//(1.3)给主函数使用的局部变量赋初值
    temp=0;    //主循环次数变量

    mMainLoopCount=0;    //主循环次数变量
    mFlag='A';           //灯的状态标志
    mLightCount=0;       //灯的闪烁次数

//(1.4)给全局变量赋初值
       temp=0;

//(1.5)用户外设模块初始化
    gpio_init(LIGHT_BLUE,GPIO_OUTPUT,LIGHT_ON);    //初始化蓝灯
    uart_init(UART_User,115200);
//(1.6)使能模块中断
    uart_enable_re_int(UART_User);

(2)======主循环部分(开头)========================================
    for(;;)   //for(;;)(开头)
    {
//(2.1)主循环次数变量+1
        mMainLoopCount++;
//(2.2)未达到主循环次数设定值,继续循环
        if (mMainLoopCount<=12888999)  continue;
//(2.3)达到主循环次数设定值,执行下列语句,进行灯的亮暗处理
//(2.3.1)清除循环次数变量
        mMainLoopCount=0; 

//O0优化等级下,temp为非volatile变量,该语句编译后不变,仍为  while(temp==!255)

//Os优化等级下,temp为非volatile变量,该语句编译后改变,被优化为  while(true)

//Os优化等级下,temp为volatile变量,该语句编译后不变,仍为  while(temp==!255)
        while(temp==!255)
        {
                    
        }

        
        
//(2.3.2)如灯状态标志mFlag为'L',灯的闪烁次数+1并显示,改变灯状态及标志
        if (mFlag=='L')                    //判断灯的状态标志
        {
            mLightCount++;  
            printf("灯的闪烁次数 mLightCount = %d\n",mLightCount);
            mFlag='A';                       //灯的状态标志
            gpio_set(LIGHT_BLUE,LIGHT_ON);  //灯“亮”
            printf(" LIGHT_BLUE:ON--\n");   //串口输出灯的状态
        }
//(2.3.3)如灯状态标志mFlag为'A',改变灯状态及标志
        else
        {
            mFlag='L';                       //灯的状态标志
            gpio_set(LIGHT_BLUE,LIGHT_OFF); //灯“暗”
            printf(" LIGHT_BLUE:OFF--\n");  //串口输出灯的状态
        }
    }  //for(;;)结尾
//(2)======主循环部分(结尾)========================================
}   //main函数(结尾)

        O0优化等级下,temp是否volatile变量,while(temp==!255)语句编译后不变,仍为  while(temp==!255),程序运行结果不变。

        Os优化等级下,temp为非volatile变量while(temp==!255)语句编译后改变,被优化为  while(true),小灯亮暗永远不会改变。

        Os优化等级下,temp为volatile变量,该语句编译后不变,仍为  while(temp==!255),UART_User串口接收到数据后,temp变量被赋值为255,程序从while循环跳出,小灯亮暗状态不断切换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值