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

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

C51内存结构深度剖析\x0d\x0a在编写应用程序时,定义一个变量,一个数组,或是说一个固定表格,到底存储在什么地方;当定义变量大小超过MCU的内存范围时怎么办;如何控制变量定义不超过存储范围;以及如何定义变量才能使得变量访问速度最快,写出的程序运行效率最高。以下将一一解答。\x0d\x0a\x0d\x0a1 六类关键字(六类存储类型)\x0d\x0adata idata xdata pdata code bdata\x0d\x0a\x0d\x0acode: 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\x0achar func1(int x) large\x0d\x0aint 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\x0aDBYTE 寻址DATA区\x0d\x0aPBYTE 寻址XDATA(低256)区\x0d\x0aXBYTE 寻址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=0i 回答于 2023-01-06 华为Mate50 Pro曲面旗舰手机 ¥6799 苹果 AirPods Pro 2代 ¥1699 索尼65英寸4K HDR专业游戏电视 ¥7499 惠普战66五代15.6英寸轻薄本 ¥4399 查看更多

STM32F1_外部SRAM作为运行内存:

http://blog.csdn.net/ybhuangfugui/article/details/51477977

Keil系列教程:

http://blog.csdn.net/column/details/13472.html


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12199323.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存