开发上位机的人转而作嵌入式容易犯下“财大气粗”大手大脚“花钱”的毛病,毕竟嵌入式开发尤其是单片机,单片机的各个数据空间都是非常有限的,尤其程序存储器(当然,对于新手来说这个存储区域往往用得很少),默认的程序代码中所定义的变量包括函数中使用的变量(只要是没有显式声明的变量)都会存储在数据存储器中。
要知道,51单片的片内存储器空间为256字节,地址从0000H—00FFH(也就是我们俗称"双F”区)
所以,当遇到大量声明变量时,就会遇到溢出,如下图:

在这里插入图片描述
我们甚至还会遇到程序增加一个变量就会出错,而且就是出现上面的错误,去掉新增的变量程序就不报错,那么,问题就是你声明的变量超过数据存储器的容量了!!!

数据类型字节值的范围
char81-128~127
unsigned char810~255
enum162-32768~32767
short162-32768~32767
unsigned short1620~65535
int162-32768~32767
unsigned int1620~65535
long324-2147483648~2147483647
unsigned long3240~4294967295
float324±1.175494e-38~±3.402823e+38
bit10,1
sbit10,1
sfr810~255
sfr161620~65535

从上表我们可以看出,256个字节真的很贫穷,几个长一点的数组就给占用完了(4个16个元素的float就干爆了),还不用说程序中用到的左一个右一个变量。
要命的是256个字节还不是全都能够给你用的,它们还得再分为两个部分:
其中:低128字节,00H—7FH,是真正的RAM区,这部分你可以随便用。
另一部分为高128字节,80H—FFH,为特殊功能寄存器区,不是你随便可以使用的。

所以,我们常常会在编译的时候得到有关低位128字节的使用报告:
在这里插入图片描述
当这里的data超过了128了,自然就发生了上面的错误。把他们存储到片外或者程序存储区都可以。观察报告我们可以发现xdata=0,code=758,这些里面都是很大的潜力的(一般程序存储区就是我们说的“三F”区,有4K的存储空间),我们可以通过加关键字code或者xdata很轻松解决这个问题,比如,使用xdata后报告中就会出现xdata使用的量:
在这里插入图片描述
很明显,把data的130个字节,移动了84到xdata里,于是data=46了!

既然知道了根源,那么解决的方法有两个:
1、将部分声明的不需要修改的变量声明为程序存储器变量,即在变量名前增加code关键字,如:

unsigned char code  led_mod[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

当然,我们也可以使用关键字xdata将数据存储到片外存储器中去(如果我们不加任何关键字,就相当于默认使用了data关键字,也就是默认使用的是片内数据存储器)

2、修改存储器模式
对于代码行数比较多,程序运行空间需求大的程序,可能也会出现内存溢出的错误。但这个不是数据存储器的问题,而是程序存储器问题。程序存储器是用来供编译器控制指令small,compact和large指定编译时的存储器模式。
在这里插入图片描述
上图的code rom是设置程序存储器的,显而易见,存储模式修改了,那么程序存储器空间的大小自然会被修改,默认的是small模式,也就是只有前面提到的0FFFH的区域,4K的大小。修改为compact或者large则可以访问的是FFFFH的64K区域了。
Memory Model是设置数据存储器的
使用Small的模式:变量默认存储在片内128个字节的数据存储器内,但变量并就是不可以存储在片外,一样可以存储在片外,但需要你显式的指定(xdata),如:
small模式:
unsigned char xdata a;那么变量a就存储在片外的ram。
unsigned char seg;变量存储在片内ram。
Large的模式:
unsigned char xdata seg;那么变量a就存储在片外的ram。
unsigned char seg;变量存储在片外ram。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐