在单片机c51中,局部变量的存储类型型

8051单片机存储结构及变量、指针使用技巧
MCS-51单片机在物理结构上有四个存储空间:
1、片内程序存储器
2、片外程序存储器
3、片内数据存储器
4、片外数据存储器
但在逻辑上,即从用户的角度上,8051单片机有三个存储空间:
1、片内外统一编址的64K的程序存储器地址空间
2、256B的片内数据存储器的地址空间
3、以及64K片外数据存储器的地址空间
在访问三个不同的逻辑空间时,应采用不同形式的指令(具体我们在后面的指令系统学习时将会讲解),以产生不同的存储器空间的选通信号
数据存储器
数据存储器也称为随机存取数据存储器。数据存储器分为内部数据存储和外部数据存储。
访问片内RAM用“MOV”指令,访问片外RAM用“MOVX”指令。它们是用于存放执行的中间结果和过程数据的。
MCS-51单片机的内部数据存储器在物理上和逻辑上都分为两个地址空间,即: 数据存储器空间(低128单元)
特殊功能寄存器空间(高128单元)&
从用户角度而言,低128单元才是真正的数据存储器
程序存储器
当EA=1时,程序从片内ROM开始执行,当PC值超过片内ROM容量时会自动转向外部ROM空间。
当EA=0时,程序从外部存储器开始执行,例如前面提到的片内无ROM的8031单片机,在实际应用中就要把8031的引脚接为低电平。
8051片内有4kB的程序存储单元,其地址为0000H—0FFFH,单片机启动复位后,程序计数器的内容为0000H,所以系统将从0000H单元开始执行程序。但在程序存储中有些特殊的单元,这在使用中应加以注意:
其中一组特殊是0000H—0002H单元,系统复位后,PC为0000H,单片机从0000H单元开始执行程序,如果程序不是从0000H单元开始,则应在这三个单元中存放一条无条件转移指令,让CPU直接去执行用户指定的程序。
另一组特殊单元是0003H—002AH,这40个单元各有用途,它们被均匀地分为五段,它们的定义如下:
可见以上的40个单元是专门用于存放中断处理程序的地址单元,中断响应后,按中断的类型,自动转到各自的中断区去执行程序。从上面可以看出,每个中断服务程序只有8个字节单元,用8个字节来存放一个中断服务程序显然是不可能的。因此以上地址单元不能用于存放程序的其他内容,只能存放中断服务程序。但是通常情况下,我们是在中断响应的地址区安放一条无条件转移指令,指向程序存储器的其它真正存放中断服务程序的空间去执行,这样中断响应后,CPU读到这条转移指令,便转向其他地方去继续执行中断服务程序。
keil C51新增一些变量类型
code:存放在ROM内,注意是程序存储器,不是数据存储器,只能使用MOVC指令访问变量,而且只读,不易丢失
data:片内RAM的低128字节,可直接寻址
bdata:可位寻址的片内RAM,在不进行位处理时与data相同
以上两种类型可以快速的存取数据,常用来放临时性的传递变量或使用频率较高的变量。
idata:整个片内RAM间接寻址。在52内核中,当片内直接寻址数据存储器不够用时,可以使128字节间接寻址,访问速度比data慢
xdata:片外存储区(64KB),由于在对片外存储区操作时,需要先将数据移到片内,进行处理后再存储到片外,因此常用来存放不常用的变量,或收集待处理的数据,或存放要被发往另一台计算机的数据。目标代码只能使用MOVE
pdata:属于xdata类型,且片外存储器的第一页
bit:位变量。存储在片内数据存储器的可位寻址字节(20H~2FH)的某个位上,这个变量在实时控制中具有很高的实用价值
重点是新增的指针变量存储类型
一般指针Generic Pointer和存储器指针Memory_Specific Pointer
数据类型[数据存储类型]*[指针存储类型]标识符
char data * &
//str指向data区中char型数据,且str存储在data区,若不使用[数据存储类型],则指针为一般指针,占用3个字节;若使用[数据存储类型]则指针为基于存储器的指针,占用1~2个字节。
Keil C51中使用变量存储模式的必要性
在Keil C51中,变量的存储模式是一个可选项,如果不使用这个选项,则Keil
C51在编译时自动进行优选分配。但这种处理方法有以下缺点:
1、系统不知道各种变量的使用频度,有可能对使用频度高的变量使用了访问速度慢的片外存储方式,而对使用频高的变量使用了片内存储方式,使得程序的运行效率降低;
2、在使用指针寻址时,由于不知道寻址对象的存储方式,只好使用一般指针,在Keil
C51中一般指针要多占用1~2个字节,并且使用时还要对存储方式进行判断,增加了寻址操作时间。
如果能够在定义变量的同时定义其存储类型,可以高效地使用51内核单片机的存储空间,获得高质量的目标代码。
全局变量和静态局部变量
全局变量一般会在多个函数中被使用,并在整个程序运行期间内有效,静态局部变量虽然只在一个函数中使用,但也是在整个程序运行期间有效。对于这些变量,应尽量选择data型,这样在目标代码中就可以用直接寻址指令访问,获得最高的访问速度,提高程序的工作效率。例如一个保存人数的全局变量n_g,在多个函数中都被经常用到,可以这样定义:
unsigned int data n_g;
非静态局部变量
非静态局部变量仅在某一函数内使用,退出该函数时变量也被释放。
若系统使用small存储模式,对于这些变量可以不加存储说明,由编译软件自行按最优原则决定,因为仅在函数内使用的非静态局部变量,有可能使用工作寄存器R0~R7,这样会更快速和更节省存储空间。例如:
unsigned char i,j;//系统尽可能会用R0~R7存储i和j
若系统使用了compact或large存储模式,则应将这些变量定义为data存储模式,以防系统自行决定时被定义为pdagta或xdata模式而降低工作效率
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。查看: 3553|回复: 4
请教一个在程序定义的变量如何在单片机的Flash或RAM储存的问题
主题帖子精华
新手上路, 积分 28, 距离下一级还需 22 积分
在线时间0 小时
先给出一段代码:
#include &reg51.h&
#include "uart.h"
&void main()
&&&&char []str="abcdef";
&&&&UartInit();
&&&&while(1)
&&&&&&&&nbsprintString(str);
&&&&&&&&Delayms(500);
这样,这个测试程序可以一直通过串口打印字符串“abcdef”。
问题1:定义的char []str字符数组占用了单片机的RAM,是否同时占用单片机的Flash程序空间?
问题2:如果在字符数组定义时加上“code”关键词,即定义成 char code []str ="abcdef";是不是只占用单片机的Flash程序空间?
请各位大神指教,先谢谢了。。
--------------------------------------------------------------------------------------------------------
如果说 char []str ="abcdef"定义后只占用RAM;char code []str="abcdef";定义后只占用Flash,
那为什么char []str ="abcdef"这样定义的程序编译下载到单片机后能打印出“abcdef”呢,断电后重启也能打印出来,这个字符不是保存在RAM空间么?很疑惑。
回复【3楼】Weboo10000:
---------------------------------
abcdef,肯定是存放在flash里面了.
只是你同时又将这个字符串赋值给了数组str.
等于说单片机内部有这么一个操作:
实际存储:
code&str1x="abcdef"
运行到main函数时:
char&str[]=str1x;
主题帖子精华
在线时间273 小时
回复【3楼】Weboo10000:
---------------------------------
abcdef,肯定是存放在flash里面了.
只是你同时又将这个字符串赋值给了数组str.
等于说单片机内部有这么一个操作:
实际存储:
code&str1x="abcdef"
运行到main函数时:
char&str[]=str1x;
我的淘宝小店:
主题帖子精华
新手上路, 积分 33, 距离下一级还需 17 积分
在线时间0 小时
HI,你好,如果定义,char&[]str&在程序编译的时候就分配了RAM空间,这个空间在整个MAIN函数里面都有效。
对于问题2,是只占用了FLASH的空间
主题帖子精华
新手上路, 积分 28, 距离下一级还需 22 积分
在线时间0 小时
回复【2楼】CXP_ARM:
---------------------------------
谢谢这位朋友的解答。我的疑问点还有一个:就是说这个程序编译后生成HEX,下载到单片机,定义的char&str[]="abcdef";是存在于所分配的RAM空间,而不会占用Flash空间,那我让单片机断电重启,串口还是能打印“abcdef”这样的字符串,那这个要怎么解释呢?主要是这一点我很迷糊
主题帖子精华
新手上路, 积分 28, 距离下一级还需 22 积分
在线时间0 小时
回复【4楼】正点原子:
---------------------------------
谢谢原子哥,你这么解释我终于明白了。
Powered byC51存储器类型与51单片机的物理区域
17:25:13&&&来源:21ic &&
1、 data区空间小,所以只有频繁用到或对运算速度要求很高的变量才放到data区内,比如for循环中的计数值。
2、 data区内最好放局部变量。
因为局部变量的空间是可以覆盖的(某个函数的局部变量空间在退出该函数是就释放,由别的函数的局部变量覆盖),可以提高内存利用率。当然静态局部变量除外,其内存使用方式与全局变量相同;
3、 确保你的程序中没有未调用的函数。
在Keil C里遇到未调用函数,编译器就将其认为可能是中断函数。函数里用的局部变量的空间是不释放,也就是同全局变量一样处理。这一点Keil C做得很愚蠢,但也没办法。
4、 程序中遇到的逻辑标志变量可以定义到bdata中,可以大大降低内存占用空间。
在51系列芯片中有16个字节位寻址区bdata,其中可以定义8*16=128个逻辑变量。定义方法是: bdata bit LedS但位类型不能用在数组和结构体中。
5、 其他不频繁用到和对运算速度要求不高的变量都放到xdata区。
6、 如果想节省data空间就必须用large模式,将未定义内存位置的变量全放到xdata区。当然最好对所有变量都要指定内存类型。
7、 当使用到指针时,要指定指针指向的内存类型。在C51中未定义指向内存类型的通用指针占用3个字节;而指定指向data区的指针只占1个字节;指定指向xdata区的指针占2个字节。如指针p是指向data区,则应定义为: char data *p;。还可指定指针本身的存放内存类型,如:char data *。其含义是指针p指向data区变量,而其本身存放在xdata区。
bit---是在内部数据存储空间中 20H .. 2FH 区域中一个位的地址,或者 8051 位可寻址 SFR 的一个位地址。
code---是在 0000H .. 0FFFFH 之间的一个代码地址。
data---是在 0 到 127 之间的一个数据存储器地址,或者在 128 .. 255 范围内的一个特殊功能寄存器(SFR)地址。
idata---是 0 to 255 范围内的一个 idata 存储器地址。
xdata 是 0 to 65535 范围内的一个 xdata 存储器地址。
指针类型和存储区的关系详解
一、存储类型与存储区关系
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的0x9
第1种情况:
uchar data *
首先要提醒大家这样的代码是有bug的, 他不能通过这种方式正确的访问到tmp空间。 为什么?我们把编译后看到下面的汇编代码:
MOV 0x08,#tmp(0x00) ;0x08是指针pstr的存储地址
看到了吗!本来访问外ram需要2 byte来寻址64k空间,但因为使用data关键字(在"*"号前的那个),所以按KeilC编译环境来说就把他编译成指向内ram的指针变量了,这也是初学C51的朋友们不理解各个存储类型的关键字定义而造成的bug。特别是当工程中的默认的存储区类为large时,又把tmp[10] 声明为uchar tmp[10] 时,这样的bug是很隐秘的不容易被发现。
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
C51相关资源
存储器类型相关资源
51单片机相关资源
物理区域相关资源
编辑:什么鱼
本文引用地址:
本周热门资源推荐
EEWORLD独家单片机C语言之第四课 数据类型_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
单片机C语言之第四课 数据类型
上传于||文档简介
&&单​片​机​技​术
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
下载文档到电脑,查找使用更方便
还剩41页未读,继续阅读
你可能喜欢单片机原理与应用及C51程序设计(第二版)课后答案-五星文库
免费文档下载
单片机原理与应用及C51程序设计(第二版)课后答案
导读:程序执行效率高可移植性好有哪些数据类型是MCS-51单片机直接支持的?,答:MCS-51单片机直接支持的数据类型标准分为基本数据类型和组合数据类型,code:程序存储器ROM64KB空间,C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容,防止其他程序调用,!(a&b)&&!c||1结果:真!(a+b)+c-1&a,使程序继续执行switch结构后面的一个
2. 可以直接对计算机硬件进行操作 生成的目标代码质量高,程序执行效率高 可移植性好 有哪些数据类型是MCS-51单片机直接支持的?
答:MCS-51单片机直接支持的数据类型标准分为基本数据类型和组合数据类型,基本数据类型有字符型char、短整型short、整型int、长整型long、浮点型float、双精度型double、特殊功能寄存器型和位类型,其中char型与short型相同,float型与double型相同。组合数据类型有数组类型、结构体类型、共同体类型和枚举类型,另外还有指针类型和空类型。
3. C51特有的数据类型有哪些?
答:C51特有的数据类型有特殊功能寄存器型和位类型。
4. C51中的存储器类型有几种,它们分别表示的存储器区域是什么?
答:C51中的存储器类型有6种,分别如下:
data:直接寻址的片内RAM低128B,访问速度快
bdata:片内RAM的可位寻址区(20H~2FH),允许字节和位混合访问
idata:间接寻址访问的片内RAM,允许访问全部片内RAM
pdata:用Ri间接访问的片外RAM低256B
xdata:用DPTR间接访问的片外RAM,允许访问全部64KB片外RAM
code:程序存储器ROM 64KB空间
5. 在C51中,bit位与sbit位有什么区别?
答:bit位类型符用于定义一般的位变量。存储器类型只能是bdata、data、idata,只能是片内RAM的可位寻址区,严格来说只能是bdata。
sbit位类型符用于定义在可位寻址字节或特殊功能寄存器中的位,定义时需指明其位地址,可以是位直接地址,可以是可位寻址变量带位号,也可以是特殊功能寄存器名带位号。
6. 在C51中,通过绝对地址来访问的存储器有几种?
答:通过绝对地址来访问存储器有三种方法:1. 使用C51运行库中预定义宏。2. 通过指针访问。3. 使用C51扩展关键字_at_
7. 在C51中,中断函数与一般函数有什么不同?
答:中断函数在定义时后面带interrupt m修饰符,m的取值为0~31,对应的中断情况如下:0――外部中断0,1――定时/计数器T0,2――外部中断1,3――定时/计数器T1,4――串行口中断,5――定时/计数器T2,其他值预留。
编写MCS-51中断函数需要注意如下几点。
(1) 中断函数不能进行参数传递,如果中断函数中包含任何参数声明都将导致编译出错。 中断函数没有返回值。 在任何情况下都不能直接调用中断函数 如果在中断函数中调用了其他函数,则被调用函数所使用的寄存器必须与中断函数相同,否则会产生不正确的结果。 C51编译器对中断函数编译时会自动在程序开始和结束处加上相应的内容。 C51编译器从绝对地址8m+3处产生一个中断向量,其中m为中断号,也即interrupt后面的数字。该向量包含一个到中断函数入口地址的绝对跳转。 中断函数最好写在文件的尾部,并且禁止使用extern存储类型说明。防止其他程序调用。 按给定的存储类型和数据类型,写出下列变量的说明形式。 在data区定义字符变量val1。
data val1;
(2) 在idata区定义整型变量val2。
(3) 在xdata区定义无符号字符型数组val3[4]。
unsigned char xdata
(4) 在xdata区定义一个指向char类型的指针px。
(5) 定义可寻址位变量flag。
(6) 定义特殊功能寄存器变量P3。
(7) 定义特殊功能寄存器变量SCON。
SCON=0x98;
(8) 定义16位的特殊功能寄存器T0。
sfr16 T0=0x8a;
(2) 写出下列关系表达式或逻辑表达式的结果,设a=3,b=4,c=5。 a+b&c&&b= =c
结果:假 a||b+c&&b-c
!(a&b)&&!c||1
结果:真 !(a+b)+c-1&&b+c/2
结果:假 写出下列C51程序的执行结果。
#include &stdio.h&
extern serial_initial();
结果: 8 9 9
8 8 9 int x,y,z; serial_initial(); x=y=8;z=++x; printf(&\n %d %d %d&,y,z,x); x=y=8;z=x++; printf(&\n %d %d %d&,y,z,x); x=y=8;z=--x; printf(&\n %d %d %d&,y,z,x); x=y=8;z=x--; printf(&\n %d %d %d&,y,z,x); printf(&\n&); while(1);
8 7 7 8 8 7
#include &stdio.h&
extern serial_initial();main()
int x,y,z; serial_initial(); printf(&input data x,y?\n&); scanf(&%d %d&,&x,&y); printf(&\n
x&=y x!=y x==y&); printf(&\n&); printf(&\n%3d%3d&,x,y); z=x&y; z=x&=y; z=x&y; z=x&=y; z=x!=y; z=x==y; while(1);
printf(&%5d&,z); printf(&%5d&,z); printf(&%5d&,z); printf(&%5d&,z); printf(&%5d&,z); printf(&%5d&,z);
执行结果:
input data x,y?
x&=y x!=y x==y
#include &stdio.h&
extern serial_initial();
int x,y,z;
serial_initial();
printf(&input data x, y ?\n&);
scanf(&%d %d&,&x,&y);
printf(&\n
printf(&\n%3d%3d&,x,y);
printf(&%5d&,z);
printf(&%5d&,z);
printf(&%5d&,z);
printf(&\n&);printf(&\n&);
printf(&That is all\n&);
执行结果:
input data x, y ?
That is all
#include &stdio.h&
extern serial_initial();
unsigned int x,y; serial_initial(); a=b=0xaa55;x=y=0xaa55;
printf(&\n a=%4x b=%4x x=%4x y=%4x&,a,b,x,y);
a=a&&1;b=b&&1; x=x&&1;y=y&&1;
printf(&\n a=%4x b=%4x x=%4x y=%4x&,a,b,x,y);
printf(&\n&);
printf(&\n&); printf(&That is all.\n&);
执行结果:
a=aa55 b=aa55 x=aa55 y=aa55
a=54aa b=d52a x=54aa y=552a
That is all.
11. break和continue语句的区别是什么?
答:break语句可以跳出switch结构,使程序继续执行switch结构后面的一个语句。break语句还可以从循环体中跳出循环,提前结束循环而接着执行循环结构下面的语句。
continue语句用在循环结构中,用于结束本次循环,跳过循环体中continue下面尚未执行的语句,直接进行下一次是否执行循环的判定。
continue语句和break语句的区别在于:continue语句只是结束本次循环而不是终止整个循环;break语句则是结束循环,不再进行条件判断。
12. 用分支结构编程实现:输入“1”显示“A”,输入“2”显示“B”,输入“3”显示“C”,输入“4”显示“D”,输入“5”结束。
参考程序:
void main(void)
SCON=0x52;
TMOD=0x20;
//串口初始化
包含总结汇报、党团工作、资格考试、文档下载、旅游景点、办公文档、教程攻略、人文社科、IT计算机以及单片机原理与应用及C51程序设计(第二版)课后答案等内容。本文共9页
相关内容搜索

我要回帖

更多关于 c语言变量存储类型 的文章

 

随机推荐