微控制器指標型別和儲存區的關係詳解

2021-04-21 21:16:31 字數 3230 閱讀 2275

一、儲存型別與儲存區關係

data ---> 可定址片內ram

bdata ---> 可位定址的片內ram

idata ---> 可定址片內ram,允許訪問全部內部ram

pdata ---> 分頁定址片外ram (movx @r0) (256 byte/頁)

xdata ---> 可定址片外ram (64k 位址範圍)

code ---> 程式儲存區 (64k 位址範圍),對應movc @dptr

二、指標型別和儲存區的關係

對變數進行宣告時可以指定變數的儲存型別如:uchar data x和data uchar x相等價都是在內ram區分配乙個位元組的變數。同樣對於指標變數的宣告,因涉及到指標變數本身的儲存位置和指標所指向的儲存區位置不同而進行相應的儲存區型別關鍵字的使用如:

uchar xdata * data pstr

是指在內ram區分配乙個指標變數("*"號後的data關鍵字的作用),而且這個指標本身指向xdata區("*"前xdata關鍵字的作用),可能初學c51時有點不好懂也不好記。沒關係,我們馬上就可以看到對應「*」前後不同的關鍵字的使用在編譯時出現什麼情況。

......

uchar xdata tmp[10]; //在外ram區開闢10個位元組的記憶體空間,位址是外ram的0x0000-0x0009

......

第1種情況:

uchar data * data pstr;

pstr=tmp;

mov 0x08,#tmp(0x00) ;0x08是指標pstr的儲存位址

看到了嗎!本來訪問外ram需要2 byte來定址64k空間,但因為使用data關鍵字(在"*"號前的那個),所以按keilc編譯環境來說就把他編譯成指向內ram的指標變數了,這也是初學c51的朋友們不理解各個儲存型別的關鍵字定義而造成的bug。特別是當工程中的預設的儲存區類為large時,又把tmp[10] 宣告為uchar tmp[10] 時,這樣的bug是很隱秘的不容易被發現。

第2種情況:

uchar xdata * data pstr;

pstr = tmp;

這種情況是沒問題的,這樣的使用方法是指在內ram分配乙個指標變數("*"號後的data關鍵字的作用),而且這個指標本身指向xdata區("*"前xdata關鍵字的作用)。編譯後的彙編**如下。

mov 0x08,#tmp(0x00) ;0x08和0x09是在內ram區分配的pstr指標變數位址空間

mov 0x09,#tmp(0x00)

這種情況應該是在這裡所有介紹各種情況中效率最高的訪問外ram的方法了,請大家記住他。

第3種情況:

uchar xdata * xdata pstr;

pstr=tmp;

這中情況也是對的,但效率不如第2種情況。編譯後的彙編**如下。

mov dptr, #0x000a ;0x000a,0x000b是在外ram區分配的pstr指標變數位址空間

mov a, #tmp(0x00)

mov @dptr, a

inc dptr

mov a, #tmp(0x00)

movx @dptr, a

這種方式一般用在內ram資源相對緊張而且對效率要求不高的專案中。

第4種情況:

uchar data * xdata pstr;

pstr=tmp;

如果詳細看了第1種情況的讀者發現這種寫法和第1種很相似,是的,同第1 種情況一樣這樣也是有bug的,但是這次是把pstr分配到了外ram區了。編譯後的彙編**如下。

mov dptr, #0x000a ;0x000a是在外ram區分配的pstr指標變數的位址空間

mov a, #tmp(0x00)

movx @dptr, a

第5種情況:

uchar * data pstr;

pstr=tmp;

大家注意到"*"前的關鍵字宣告沒有了,是的這樣會發生什麼事呢?下面這麼寫呢!對了用齊豫的一首老歌名來說就是 「請跟我來」,請跟我來看看編譯後的彙編**,有人問這不是在講c51嗎? 為什麼還要給我們看彙編**。c51要想用好就要盡可能提公升c51編譯後的效率,看看編譯後的彙編會幫助大家盡快成為生產高效c51**的高手的。還是看**吧!

mov 0x08, #0x01 ;0x08-0x0a是在內ram區分配的pstr指標變數的位址空間

mov 0x09, #tmp(0x00)

mov 0x0a, #tmp(0x00)

注意:這是新介紹給大家的,大家會疑問為什麼在前面的幾種情況的pstr指標變數都用2 byte空間而到這裡就用3 byte空間了呢?這是keilc的乙個系統內部處理,在keilc中乙個指標變數最多占用 3 byte空間,對於沒有宣告指標指向儲存空間型別的指標,系統編譯**時都強制載入乙個位元組的指標型別分辯值。具體的對應關係可以參考keilc的help中c51 user's guide。

第6種情況:

uchar * pstr;

pstr=tmp;

這是最直接最簡單的指標變數宣告,但他的效率也最低。還是那句話,大家一起說好嗎!編譯後的彙編**如下。

mov dptr, #0x000a ;0x000a-0x000c是在外ram區分配的pstr指標變數位址空間

mov a, #0x01

mov @dptr, a

inc dptr

mov dptr, #0x000a

mov a, #tmp(0x00)

mov @dptr, a

inc dptr

mov a, #tmp(0x00)

movx @dptr, a

這種情況很類似第5種和第3種情況的組合,既把pstr分配在外ram空間了又增加了指標型別的分辨值。

小結一下:大家看到了以上的6種情況,其中效率最高的是第2種情況,既可以正確訪問ram區又節約了**,效率最差的是第6種,但不是說大家只使用第2種方式就可以了,還要因情況而定,一般說來應用51系列的系統架構的內部ram資源都很緊張,最好大家在定義函式內部或程式段內部的區域性變數使用內ram,而盡量不要把全域性變數宣告為內ram區中。所以對於全域性指標變數我建議使用第3種情況,而對於區域性的指標變數使用第2種方式。c51是很靈活的,也很好理解和使用,但要成為笑傲江湖的一代高手還是要多想多練,沒有實際專案的鍛鍊是不容易提高的。希望這篇文章對大家一點用處。

51微控制器 RAM 資料儲存區

ram 是程式執行中存放隨機變數的資料空間。在 keil 中編寫程式,如果當前模式為small模式,如果總的變數大小未超過128b 則未初始化的變數的初值預設為 0.如果所有的變數超過微控制器small模式下的128b 大小,則必須對變數進行初始化,否則超過 ram大小變數的值是不確定的,在smal...

關於微控制器XDATA 和DATA區

最近在做專案的時候在編譯keil文件時遇到問題,其實自己也是小白菜,在做專案中慢慢進步,遇到問題解決了就記下來,以免後邊犯同樣的錯誤 關於 error l105 public refers to ignored segment錯誤 這個錯誤說明你的微控制器內部的data區已經滿了,放不下更多的變數。...

微控制器學習筆記二(微控制器的儲存結構)

8051微控制器在物理結構上有4個儲存空間 1.片內程式儲存器 2.片外程式儲存器 3.片內資料儲存器 4.片外資料儲存器 邏輯上,8051微控制器有三個儲存空間 1.片內外統一編址的64k的程式儲存器位址空間 movc 2.256b的片內資料儲存器的位址空間 mov 3.64k片外資料儲存器的位址...