数据的存储器类型和存储器模式
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据的存储器类型和存储器模式
2009-05-10 13:28
数据的存储器类型和存储器模式
变量是一种在程序执行过程中,其数值不断变化的量。
C51规定变量必须先定义后使用。
C51对变量的进行定义的格式如下:[存储种类] 数据类型 [存储器类型] 变量名表。
其中,存储种类和存储器类型是可选项。
1. 存储种类
存储种类是指变量在程序执行过程中的作用范围。
变量的存储种类有四种,分别为:自动(auto)、外部(extern)、静态(static)和寄存器(register)。
使用存储种类说明符auto定义的变量称为自动变量。
自动变量作用范围在定义它的函数体或复合语句内部,在定义它的函数体或复合语句被执行时,C51才为该变量分配内存空间,当函数调用结束返回或复合语句执行结束时,自动变量所占用的内存空间被释放,这些内存空间又可被其他的函数体或复合语句使用。
可见使用自动变量能最有效地使用80C51单片机内存。
定义变量时,如果省略存储种类,则该变量默认为自动(auto)变量。
由于80C51单片机访问片内RAM速度最快,通常将函数体内和复合语句中使用频繁的变量放在片内RAM中,且定义为自动变量,可有效地利用片内有限的RAM资源。
使用外部种类存储符extern定义的变量称为外部变量。
在一个函数体内,要使用一个已在该函数体外或别的程序模块文件中定义过的外部变量时,该变量在本函数体内要用extern说明。
外部变量被定义后,即分配了固定的内存空间,在程序的整个执行时间内都是有效的。
通常将多个函数或模块共享的变量定义为外部变量。
外部变量是全局变量,在程序执行期间一直占有固定的内存空间。
当片内RAM资源紧张时,不建议将外部变量放在片内RAM。
使用存储种类说明符static定义的变量称为静态变量。
静态变量分为局部静态变量和全局静态变量。
局部静态变量是在两次函数调用之间仍能保持其值的局部变量。
有些程序要求在多次调用之间仍然保持变量的值,使用自动变量无法作用到这一点。
使用全局变量有时会带来意外的副作用,这时可采用局部静态变量。
使用存储种类说明符register定义的变量称为寄存器变量。
80C51访问寄存器的速度最快,通常将使用频率最高的那些变量定义为寄存器变量。
C51编译器能自动识别程序中使用频率最高的变量,并自动将其作为寄存器变量,用户无需专门声明。
2. 存储器类型
存储器类型:
用以指明所定义的变量应分配在什么样的存储空间。
一、程序存储区
Code:程序空间
用code标识符来访问片内、片外统一编址的程序存储区,寻址范围为
0~65535。
二、内部数据存储区
Data: 直接访问的内部数据存储器
该标识符通常是指低128字节的内部数据区,为片内直接寻址的RAM空间,寻址范围0~127。
Idata: 间接访问的内部数据存储器
该标识符是指全部256个字节的内部存储区,为片内间接寻址的RAM空间,寻址范围为0~255。
Bdata: 可位寻址的内部数据存储器
该标识符是指可位寻址的16字节内部存储区(20H~2FH),位地址范围为
0~127.本空间允许按字节和按拉寻址。
三、外部数据存储区
Xdata: 外部数据存储器(64KB)
该标识符是指外部数据存储区(64KB)内的任何地址,寻址范围为0~65535。
Pdata: 分页的外部数据存储器(256字节)
该标识符仅指一页或256字节的外部数据存储区,寻址范围为0~255。
定义变量时,除了说明存储种类外,还允许说明变量的存储器类型。
存储器类型和存储种类是完全不同的概念,存储器类型指明该变量所处的单片机的内存空间。
如果在变量定义时省略了存储器类型标识符,C51编译器会选择默认的存储器类型。
默认的存储器类型由SMALL、COMPACT和LARGE存储模式指令决定。
1)DATA区
对DATA区的寻址是最快的,所以应该把使用频率高的变量放在DATA区,由于空间有限,必须注意使用DATA区,DATA区除了包含程序变量外,还包含了堆栈和寄存器组DATA 区。
unsigned char data system_status=0;
unsigned int data unit_id[2];
char data inp_string[16];
float data outp_value;
mytype data new_var;
在SMALL存储模式下,未说明存储器类型时,变量默认被定位在DATA区。
标准变量和用户自定义变量都可以存储在DATA区,只要不超过DATA区的范围。
因为C51使用默认的寄存器组传递参数,至少失去了8B。
另外要定义足够大的堆栈空间,当内部堆栈溢出的时候,程序会产生莫名其妙的错误,实际原因是80C51系列单片机没有硬件报错机制,堆栈溢出只能以这种方式表示出来。
2)BDATA区
当在DATA区的位寻址区定义变量,这个变量就可进行位寻址,并且声明位变量。
这对状态寄存器来说十分有用,因为它可以单独使用变量的每一位,而不一定要用位变量名引用位变量。
下面是一些在BDATA区中声明变量和使用位变量的例子。
unsigned char bdata status_byte;
unsigned int bdata status_word;
unsigned long bdata status_dword;
sbit stat_flag=status_byte^4;
if(status_word^15){
……}
stat_flag=1;
编译器不允许在BDATA区中定义float和double类型的变量,如果想对浮点数的每位寻址,可以通过包含float和long的联合实现。
typedef union{ /*定义联合类型*/
unsigned long lvalue; /*长整型32位*/
float fvalue; /*浮点数32位*/
}bit_float; /*联合名*/
bit_float bdata myfloat; /*在BDATA区中声明联合*/
sbit float_ld=myfloat.lvalue^31; /*定义位变量名*/
3)IDATA区
IDATA区也可以存放使用比较频繁的变量,使用寄存器作为指针进行寻址。
在寄存器中设置8位地址进行间接寻址,与外部存储器寻址比较,它的指令执行周期和代码长度都比较短。
unsigned char idata system_status=0;
unsigned int idata unit_id[2];
char idata inp_string[16];
float idata outp_value;
4)PDATA和XDATA区
在这两个区声明变量和在其他区的语法是一样的,PDATA区只有256B,而XDATA区可达65536B,举例如下。
unsigned char xdata system_status=0;
unsigned int pdata unit_id[2];
char xdata inp_string[16];
float pdata outp_value;
对PDATA和XDATA的操作是相似的,对PDATA区寻址比对XDATA区寻址要快,因为对PDATA区寻址只需要装入8位地址,而对XDATA区寻址需装入16位地址。
所以尽量把外部数据存储在PDATA区中,对PDATA和XDATA寻址要使用MOVX指令,需要2个处理周期。
5)CODE区
CODE区即80C51的程序代码区,所以代码区的数据是不可改变的,80C51的代码区不可重写。
一般代码区中可存放数据表,跳转向量和状态表,对CODE区的访问和对XDATA 区的访问的时间是一样的,代码区中的对象在编译时初始化,否则就得不到想要的值。
下面是代码区的声明例子。
unsigned int code unit_id[2]={0x1234, 0x89ab};
unsigned char code uchar_data[16] ={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x10,0x11,0x12,0x13,0x14,0x15};
3. 存储模式
C51编译器允许采用三种存储模式:小编译模式SMALL、紧凑编译模式COMPACT、大编译模式LARGE。
一个变量的存储器模式确定了变量在内存中的地址空间。
在SMALL模式下,该变量在80C51单片机的内部RAM中;在COMPACT和LARGE模式下,该变量在80C51单片机的外部RAM中。
同样一个函数的存储器模式确定了函数的参数和局部变量在内存中的地址空间。
在SMALL模式下,函数的参数和局部变量在80C51单片机的内部RAM中;在COMPACT
和LARGE模式下,函数的参数和局部变量在80C51单片机的外部RAM中。
下面这个例子说明了存储模式的定义方法。
变量和函数的存储模式
#pragma small /*默认存储器类型为80C51片内直接寻址RAM*/
char data i,j,k; /*在80C51片内直接寻址RAM中定义了3个变量,默认为自
动变量*/
char i,j,k; /*未指明存储模式,由#pragma small决定,与前一句完全等价*/
int xdata m, n; /*在80C51片外RAM中定义了2个自动变量*/
static char m, n; /*在80C51片内直接寻址RAM中定义了2个静态变量*/
unsigned char xdata ram[128]; /*在80C51片外RAM中定义了大小为128B的数组变量*/
int func1(int i, int j) large /*指定 large 模式*/
{
return(i+j);
}
int func2(int i, int j) /*未指明存储模式, 按默认的SMALL模式*/
{
return(i-j);
}
不同的存储器类型访问速度是不一样的,如:
unsigned char data var1; /*SMALL模式,var1被定位在DATA区*/
/*即80C51片内直接寻址RAM*/
unsigned char pdata var1; /*COMPACT模式,var1被定位在PDATA区*/
/*即80C51片外按页面间接寻址RAM*/
unsigned char xdata var1; /*LARGE模式,var1被定位在XDATA区*/
/*即80C51片外间接寻址RAM*/
在SMALL模式下,var1被定位在DATA区,经C51编译器编译后,采用内部RAM直接寻址方式访问速度最快;在COMPACT模式下,var1被定位在PDATA区,经C51编译器编译后,采用外部RAM间接寻址方式访问速度较快;在LARGE模式下,var1被定位在XDATA 区,经C51编译器编译后,采用外部RAM间接寻址方式访问速度最慢。
为了提高系统运行速度,建议在编写源程序时,把存储模式设定为SMALL,再在程序中把XDATA、PDATA和IDATA 等类型变量进行专门声明。