“Keil C51”下如何让编译器优先使用片内“RAM”?

作者&投稿:戎叙 (若有异议请与网页底部的电邮联系)
~ C51内存结构深度剖析\x0d\x0a在编写应用程序时,定义一个变量,一个数组,或是说一个固定表格,到底存储在什么地方;当定义变量大小超过MCU的内存范围时怎么办;如何控制变量定义不超过存储范围;以及如何定义变量才能使得变量访问速度最快,写出的程序运行效率最高。以下将一一解答。\x0d\x0a\x0d\x0a1 六类关键字(六类存储类型)\x0d\x0adata idata xdata pdata code bdata\x0d\x0a\x0d\x0a code: code memory (程序存储器也即只读存储器)用来保存常量或是程序。code memory 采用16位地址线编码,可以是在片内,或是片外,大小被限制在64KB\x0d\x0a 作用:定义常量,如八段数码表或是编程使用的常,在定义时加上code 或明确指明定义的常量保存到code memory(只读)\x0d\x0a 使用方法:\x0d\x0a char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};\x0d\x0a 此关键字的使用方法等同于const\x0d\x0a\x0d\x0adata data memory (数据存储区)只能用于声明变量,不能用来声明函数,该区域位于片内,采用8位地址线编码,具有最快的存储速度,但是数量被限制在128byte或更少。\x0d\x0a 使用方法:\x0d\x0a unsigned char data fast_variable=0;\x0d\x0a\x0d\x0a idata idata memory(数据存储区)只能用于声明变量,不能用来声明函数. 该区域位于片内,采用8位地址线编码,内存大小被限制在256byte或更少。该区域的低地址区与data memory地址一致;高地址区域是52系列在51系列基础上扩展的并与特殊功能寄存器具有相同地址编码的区域。即:data memory是idata memory的一个子集。\x0d\x0a \x0d\x0a xdata xdata memory 只能用于声明变量,不能用来声明函数,该区域位于MCU\x0d\x0a 外部,采用16位地址线进行编码,存储大小被限制在64KB以内。\x0d\x0a 使用方法:\x0d\x0a unsigned char xdata count=0;\x0d\x0a\x0d\x0apdata pdata memory 只能用于声明变量,不能用来声明函数,该区域位于MCU外部,采用8位地址线进行编码。存储大小限制在256byte. 是xdata memory的低256byte。为其子集。\x0d\x0a 使用方法\x0d\x0a unsigned char pdata count=0;\x0d\x0a\x0d\x0a bdata bdata memory 只能用于声明变量,不能用来声明函数。该区域位于8051内部位数据地址。定义的量保存在内部位地址空间,可用位指令直接读写。\x0d\x0a 使用方法:\x0d\x0a unsigned char bdata varab=0\x0d\x0a\x0d\x0a 注:有些资料讲,定义字符型变量时,在缺省unsigned 时,字符型变量,默认为无符号,与标准C不同,但我在Keil uVision3中测试的时候发现并非如此。在缺省的情况下默认为有符号。或许在以前的编译器是默认为无符号。所以看到有的资料上面这样讲的时候,要注意一下,不同的编译器或许不同。所以我们在写程序的时候,还是乖乖的把unsigned signed 加上,咱也别偷这个懒。\x0d\x0a 2函数的参数和局部变量的存储模式\x0d\x0a C51 编译器允许采用三种存储器模式:SMALL,COMPACT 和LARGE。一个函数的存储器模式确定了函数的参数的局部变量在内存中的地址空间。处于SMALL模式下的函数参数和局部变量位于8051单片机内部RAM中,处于COMPACT和LARGE模式下的函数参数和局部变量则使用单片机外部RAM。在定义一个函数时可以明确指定该函数的存储器模式。方法是在形参表列的后面加上一存储模式。\x0d\x0a \x0d\x0a 示例如下:\x0d\x0a #pragma large //此预编译必须放在所有头文前面\x0d\x0a int func0(char x,y) small;\x0d\x0a char func1(int x) large;\x0d\x0a int func2(char x);\x0d\x0a 注:\x0d\x0a 上面例子在第一行用了一个预编译命令#pragma 它的意思是告诉c51编译器在对程序进行编译时,按该预编译命令后面给出的编译控制指令LARGE进行编译,即本例程序编译时的默认存储模式为LARGE.随后定义了三个函数,第一个定义为SMALL存储模式,第二个函数定义为LARGE第三个函数未指定,在用C51进行编译时,只有最后一个函数按LARGE存储器模式处理,其它则分别按它们各自指定的存储器模式处理。\x0d\x0a 本例说明,C51编译器允许采用所谓的存储器混合模式,即允许在一个程序中将一些函数使用一种存储模式,而其它一些则按另一种存储器模式,采用存储器混合模式编程,可以充分利用8051系列单片机中有限的存储器空间,同时还可以加快程序的执行速度。\x0d\x0a\x0d\x0a3绝对地址访问 absacc.h(相当重要)\x0d\x0a\x0d\x0a#define CBYTE ((unsigned char volatile code *) 0)\x0d\x0a#define DBYTE ((unsigned char volatile data *) 0)\x0d\x0a#define PBYTE ((unsigned char volatile pdata *) 0)\x0d\x0a#define XBYTE ((unsigned char volatile xdata *) 0)\x0d\x0a 功能:CBYTE 寻址 CODE区\x0d\x0a DBYTE 寻址 DATA区\x0d\x0a PBYTE 寻址 XDATA(低256)区\x0d\x0a XBYTE 寻址 XDATA区\x0d\x0a 例: 如下指令在对外部存储器区域访问地址0x1000\x0d\x0a xvar=XBYTE[0x1000];\x0d\x0a XBYTE[0x1000]=20;\x0d\x0a\x0d\x0a#define CWORD ((unsigned int volatile code *) 0)\x0d\x0a#define DWORD ((unsigned int volatile data *) 0)\x0d\x0a#define PWORD ((unsigned int volatile pdata *) 0)\x0d\x0a#define XWORD ((unsigned int volatile xdata *) 0)\x0d\x0a\x0d\x0a 功能:与前面的一个宏相似,只是它们指定的数据类型为unsigned int .。\x0d\x0a 通过灵活运用不同的数据类型,所有的8051地址空间都是可以进行访问。\x0d\x0a 如\x0d\x0aDWORD[0x0004]=0x12F8;\x0d\x0a即内部数据存储器中(0x08)=0x12; (0x09)=0xF8\x0d\x0a\x0d\x0a注:用以上八个函数,可以完成对单片机内部任意ROM和RAM进行访问,非常方便。还有一种方法,那就是用指钟,后面会对C51的指针有详细的介绍。\x0d\x0a\x0d\x0a4寄存器变量(register)\x0d\x0a 为了提高程序的执行效率,C语言允许将一些频率最高的那些变量,定义为能够直接使用硬件寄存器的所谓的寄存器变量。定义一个变量时,在变量类型名前冠以“register” 即将该变量定义成为了寄存器变量。寄存器变量可以认为是一自动变量的一种。有效作用范围也自动变量相同。由于计算机寄存器中寄存器是有限的。不能将所有变量都定义成为寄存器变量,通常在程序中定义寄存器变量时,只是给编译器一个建议,该变量是否真正成为寄存器变量,要由编译器根据实际情况来确定。另一方面,C51编译器能够识别程序中使用频率最高的变量,在可能的情况下,即使程序中并未将该变量定义为寄存器变量,编译器也会自动将其作为寄存器变量处理。被定义的变量是否真正能成为寄存器变量,最终是由编译器决定的。\x0d\x0a\x0d\x0a5内存访问杂谈\x0d\x0a 1指钟\x0d\x0a指钟本身是一个变量,其中存放的内容是变量的地址,也即特定的数据。8051的地址是16位的,所以指针变量本身占用两个存储单元。指针的说明与变量的说明类似,仅在指针名前加上“*”即可。\x0d\x0a 如 int *int_point; 声明一个整型指针\x0d\x0a char *char_point; 声明一个字符型指针\x0d\x0a 利用指针可以间接存取变量。实现这一点要用到两个特殊运算符\x0d\x0a & 取变量地址\x0d\x0a * 取指针指向单元的数据\x0d\x0a\x0d\x0a示例一:\x0d\x0aint a,b;\x0d\x0a int *int_point; //定义一个指向整型变量的指针\x0d\x0a a=15;\x0d\x0a int_point=&a; //int_point指向 a\x0d\x0a *int_point=5; //给int_point指向的变量a 赋值5 等同于a=5; \x0d\x0a示例二:\x0d\x0a char i,table[6],*char_point;\x0d\x0a char_point=table;\x0d\x0a for(i=0;i<6;i++)\x0d\x0a {\x0d\x0a char_point=i;\x0d\x0a char_point++;\x0d\x0a}\x0d\x0a注:\x0d\x0a 指针可以进行运算,它可以与整数进行加减运算(移动指针)。但要注意,移动指针后,其地址的增减量是随指针类型而异的,如,浮点指针进行自增后,其内部将在原有的基础上加4,而字符指针当进生自增的时候,其内容将加1。原因是浮点数,占4个内存单元,而字符占一个字节。\x0d\x0a\x0d\x0a宏晶科技最新一代STC12C5A360S2系列,每一个单片机出厂时都有全球唯一身份证号码(ID号),用户可以在单片机上电后读取内部RAM单元F1H~F7H的数值,来获取此单片机的唯一身份证号码。使用MOV @Ri 指令来读取。下面介绍C51 获取方法:\x0d\x0a char id[7]={0};\x0d\x0a char i;\x0d\x0a char idata *point;\x0d\x0a for(i=0;i<7;i++)\x0d\x0a {\x0d\x0a id[i]=*point;\x0d\x0a point++;\x0d\x0a}\x0d\x0a \x0d\x0a(此处只是对指针做一个小的介绍,达到访问内部任何空间的方式,后述有对指针使用的详细介绍)\x0d\x0a2对SFR,RAM ,ROM的直接存取\x0d\x0aC51提供了一组可以直接对其操作的扩展函数\x0d\x0a若源程序中,用#include包含头文件,io51.h 后,就可以在扩展函数中使用特殊功能寄存器的地址名,以增强程序的可读性:\x0d\x0a\x0d\x0a 注 此方法对SFR,RAM,ROM的直接存取不建议使用.因为,淡io51.h这个头文件在KEIL中无法打开,可用指针,或是采用absacc.h头文件,


渝北区15233697469: keil如何编译C++语言 -
乐正幸结核: 跟C一样用,只不过所有源码文件使用.cpp后缀,Keil就会自动调用C++编译器了

渝北区15233697469: Keil C51下如何让编译器优先使用片内RAM
乐正幸结核: 改Memory Mode为Small,这样分配的变量默认都在片内.Compact和Large都会把变量分配到片外的. 之后再调试,有什么错误继续贴出来.

渝北区15233697469: 假设Keil C51编译器路径已列入系统路径中,将当前目录下的C51源文档myfile.c编译为目标文件的控制台基本操
乐正幸结核: c51 myfile.c --------------------------------- C51是C语言编译器,其使用方法为: C51 sourcefile[编译控制指令] 或者 C51 @ commandfile 其中sourcefile为C源文件(.C).大量的编译控制指令完成C51编译器的全部功能.包控C51输出文件C.LST,.OBJ,.I和.SRC文件的控制.源文件(.C)的控制等,详见第五部分的具体介绍. 而Commandfile为一个连接控制文件其内容包括:.C源文件及各编译控制指令,它没有固定的名字,开发人员可根据自己的习惯指定,它适于用控制指令较多的场合.

渝北区15233697469: 怎么样使用keil软件 -
乐正幸结核: KeilC51的安装和使用说明1) Keil C51软件的安装 系统要求: 安装Keil C51集成开发软件,必须满足一定的硬件和软件要求,才能确保编译器以及其他程序功能正常,必须具有:Pentium、Pentium-II或兼容处理器的PC;Windows95、Windows98...

渝北区15233697469: eclipse 怎么编译keil工程 -
乐正幸结核: 1. 把KeilBuilder.exe复制到MDK的编译器目录下, 一般为: C:\Keil\ARM\BIN40下, 这要看你的MDK安装在哪了. 2. 新建一个C Project 工程, 并选择Cross GCC交叉编译工具为本工程编译工具. .通过菜单File -> new -> C Project 新建一个空的C...

渝北区15233697469: 怎么用keil写汇编程序并且下载到51单片机中去,我试了但硬件没反应,求详细过程? -
乐正幸结核: Keil写汇编程序与写c程序差不多,写一个汇编程序步骤如下.一,运行keil,建一个工程.二,新建一个文件,另存为后缀为asm的汇编文件.三,将这个文件载入刚建的工程.四,现在可以录入代码了.五,录入完成后编译调试直到没有错误和警告,生成HEX文件.六,将HEX文件下载到单片机,运行看效果.七,修改软件直到达到预期效果.

渝北区15233697469: 易语言怎么调用c语言编译器来运行程序代码 ! 急!谢谢回答者!说详细些
乐正幸结核: 如果易语言编译器容许您,那么就是可以的,例如keilc51编译器和常用调试arm裸机程序,是可以在c语言语句中加入汇编语言. 由于本人不了解易语言,无法确定其编译器是否可以编译c,但估计是不行. 那么说回来,如果这样,程序就没法...

渝北区15233697469: 如何使用Keil c51 -
乐正幸结核: 在target上点右键有个options for target“”,然后选择output项,有个create hex,把前面的勾点上,确定.工具栏上有一个双箭头朝下的图标(rebuild all target files),还有一个单箭头朝下的图标(build target),点哪个都可以,就编译并生成文件了,

渝北区15233697469: 请问如何把keil c 当作工具添加到silicon labs IDE里那? 请大虾指教!
乐正幸结核: 在silicon IDE 的Project下面Tool Chain Integration 打开,出现一个定义界面.在这个界面选择,tool 为keil ;选择Assembler 指向你安装keil安装子目录里的A51.exe;Compiler 指向C51.exe;Linker指向BL51.exe.如:E:\Keil\C51\BIN\A51.EXE ;E:\Keil\C51\BIN\C51.exe; E:\Keil\C51\BIN\BL51.EXE然后检查 Command line flags ,这个是你的编译连接选项,一般你可以直接用默认值.按下ok 就是用KEIL C51编译连接器了.

渝北区15233697469: keil c51使用 -
乐正幸结核: 1.可以的,使用At89系列的单片机代替就可以.2.不可以,用AT89系列的代替就可以.指令上完全兼容. 其实完全没有必要,因为针对某个MCU来说,不同仅仅是编译包文件和寄存器头文件的不同(C51 Compiler package),STC的单片机与51单片机硬件和指令完全兼容,显然没有这个必要.直接用51的就行了!

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网