<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 51單片機(jī)同時(shí)外擴(kuò)RAM,ROM的具體實(shí)現(xiàn)及Keil的具體設(shè)置

          51單片機(jī)同時(shí)外擴(kuò)RAM,ROM的具體實(shí)現(xiàn)及Keil的具體設(shè)置

          作者: 時(shí)間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
          51MCU內(nèi)部有RAM,ROM,不同于8031。盡管如今的增強(qiáng)行51MCU的內(nèi)部RAM,ROM可能已經(jīng)很大的空間。但就技術(shù)而言,擴(kuò)展RAM,ROM還是需要學(xué)會的。
          對于不同的設(shè)計(jì)方案需求,擴(kuò)展可能基于以下任何一種設(shè)計(jì):
          A,只擴(kuò)展RAM
          B,只擴(kuò)展ROM
          C,擴(kuò)展ROM,RAM
          總線擴(kuò)展時(shí),P2口是否可用做普通IO口
          這種擴(kuò)展是基于總線擴(kuò)展的,所以,P0P2口就已經(jīng)不可以再做它用了(有網(wǎng)友提供信息,總線擴(kuò)展P2還可以做普通IO口用,有兩種可能:1,P2口復(fù)用,如同P1利用373鎖存器。2,在總線擴(kuò)展時(shí),只用到了低地址總線,P2口未用到。就作為普通IO口應(yīng)用。由于技術(shù)還不到位,不做評論。)
          *擴(kuò)展RAM程序
          擴(kuò)展RAM,在程序中定義的xdata類型 XBYTE類型等地址范圍在外部RAM的變量,對其讀寫的過程。用C51語言編寫程序,且使用總線擴(kuò)展的RAM,則時(shí)序電路不用考慮,WR RD等信號由編譯器/硬件自動(dòng)完成。
          編譯器設(shè)置*
          內(nèi)部RAM:0x00~~0xFF
          外部RAM:0x0000~~0xFFFF
          RAM的地址雖重復(fù),但是兩個(gè)RAM是沒有關(guān)系的,所以不會造成干擾
          使用了外部RAM,就在工程選項(xiàng)---off-chip xdata memory中設(shè)置 start:0x0000 size:0xFFFF(根據(jù)具體的RAM大小設(shè)置size)。
          *擴(kuò)展RAM時(shí)的變量定位及連續(xù)讀取問題*
          ROM,RAM的擴(kuò)展時(shí),需要用到變量的絕對地址定位,函數(shù)定位等。
          變量的絕對地址定位,是由于在程序中可能需要即時(shí)讀取某個(gè)變量,但變量的類型可能是XDATA,存儲在外部RAM中。這里有兩個(gè)方法:
          1,用 _at_ 定位 關(guān)鍵字定位
          unsigned char xdata xxx _at_ 0x1100 //定義變量XXX數(shù)據(jù)類型xdata,位置0x1100
          [memory_space]tepe variable_name _at_ constant;
          *絕對地址的變量不可以被初始化;函數(shù)或BIT類型的變量是不可以被定義為絕對地址;
          2,用 XBYTE 定位 宏定義 絕對地址訪問
          #define CBYTE((unsigned char volatile code*)0)
          #define DBYTE((unsigned char volatile idata*)0)
          #define PBYTE((unsigned char volatile pdata*)0)
          #define XBYTE((unsigned char volatile xdata*)0)
          ////////////////////////////////////////////////////////////////////////////
          #define CWORD((unsigned int volatile code*)0)
          #define DWORD((unsigned int volatile idata*)0)
          #define PWORD((unsigned int volatile pdata*)0)
          #define XWORD((unsigned int volatile xdata*)0)
          以上是宏定義的原型函數(shù),定義在 #include 頭文件中
          #defme xxx XBYTE[0x8000] //變量類型為unsigned char 類型的數(shù)據(jù)xxx,位置xdata 0x8000
          yyy=XBYTE[0x8000]; //變量類型為unsigned char 類型的數(shù)據(jù)yyy,位置xdata 0x8000
          (在這里,有網(wǎng)友提到,當(dāng)編譯器優(yōu)化時(shí),用絕對地址定位的變量,可能導(dǎo)致變量在連續(xù)讀取時(shí)出
          錯(cuò),采用解決方法:
          a,將編譯器優(yōu)化調(diào)整為0,即不優(yōu)化,程序不用修改,做以下操作
          >>選擇project窗口的Target,然后打開"OptionsforTarget” 設(shè)置對話框,選擇“C5l”選項(xiàng)卡,
          將“Code Optimiztaion”中的“Level”選擇為“0:Costant folding”。再次編譯<<
          b,修改變量定義,增加“volatile”關(guān)鍵字說明其特征:就是說明該變量具有‘揮發(fā)’性,每次的讀取都一
          有意義的,這樣編譯器即使在優(yōu)化時(shí),編譯后的代碼也不會省略掉重復(fù)讀取的過程。如:
          unsigned char volatile xdata xxx_at_0x8000;
          由上文XBYTE等的宏定義函數(shù)原型可以看出,該宏定義已經(jīng)說明了變量具有volatile特性,因此,
          也可以直接用XBYTE定義所需要的變量
          c,硬件解決辦法
          以上解決方法為參考網(wǎng)絡(luò)文章)
          *擴(kuò)展ROM時(shí)的函數(shù)定位函數(shù)一部分在內(nèi)部ROM,一部分在外部ROM中
          函數(shù)定位,個(gè)人理解:當(dāng)一個(gè)完整功能的程序存儲在外部內(nèi)部ROM中時(shí),即利用了內(nèi)部ROM,可能由于內(nèi)部ROM空間不夠,部分函數(shù)在外部中,這時(shí),如果要執(zhí)行整個(gè)功能,就需要告訴編譯器,其他功能函數(shù)的地址(函數(shù)在外部ROM中的地址),此時(shí)就要用到函數(shù)定位功能。解決方法如下:
          ....待續(xù).....
          51內(nèi)部ROM地址范圍0x0000~0x0FFF,所以外部ROM的地址為0x1000~~最大0xFFFF。
          c51bbs有詳細(xì)介紹
          編寫完整的程序(如果建立兩個(gè)工程,堆棧等可能分配位置不同,導(dǎo)致地址重復(fù)或多個(gè)地址出錯(cuò)),
          編譯后查看.M51文件,找到需要定位的函數(shù)名稱信息(如?PR?_BCD2HEX?TOOLS),在KEIL51工程選項(xiàng)---BL51 lacate中code項(xiàng)中加入:?PR?_BCD2HEX?TOOLS(0x1000)再次編譯工程,打開.M51文件會發(fā)現(xiàn)?PR?_BCD2HEX?TOOLS已經(jīng)定位在了0x1000位置了。
          如果有多個(gè)程序需要定位,方法同上,找出函數(shù)的名稱信息,添加到BL51 locate的CODE項(xiàng)中,每個(gè)函數(shù)之間用逗號隔開。而且要注意,所要定位的多個(gè)函數(shù)根據(jù)定位設(shè)置之前的地址高低安排,仍舊是低地址函數(shù)在前,高地址函數(shù)在后。
          程序分為兩部分存儲,需要做的設(shè)置等如下:
          ....待續(xù).....
          完成函數(shù)定位設(shè)置后,由于函數(shù)是要燒錄在兩個(gè)ROM中,需要將HEX文件分割成兩個(gè),內(nèi)部ROM空間范圍與外部ROM空間范圍是不一樣的,自然就應(yīng)該將內(nèi)部ROM的地址范圍的HEX代碼存儲為一個(gè)文件,將剩余部分的代碼存儲為另一個(gè)文件,就完成了分割。
          例如HEX文件的0x0000~~0x0FFF地址劃分為一個(gè)文件,0x1000~~0xFFFF劃分為另一個(gè)文件。
          這一點(diǎn),如果所用的MCU的內(nèi)部ROM大小不一致,就需要根據(jù)具體的大小劃分分割HEX文件。
          *編譯器設(shè)置
          由于是內(nèi)部ROM和外部擴(kuò)展ROM同時(shí)使用,在工程選項(xiàng)off-chip memory中需要設(shè)置外部ROM地址范圍,如eprom start:0x1000 size:0xFFFF(根據(jù)具體ROM大小設(shè)置size,同時(shí)use on-chip memory選項(xiàng)不選,電路中EA接高電平)
          *擴(kuò)展ROM,所有程序都在外部ROM中
          51內(nèi)部ROM不夠用,但外部擴(kuò)展的ROM應(yīng)該足夠了,所以,在擴(kuò)展了ROM之后,盡量避免編程麻煩,所有功能均放在外部ROM中,此時(shí)需要的設(shè)置操作等如下:
          ....待續(xù).....
          由于程序代碼只用到了外部ROM,程序編譯等不需要特殊的設(shè)置,按正常編譯。然后將整個(gè)代碼燒錄到外部ROM就可以了。也就不存在HEX文件分割的問題了。
          *編譯器設(shè)置
          由于只用到了外部ROM,在工程選項(xiàng)off-chip memory中需要設(shè)置外部ROM地址范圍,如eprom start:0x0000 size:0xFFFF(根據(jù)具體ROM大小設(shè)置size,同時(shí)use on-chip memory選項(xiàng)不選,電路中EA接低電平),這里的設(shè)置不同與內(nèi)外部ROM都用的情況,沒有使用內(nèi)部ROM的情況下需要地址從0x0000開始,程序的開始地址中斷向量等都在這里(具體參考內(nèi)部ROM地址的使用)。EA接低電平表示程序是從外部ROM開始讀起的,即不用內(nèi)部ROM。
          擴(kuò)展ROM,RAM時(shí),總線地址如何安排*
          在擴(kuò)展了ROM,RAM時(shí),總線地址要如何安排,具體怎樣設(shè)置呢?操作如下:
          ......待續(xù).......
          在程序設(shè)計(jì)時(shí),要考慮硬件連接。例如,在外部ROM,RAM的地址設(shè)置時(shí)(keil工程選項(xiàng)中),假設(shè)P15初始化置1了或在程序中,P15為1時(shí)WR RD信號才時(shí)序正常(使用了74門電路),則keil工程選項(xiàng)中的地址設(shè)置就要考慮工作狀態(tài)P15是0或1的情況了。頁選信號就是從這里這樣而來的,P15頁選或地址線高字節(jié)頁選。
          *硬件連接,需要考慮的問題
          擴(kuò)展ROM,RAM時(shí),硬件需要?jiǎng)t樣連接?總線上的時(shí)續(xù),總線設(shè)備的速度匹配問題?
          .......待續(xù)........
          使用總線方式連接擴(kuò)展設(shè)備時(shí),51總線有固定的時(shí)序,時(shí)序也就決定了速度。比如每個(gè)讀寫的過程,相應(yīng)的信號持續(xù)時(shí)間長短,擴(kuò)展設(shè)備能否在這個(gè)周期內(nèi)完成工作,是需要51的總線時(shí)序和擴(kuò)展設(shè)備的時(shí)序匹配才可以的。


          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();