浅谈51单片机内存优化

发布者:雅致人生最新更新时间:2013-05-08 来源: 21ic关键字:51单片机  内存优化  编译器 手机看文章 扫描二维码
随时随地手机看文章

对 51 单片机内存的认识,很多人有误解,最常见的是以下两种:

① 超过变量128后必须使用compact模式编译

实际的情况是只要内存占用量不超过 256.0 就可以用 small 模式编译

② 128以上的某些地址为特殊寄存器使用,不能给程序用

与 PC 机不同,51 单片机不使用线性编址,特殊寄存器与 RAM 使用重复的重复的地址。但访问时采用不同的指令,所以并不会占用 RAM 空间。

由于内存比较小,一般要进行内存优化,尽量提高内存的使用效率。

以 Keil C 编译器为例,small 模式下未指存储类型的变量默认为data型,即直接寻址,只能访问低 128 个字节,但这 128 个字节也不是全为我们的程序所用,寄存器 R0-R7必须映射到低RAM,要占去 8 个字节,如果使用寄存组切换,占用的更多。

所以可以使用 data 区最大为 120 字节,超出 120 个字节则必须用 idata 显式的指定为间接寻址,另外堆栈至少要占用一个字节,所以极限情况下可以定义的变量可占 247 个字节。当然,实际应用中堆栈为一个字节肯定是不够用的,但如果嵌套调用层数不深,有十几个字节也够有了。

为了验上面的观点,写了个例子

#define LEN 120

data UCHAR tt1[LEN];

idata UCHAR tt2[127];

void main()

{

UCHAR i,j;

for(i = 0; i < LEN; ++i )

{

j = i;

tt1[j] = 0x55;

}

}

可以计算 R0-7(8) + tt1(120) + tt2(127) + SP(1) 总共 256 个字节

keil 编译的结果如下:

Program Size: data=256.0 xdata=0 code=30

creating hex file from "./Debug/Test"...

"./Debug/Test" - 0 Error(s), 0 Warning(s).

(测试环境为 XP + Keil C 7.5)

这段代码已经达到了内存分配的极限,再定义任何全局变量或将数组加大,编译都会报错 107

这里要引出一个问题:为什么变量 i、j 不计算在内?

这是因为 i、j 是局部变量,编译器会试着将其优化到寄存器 Rx 或栈。问题也就在这了,如果局部变量过多或定义了局部数组,编译器无法将其优化,就必须使用 RAM 空间,虽然全局变量的分配经过精心计算没有超出使用范围,仍会产生内存溢出的错误!

而编译器是否能成功的优化变量是根据代码来的[page]

上面的代码中,循环是臃肿的,变量 j 完全不必要,那么将代码改成

UCHAR i;

UCHAR j;

for(i = 0; i < LEN; ++i )

{

tt1[i] = 0x55;

}

再编译看看,出错了吧!

因为编译器不知道该如何使用 j,所以没能优化,j 须占 RAM 空间,RAM 就溢出了。

(智能一点的编译器会自动将这个无用的变量去掉,但这个不在讨论之列了)

另外,对 idata 的定义的变量最好放在 data 变量之后

对于这一种定义

uchar c1;

idata uchar c2;

uchar c3;

变量 c2 肯定会以间接寻址,但它有可能落在 data 区域,就浪费了一个可直接寻址的空间

变量优化一般要注意几点:

①让尽可能多的变量使用直接寻址,提高速度

假如有两个单字节的变量,一个长119的字符型数组

因为总长超过 120 字节,不可能都定义在 data 区

按这条原则,定义的方式如下:

data UCHAR tab[119];

data UCAHR c1;

idata UCHaR c2;

但也不是绝的,如果 c1, c2 需要以极高的频率访问,而 tab 访问不那么频繁

则应该让访问量大的变量使用直接寻址:

data UCAHR c1;

data UCHaR c2;

idata UCHAR tab[119];

这个是要根据具体项目需求来确定的

②提高内存的重复利用率

就是尽可能的利用局部变量,局部变量还有个好处是访问速度比较快

由前面的例子可以看出,局部变量 i, j 是没有单独占用内存的

子程序中使用内存数目不大的变量尽量定义为局部变量

③对于指针数组的定义,尽可能指明存储类型

尽量使用无符号类型变量

一般指针需要一个字节额外的字节指明存储类型

8051 系列本身不支持符号数,需要外加库来处理符号数,一是大大降低程序运行效率,二是需要额外的内存

④避免出现内存空洞

可以通过查看编译器输出符号表文件(.M51)查看

对前面的代码,M51文件中关于内存一节如下:

* * * * * * * D A T A M E M O R Y * * * * * * *

REG 0000H 0008H ABSOLUTE "REG BANK 0"

DATA 0008H 0078H UNIT ?DT?TEST

IDATA 0080H 007FH UNIT ?ID?TEST

IDATA 00FFH 0001H UNIT ?STACK

第一行显示寄存器组0从地址0000H开始,占用0008H个字节

第二行显示DATA区变量从0008H开始,占用0078H个字节

第三行显示IDATA区变量从0080H开始,占用007F个字节

第四行显示堆栈从00FFH开始,占0001H个字节

由于前面代码中变量定义比较简单,且连续用完了所有空间,所以这里显示比较简单

变量定义较多时,这里会有很多行

如果全局变量与局部变量分配不合理,就有可能出现类似下面的行

0010H 0012H *** GAP ***

该行表示从0010H开始连续0012H个字节未充分利用或根本未用到

出现这种情况最常见的原因是局变量太多、多个子程序中的局部变量数目差异太大、使用了寄存器切换但未充分利用。

关键字:51单片机  内存优化  编译器 引用地址:浅谈51单片机内存优化

上一篇:MCS-51单片机输入输出端口(I/O口)
下一篇:51单片机上拉电阻

推荐阅读最新更新时间:2024-03-16 13:23

89c51单片机控制两个步进电机正反转加减速
序有详细注释。 仿真原理图如下 单片机源程序如下: /******************************************************************************* * 实 验 名: 步进电机实验 * 使用的IO: 电机用P1口,键盘使用P2.0、P2.1、P2.2、P2.3、P2.4、P2.5 * 按键功能:K1;正转 K2;反转 K3;低速转动 K4;高速转动 K5:电机切换 K6;停止 * 实验效果: 按下K1键,顺时针转,按下K2键,逆时针转,按下K3键,低速,按下K4键,高速。 按下K5键,转动的电机停止,并切换到控制另一个电机 按下K6键,转动的电机停止
[单片机]
89c<font color='red'>51单片机</font>控制两个步进电机正反转加减速
基于8051单片机的频率测量技术
0引言 随着无线电技术的发展与普及,"频率"已经成为广大群众所熟悉的物理量。而单片机的出现,更是对包括测频在内的各种测量技术带来了许多重大的飞跃,然而,小体积、价廉、功能强等优势也在电子领域占有非常重要的地位。为此.本文给出了一种以单片机为核心的频率测量系统的设计方法。 1 测频系统的硬件结构 测量频率的方法一般分为无源测频法、有源测频法及电子计数法三种。无源测频法(又可分为谐振法和电桥法),常用于频率粗测,精度在1%左右。有源比较法可分为拍频法和差频法,前者是利用两个信号线性叠加以产生拍频现象,再通过检测零拍现象进行测频,常用于低频测量,误差在零点几Hz;后者则利用两个非线性信号叠加来产生差频现象,然后通过检测零差现象进行
[单片机]
基于80<font color='red'>51单片机</font>的频率测量技术
51单片机电子日历(可调整 带温度)DS1302时钟+12864LCD显示
可按照程序接线 51单片机显示时间(可调整)(DS1302时钟+12864LCD显示) 仿真原理图如下: 单片机源程序如下: /****************************************/ /* 带温度显示的电子日历 */ /****************************************/ #include reg51.h #include intrins.h #include string.h #define uchar unsigned char #define uint unsigned int sbit DQ=P2^7; sbit CS1=P2^1;
[单片机]
<font color='red'>51单片机</font>电子日历(可调整 带温度)DS1302时钟+12864LCD显示
51单片机的cpu主要由什么组成_51单片机的字长是多少
  51单片机的cpu主要由什么组成   51单片机的cpu主要组成部分有中央处理器( CPU )、内部数据存储器( RAM)、内部程序存储器( ROM)、定时器/计数器、并行I/0口、口、中断控制系统、定时与控制部件。   单片机是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到-块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。  
[单片机]
怎么去设计一种基于51单片机的便携式恒温箱
一、功能简介 本项目使用Proteus8.12仿真51单片机控制器,使用报警模块、LCD1602显示模块、DS18B20温度模块、加热制冷模块、按键模块、HC05蓝牙模块等。 主要功能: 系统运行后,LCD1602显示传感器检测的温度值; 可通过按键K3设置恒定温度,K1和K2进行加减调节,恒定温度范围是0-10,设定好后可再次按下K3保存。系统会根据当前温度与目标温度比对,通过PID算法控制加热或制冷工作。若温度高于报警上限或低于报警下限值则蜂鸣器报警。检测温度会实时将数据通过串口传输到手机终端显示。 主要功能如下: (1)温度实时检测; (2)LCD1602液晶显示; (3)手机终端显示; (4
[单片机]
怎么去设计一种基于<font color='red'>51单片机</font>的便携式恒温箱
基于51单片机的温度湿度采集系统
实现功能: 1、对温度、湿度进行采集 2、可以警报提示、修改温度、湿度上下限值 3、lcd显示相关信息 原理图: 部分程序: #include reg52.h #define uint unsigned int #define uchar unsigned char #include intrins.h typedef bit BOOL ; sbit io = P1^1 ;//(口线定义) sbit bee=P1^0; sbit rs = P2^5 ; sbit rw = P2^6 ; sbit ep = P2^7 ; bit flag_300ms ; sbit K1=P1^2; sbit K2=P1^3;
[单片机]
51单片机基础之继电器
继电器:简单的说继电器就是小电流、小电压控制大电流、大电压。这就是常见的继电器,这个是一路的。 工作参数:这里的控制端输入电压最少需要5V,最大24V,以及相应参数可见。 接线:有两种方式,一种是常开,另一种是常闭。 触发方式:有高电平触发,还有低电平触发方式。继电器上面有跳线帽,可以自己换。 注意:上面说了继电器是小电流小电压控制大电压大电流,所以就必须接两个电源,一端接的是继电器输入,另一端就是大电流大电压负载端,我们需要通过控制引脚来让负载工作或者停止工作。 如图:按照这个图连线,按照需要自己选择常开还是常闭。 说明:我使用的单片机是有多个电源的,所以我用一个单片机,实现了两个电源端。 这个是效果:
[单片机]
<font color='red'>51单片机</font>基础之继电器
基于89C51单片机的环境噪声测量仪
   1 引 言      环境噪声监测,是人类提高生活质量,加强环境保护的一个重要环节,在各大城市的繁华街区和居民区,已有大型环境噪声显示器竖立街头。但目前国内的便携式噪声测试仪,多为价格昂贵的进口专用设备,除卫生、计量等环保专业部门拥有外,无法作为民用品推广普及。本文介绍一种以89C51单片机为核心,采用V/F转换技术构成的低成本、便携式数字显示环境噪声测量仪。该仪器工作稳定、性能良好,经校验定标后能满足一般民用需要,可广泛应用于工矿企业、机关、学校等需要对环境噪声进行测量和控制的场合。 2 声压级的测量机理   人耳的听阈一般是20μPa,痛阈一般是200 Pa,其间相差107倍,这样宽广的声压范围很不易测量,
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved