久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4772|回復: 0
打印 上一主題 下一主題
收起左側

嵌入式的C程序中(*(volatile unsigned long *)的理解

[復制鏈接]
跳轉到指定樓層
樓主
ID:90762 發表于 2018-10-22 13:41 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
嵌入式的C程序中(*(volatile unsigned long *)的理解
  (*(volatile unsigned long *)
  
    對于不同的計算機體系結構,設備可能是端口映射,也可能是內存映射的。如果系統結構支持獨立的IO地址空間,并且是端口映射,就必須使用匯編語言完成實際對設備的控制,因為C語言并沒有提供真正的“端口”的概念。如果是內存映射,那就方便的多了。
       
    Volatile    表示可隨硬件端口變化。
   
   

以 #define    IOPIN (*((volatile unsigned long *) 0xE0028000)) 為例:作為一個宏定義語句,define是定義一個變量或常量的偽指令。首先( volatile unsigned long * )的意思是將后面的那個地址強制轉換成 volatile unsigned long * ,unsigned long    * 是無符號長整形,volatile 是一個類型限定符,如const一樣,當使用volatile限定時,表示這個變量是依賴系統實現的,以為著這個變量會被其他程序或者計算機硬件修改,由于地址依賴于硬件,volatile就表示他的值會依賴于硬件。

   
    volatile 類型是這樣的,其數據確實可能在未知的情況下發生變化。比如,硬件設備的終端更改了它,現在硬件設備往往也有自己的私有內存地址,比如顯存,他們一般是通過映象的方式,反映到一段特定的內存地址當中,這樣,在某些條件下,程序就可以直接訪問這些私有內存了。另外,比如共享的內存地址,多個程序都對它操作的時候。你的程序并不知道,這個內存何時被改變了。如果不加這個voliatile修飾,程序是利用catch當中的數據,那個可能是過時的了,加了 voliatile,就在需要用的時候,程序重新去那個地址去提取,保證是最新的。歸納起來如下:
    1.    volatile變量可變允許除了程序之外的比如硬件來修改他的內容
    2. 訪問該數據任何時候都會直接訪問該地址處內容,即通過cache提高訪問速度的優化被取消

   
   

對于((volatile unsigned long *) 0xE0028000)為隨硬件需要定義的一種地址,前面加上“*”指針,為直接指向該地址,整個定義約定符號IOPIN代替,調用的時候直接對指向的地址寄存器寫內容既可。這實際上就是內存映射機制的方便性了。其中volatile關鍵字是嵌入式系統開發的一個重要特點。上述表達式拆開來分析,首先(volatile    unsigned long *) 0xE0028000的意思是把0xE0028000強制轉換成volatile unsigned long類型的指針,暫記為p,那么就是#define A *p,即A為P指針指向位置的內容了。這里就是通過內存尋址訪問到寄存器A,可以讀/寫操作。

   
   

對于(volatile unsigned char *)0x20我們再分析一下,它是由兩部分組成:
    1)(unsigned char *)0x20,0x20只是個值,前面加(unsigned char *)表示0x20是個地址,(等效#define A *p  )而且這個地址類型是unsigned    char ,意思是說讀寫這個地址時,要寫進unsigned char 的值,讀出也是unsigned char 。
   
   

   
   
   

2)volatile,關鍵字volatile 確保本條指令不會因C 編譯器的優化而被省略,且要求每次直接讀值。例如用while((unsigned char *)0x20)時,有時系統可能不真正去讀0x20的值,而是用第一次讀出的值,如果這樣,那這個循環可能是個死循環。用了volatile    則要求每次都去讀0x20的實際值。
   
      那么(volatile unsigned char *)0x20是一個固定的指針,是不可變的,不是變量。而char *u則是個指針變量。
      

   

再在前面加"*":*(volatile    unsigned char *)0x20則變成了變量(普通的unsigned char變量,不是指針變量),如果#define i (*(volatile unsigned char *)0x20),那么與(等效unsigned char i)  是一樣了,只不過前面的i的地址是固定的。
   
   

    那么如何對這條語句進行理解呢?
   
    首先,我們來分析define語句后面的內容: (*(volatile unsigned char *)0x20),首先看到里面使用了關鍵字volatile和數據類型unsigned char以及C語言中的地址引用符號“*”,將這段代碼拆開來看, (unsigned char *)0x20中0x20是一個地址,其存儲數據的類型為unsigned char型,即一個8位的二進制數據,如一個8位的寄存器。利用關鍵字volatile對其進行修飾(volatile unsigned char *)0x20則表示這個地址中存放的數據容易被外部所軟件/硬件改變,告訴編譯器不要去優化該條語句,每次執行時均從該地址中去讀取這個值。再在(volatile unsigned char *)0x20的前面加上地址引用符號"*"則表示一個指針對應的變量,則這條語句就成為了一個可操作的指針所指向的地址內容,相當于*p,只不過這兒p的地址固定為了0x20,*p所指向的數據類型定義為了unsigned char,最后將define后面的內容用括號括起來,這是一個良好的編程習慣!最終就形成了我們所看到的 (*(volatile unsigned char *)0x20)形式。
    ---------------------
    實例
   

以前看到#define SREG    (*(volatile    unsigned char *)0x5F)這樣的定義,總是感覺很奇怪,不知道為什么,今天終于有了一點點心得,請大蝦們多多批磚~~~
         嵌入式系統編程,要求程序員能夠利用C語言訪問固定的內存地址。既然是個地址,那么按照C語言的語法規則,這個表示地址的量應該是指針類型。所以,知道要訪問的內存地址后,比如0x5F,
         第一步是要把它強制轉換為指針類型
    (unsigned    char *)0x5F,AVR的SREG是八位寄存器,所以0x5F強制轉換為指向unsigned char類型。
       volatile(可變的)這個關鍵字說明這變量可能會被意想不到地改變,這樣編譯器就不會去假設這個變量的值了。這種“意想不到地改變”,不是由程序去改變,而是由硬件去改變

   
   


       第二步,對指針變量解引用,就能操作指針所指向的地址的內容了
       *(volatile unsigned char *)0x5F
       第三步,小心地把#define宏中的參數用括號括起來,這是一個很好的習慣,所以#define SREG    (*(volatile    unsigned char *)0x5F)
        類似的,如果使用一個32位處理器,要對一個32位的內存地址進行訪問,可以這樣定義:
        #define RAM_ADDR     (*(volatile    unsigned long  *)0x0000555F)
        然后就可以用C語言對這個內存地址進行讀寫操作了
        以下與普通操作一樣

   

讀:tmp =    RAM_ADDR;
         寫:RAM_ADDR = 0x55

   
   
      
結論:那么你的問題就可解答了,(*(volatile unsigned char *)0x20)可看作是一個普通變量,這個變量有固定的地址,指向0x20。而0x20只是個常量,不是指針更不是變量。
   
  
用法
在嵌入式的C程序中,我們經常看到類似如下的定義:
#define AAA  (*(volatile unsigned char *)0x20)  取內容等效(X=5
#define BBB  (*(volatile unsigned char *)0x4B000020)
讀temp=AAA;

寫AAA=X22;

完整的Word格式文檔51黑下載地址:
volatile unsigned long.zip (16.96 KB, 下載次數: 14)


評分

參與人數 2黑幣 +55 收起 理由
sad520ljh + 5 共享資料的黑幣獎勵!
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 成人网址在线观看 | 成人毛片网 | 国产精品一区免费 | www久久久 | 久久久久www | 精品国产青草久久久久96 | 久久精品亚洲精品 | 日韩av在线中文字幕 | 日韩精品一区二区三区免费观看 | 可以看黄的视频 | 亚洲视频在线看 | 97国产爽爽爽久久久 | 久久免费精品视频 | 中文字幕第49页 | 精品免费av | 天天干天天插 | 午夜欧美| 久久精品—区二区三区 | 亚洲视频二区 | 国产偷自视频区视频 | 国产ts人妖另类 | 精品综合久久久 | 国产欧美日韩在线观看 | 99国产精品99久久久久久 | 中文字幕亚洲欧美日韩在线不卡 | 一区二区不卡 | 日韩在线不卡视频 | 国产精品久久午夜夜伦鲁鲁 | 成人免费看电影 | 国产一区影院 | 国产精品免费福利 | 久久小视频 | 国产亚洲精品精品国产亚洲综合 | 日本一区二区在线视频 | 久久丁香| 日韩成人一区 | 日韩国产一区二区三区 | 亚洲国产精品一区二区三区 | 人人玩人人添人人澡欧美 | 自拍偷拍3p | 天天碰夜夜操 |