在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            STM32 _I _0 _IO volatile const

            作者: 時(shí)間:2016-12-03 來(lái)源:網(wǎng)絡(luò) 收藏
            __I、 __O 、__IO是什么意思?
            這是ST庫(kù)里面的宏定義,定義如下:
            #define __I volatile const /*!< defines read only permissions */
            #define __O volatile /*!< defines write only permissions */
            #define __IO volatile /*!< defines read / write permissions */


            顯然,這三個(gè)宏定義都是用來(lái)替換成 volatile 和 const 的,所以我們先要了解 這兩個(gè)關(guān)鍵字的作用:

            volatile
            簡(jiǎn)單的說(shuō),就是不讓編譯器進(jìn)行優(yōu)化,即每次讀取或者修改值的時(shí)候,都必須重新從內(nèi)存或者寄存器中讀取或者修改。

            一般說(shuō)來(lái),volatile用在如下的幾個(gè)地方:
            1、中斷服務(wù)程序中修改的供其它程序檢測(cè)的變量需要加volatile;
            2、多任務(wù)環(huán)境下各任務(wù)間共享的標(biāo)志應(yīng)該加volatile;
            3、存儲(chǔ)器映射的硬件寄存器通常也要加volatile說(shuō)明,因?yàn)槊看螌?duì)它的讀寫(xiě)都可能由不同意義;

            我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到 volatile變量。不懂得volatile的內(nèi)容將會(huì)帶來(lái)災(zāi)難。假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑是否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
            1)一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
            2); 一個(gè)指針可以是volatile 嗎?解釋為什么。
            3); 下面的函數(shù)有什么錯(cuò)誤:
            int square(volatile int *ptr)
            {
            return *ptr * *ptr;
            }

            1)是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖?。它是const因?yàn)槌绦虿粦?yīng)該試圖去修改它。
            2); 是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
            3) 這段代碼有點(diǎn)變態(tài)。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
            int square(volatile int *ptr)
            {
            int a,b;
            a = *ptr;
            b = *ptr;
            return a * b;
            }
            由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
            long square(volatile int *ptr)
            {
            int a;
            a = *ptr;
            return a * a;
            }



            const
            只讀變量,即變量保存在只讀靜態(tài)存儲(chǔ)區(qū)。編譯時(shí),如何嘗試修改只讀變量,則編譯器提示出錯(cuò),就能防止誤修改。
            const與define
            兩者都可以用來(lái)定義常量,但是const定義時(shí),定義了常量的類型,所以更精確一些(其實(shí)const定義的是只讀變量,而不是常量)。#define只是簡(jiǎn)單的文本替換,除了可以定義常量外,還可以用來(lái)定義一些簡(jiǎn)單的函數(shù),有點(diǎn)類似內(nèi)置函數(shù)。const和define定義的常量可以放在頭文件里面。(小注:可以多次聲明,但只能定義一次)

            const與指針
            int me;
            const int * p1=&me; //p1可變,*p1不可變 const 修飾的是 *p1,即*p1不可變
            int * const p2=&me; //p2不可變,*p2可變 const 修飾的是 p2,即p2不可變
            const int *const p3=&me; //p3不可變,*p3也不可變 前一個(gè)const 修飾的是 *p3,后一個(gè)const 修飾的是p3,兩者都不可變


            前面介紹了 volatile 和 const 的用法,不知道大家了解了沒(méi)?了解了后,下面的講解就更加容易了:
            __I :輸入口。既然是輸入,那么寄存器的值就隨時(shí)會(huì)外部修改,那就不能進(jìn)行優(yōu)化,每次都要重新從寄存器中讀取。也不能寫(xiě),即只讀,不然就不是輸入而是輸出了。
            __O :輸出口,也不能進(jìn)行優(yōu)化,不然你連續(xù)兩次輸出相同值,編譯器認(rèn)為沒(méi)改變,就忽略了后面那一次輸出,假如外部在兩次輸出中間修改了值,那就影響輸出
            __IO:輸入輸出口,同上


            為什么加下劃線?

            原因是:避免命名沖突
            一般宏定義都是大寫(xiě),但因?yàn)檫@里的字母比較少,所以再添加下劃線來(lái)區(qū)分。這樣一般都可以避免命名沖突問(wèn)題,因?yàn)楹苌偃诉@樣命名,這樣命名的人肯定知道這些是有什么用的。
            經(jīng)常寫(xiě)大工程時(shí),都會(huì)發(fā)現(xiàn)老是命名沖突,要不是全局變量沖突,要不就是宏定義沖突,所以我們要盡量避免這些問(wèn)題,不然出問(wèn)題了都不知道問(wèn)題在哪里。


            volatile一般用在以下三個(gè)方面:

            1、中斷標(biāo)志位

            2、多線程共享的變量

            3、狀態(tài)寄存器
            來(lái)自ouravr野火M3


            關(guān)鍵詞: STM32_I_0_IOvolatilecons

            評(píng)論


            技術(shù)專區(qū)

            關(guān)閉