volatile關鍵字,是用於表明變量代碼無法被優化!
比如:
int a = 0;
a = 1;
a = 2;
a = 3;
經過編譯器代碼優化後:int a = 0;
a = 3;
省去重複工作,debug下不會作任何優化,但這樣的代碼效率一般只用在調試下,release模式下會對齊進行優化,在GCC的編譯器下會直接對這段代碼優化,GCC下沒有debug和release模式!這樣的情況對,應用層來說可以解決重複代碼,有效提高編碼以及運行效率!
但是對於嵌入式開發就不一樣了,每個電平對於不同的情況
GPIO_C |= (1<<5);
sleep(0xFFFFF);
GPIO_C |= (0<<5);
這段代碼是讓LED燈閃爍,但是倘若編譯器爲其進行了優化就會變成:sleep(0xFFFFF);
GPIO_C |= (0<<5);
看不到閃爍的情況了,因爲編譯器覺得GPIO_C最終的結果會是 |= 0<<5,所以直接索性優化掉上面重複代碼!這樣的話GPIO_C端口就接受不到高電平,也就無法驅動LED燈亮起,所以這樣做是不對的!
所以我們要用到volatile關鍵,告訴編譯器,無論如何都不要嘗試對被volatile關鍵字聲明的變量進行優化!
這樣的話編譯器就不會對齊變量進行優化!
volatile int a = 0;
即使是宏的情況下,編譯器也一樣會對其進行優化,所以我們要在宏定義裏也加上volatile:#define volatile *(unsigned int*) 0x410000
這裏在說說宏定義:#define BLOCK_2_GPIOB_CRL volatile *(unsigned int*)BLOCK_2_APB2_GPIO_B+0x0 //BLOCK_2_APB2_GPIO_B = 0X100
在運用時BLOCK_2_GPIOB_CRL |= 1
編譯時會出現錯誤:表達式必須爲左值
其實原因很簡單,下面給大家看一下預編譯文件:
volatile *(unsigned int*)0x100+0x0 |= 1
後面的0x100+0x0就錯了!編譯器看成先對0x100地址取值,然後在加上0x0|=1
這樣顯然是錯誤的,0x0是立即數,也稱爲右值,無法賦值的!立即數就如c語言中的常量
所以我們要加上括號增加運算符優先級
volatile *(unsigned int*)(BLOCK_2_APB2_GPIO_B+0x0)
預編譯後:volatile *(unsigned int*)(0x100+0x0) |= 1
這樣編譯器就會把0x100+0x0的地址裏的值|=1也就是將0x100這塊內存地址的值賦予新的值,新值是0x100裏的值|=1
因爲上面用了賦值運算符=