書名: 單片機C語言程序設計實訓100例:基于STC8051+Proteus仿真與實戰作者名: 彭偉本章字數: 1874字更新時間: 2022-05-05 20:18:21
1.7 變量、存儲類型與存儲模式
全局變量定義在函數外面。全局變量的生命期從所定義的地方開始,其后面的所有函數都可以讀/寫該全局變量。在本書有關案例中,在使用定時/計數器(Timer/Counter)時,為得到更大的延時值,程序中定義了全局變量tCount,并在定時器中斷內對該變量累加,從而得到更大的延時值。如果源程序中其他位置不使用該變量,則tCount可放在中斷函數的上一行,而不必放在程序最前面。
靜態(static)變量具有固定的內存定位。如果在某個函數內部定義了靜態變量及初始值,僅在該函數被首次調用時,該靜態變量將被初始化,此后對該函數的調用都不會再初始化該變量,這類似于定義了一個專屬于該函數的全局變量。在有關定時器案例中,為通過軟件實現更長的延時,常常在定時器溢出中斷函數內部定義static u8 tCount=0,通過在每次溢出中斷發生時,累加tCount變量來實現更長的延時。
局部變量定義在函數內部。對于循環及其他的臨時計算應盡可能使用局部變量。作為優化處理的一部分,編譯程序會試圖將局部變量維持在寄存器中。寄存器訪問是最快的內存訪問類型,特別是對于unsigned char和unsigned int類型的變量。
外部(extern)變量用于聲明當前C語言程序要使用,且定義在當前項目內其他C語言程序文件中的變量。例如,某單片機程序項目由2個以上C語言程序文件構成;當前C語言程序文件中有定義extern u8 x,這表示變量x是一個外部變量,它定義在項目內其他C語言程序文件內。
易變型(volatile)變量表示一個單變量或數組的值是會隨時變化的,即使程序沒有專門對其進行任何賦值操作。例如,作為輸入的I/O端口,其引腳值將隨時可能被用戶改變;在中斷函數內被修改的變量相對于主程序流程來講也是隨時變化的;很多特殊功能寄存器的值也將隨著指令的運行而動態改變。所有這些類型的變量要注意將它們明確定義成“volatile”類型,該類型定義可通知編譯器在優化處理過程中不能無故消除它們。
在單片機C語言程序中斷函數內,凡是修改的是全局變量或全局數組,而這些變量或數組又被主程序或其他函數引用,則要注意添加volatile關鍵字。
在8051單片機中,程序存儲器(ROM)與數據存儲器(RAM)是嚴格分開的,特殊功能寄存器與片內RAM統一編址,這與一般微型計算機的存儲結構是不同的。
Keil C51編譯器完全支持8051單片機硬件結構,可完全訪問8051單片機的硬件系統的所有部分。Keil C51編譯器通過將變量、常量定義成不同的存儲類型(data、bdata、idata、pdata、xdata、code),從而將它們定位在不同的存儲區中。表1-9列出了Keil C51存儲類型與8051單片機存儲空間的對應關系。
表1-9 Keil C51存儲類型與8051單片機存儲空間的對應關系

data、bdata、idata存儲類型將數據定位在片內RAM中,且只需要8位地址。
Keil C51編譯器提供了兩種片外存儲類型:xdata和pdata。指定為xdata存儲器類型的數據保存在最大空間為64KB的片外RAM中。通過P0與P2端口給出的16位地址(216=64KB)可訪問片外空間中的任意位置,但是64KB地址空間并非總是用于存儲器尋址的,單片機外圍擴展設備地址也可以映射到存儲器空間(Memory Space)。這樣,C語言程序在訪問外圍設備時所使用語句與訪問擴展內存的語句是相同的,并將這種技術稱為內存映射I/O技術。本書有關8255和部分字符及圖形液晶顯示案例使用的就是這種技術。pdata存儲類型的數據保存在最大空間為一頁的256B片外RAM中,而頁地址則由P2接口提供。
在擴展片外存儲器或外部設備時,源程序必須包含絕對內存訪問(Absolute Memory Access)頭文件absacc.h。該文件中有宏定義:

由其中的XBYTE定義可知,表達式XBYTE[地址]或*(XBYTE+地址)均可用來讀/寫片外RAM空間的字節數據。在有關62256擴展內存案例中就使用了該表達式訪問片外RAM。該表達式相當于匯編語言中的MOVX @DPTR語句。
對于STC15單片機而言,上述關于片內與片外的描述是相對的,要真正選擇片外存儲,還需要AUXR寄存器的EXTRAM位配合。
在涉及數碼管顯示、圖像與文字顯示的案例中,由于數碼管段碼是固定的,待顯示的圖像或文字點陣數據也是固定的,將這些數據全部保存在RAM中會占用太多寶貴的空間,甚至導致編譯失敗并提示變量定義超出了RAM空間。這是因為單片機的RAM空間本來就是非常有限的。在使用C語言開發單片機程序時,應將那些運行過程中不會發生變化的數據定義為code存儲類型,以保證將這些數據分配到Flash ROM中而不是RAM中。
定義變量時如果省略存儲類型,編譯程序將自動選擇默認存儲類型。默認存儲類型有小模式(Small)、緊縮模式(Compact)和巨模式(Large)限制,存儲模式決定了變量的默認存儲類型、參數傳遞區和未指明存儲類型變量的存儲類型。表1-10列出了這3種存儲模式及相關說明。
表1-10 3種存儲模式及相關說明

在固定的存儲器地址上進行變量傳遞是Keil C51的特征之一。在Small模式下,參數傳遞在片內RAM中完成,Compact和Large模式允許參數在片外RAM中傳遞。模式選擇可在Keil C51項目選項窗口中的Target選項卡下完成,默認選擇的是Small模式。
- Google Apps Script for Beginners
- Instant Testing with CasperJS
- 編程的修煉
- Learning RabbitMQ
- Scala編程實戰(原書第2版)
- Getting Started with Laravel 4
- Node.js:來一打 C++ 擴展
- Machine Learning With Go
- Orchestrating Docker
- Visual Basic程序設計全程指南
- SSH框架企業級應用實戰
- Learning Unreal Engine Game Development
- Web前端開發最佳實踐
- MongoDB Cookbook
- JBoss AS 7 Development