51单片机C语言编程之内存优化

发布者:EtherealLight最新更新时间:2016-02-25 来源: eefocus关键字:51单片机  C语言编程  内存优化 手机看文章 扫描二维码
随时随地手机看文章
最常见的是以下两种

① 超过变量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 空间,虽然全局变量的分配经过精心计算没有超出使用范围,仍会产生内存溢出的错误!

    而编译器是否能成功的优化变量是根据代码来的
    上面的代码中,循环是臃肿的,变量 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单片机  C语言编程  内存优化 引用地址:51单片机C语言编程之内存优化

上一篇:单片机rs232串口通信完美解析
下一篇:51单片机复位电路介绍

推荐阅读最新更新时间:2024-03-16 14:45

单片机串行口介绍,8051单片机的通信方式
串行口是单片机与外界进行信息交换的工具,8051单片机的通信方式有两种: 并行通信:数据的各位同时发送或接收。 串行通信:数据一位一位次序发送或接收。 串行通信的方式 异步通信 用一个起始位0表示字符的开始,用停止位1表示字符的结束,中间夹着8个数据位,字符能一个接一个传送 CPU与外设之间必须有字符格式和波特率两项规定 字符格式规定能使双方把0和1串理解成同一种意义,原则上自由制定,通用角度使用标准如ASCII 波特率即数据传输速率,每秒传送的二进制位数,如120字符/s,每个字符10数位,则传送波特率为1200波特 同步通信 去掉了开始结束标志提高速度,但由于数据块传递开始要用同步字符来指示,同时要求由时钟来实现发送端
[单片机]
单片机串行口介绍,80<font color='red'>51单片机</font>的通信方式
mcs-51单片机LED显示程序设计
入口:把要显示的数分别放在显示缓冲区60H-65H共6个单元中,并且分别对应各个数码管LED0-LED5。 出口:将预置在显示缓冲区中的6个数成对应的显示字形码,然后输出到数码管显示器中显示。 单片机led显示程序如下: DISP: MOV SCON,#00H ;初始化串行口方式0 MOV R1,#06H ;显示6位数 MOV R0,#65H ;60H-65H为显示缓冲区 MOV DPTR,#SEGTAB ;字形表的入口地址 LOOP: MOV A,@R0 ;取最高位的待显示数据 MOVC A,@A+DPTR ;查表获取字形码 MOV SBUF,A ;送串行口显示 DELAY: JNB TI,DELAY ;等
[单片机]
51单片机控制的LED流水灯设计
  1.引言   当今时代是一个新技术层出不穷的时代,在电子领域尤其是自动化智能控制领域,传统的分立元件或数字逻辑电路构成的控制系统,正以前所未见的速度被单片机智能控制系统所取代。单片机具有体积小、功能强、成本低、应用面广等优点,可以说,智能控制与自动控制的核心就是单片机。目前,一个学习与应用单片机的高潮正在工厂、学校及企事业单位大规模地兴起。学习单片机的最有效方法就是理论与实践并重,本文笔者用AT89C51单片机自制了一款简易的流水灯,重点介绍了其软件编程方法,以期给单片机初学者以启发,更快地成为单片机领域的优秀人才。   2.硬件组成   按照单片机系统扩展与系统配置状况,单片机应用系统可分为最小系统、最小功耗系统及典型系
[单片机]
用<font color='red'>51单片机</font>控制的LED流水灯设计
基于51单片机的万年历(算法实现)
基于51单片机的万年历,用到了单片机独立键盘、数码管、LED灯模块实现。 想要简单还是DS1302好用。 1 /************************************************** 2 3 作者:纟彖氵戋 博客:http://www.cnblogs.com/yllinux/ 4 5 时间:2017年6月7日 6 7 目标:利用单片机独立键盘、数码管、LED灯模块实现万年历(算法实现) 8 9 ***************************************************/ 10 #include reg52.h 11 #de
[单片机]
如何用51单片机实现交通信号灯
实验环境 软件: Keil5+Proteus7 元件(主要): AT89C51 * 1, BUTTON * 1, 7SEG-MPX2-CA * 1, LED-GREEN * 8, LED-RED * 4, LED-YELLOW * 4 实验原理 7SEG-MPX2-CA数码管 7SEG-MPX2-CA数码管是一个两位数的阳极数码管,有10个针脚,通过标号a-dp八个针脚控制,LED灯的显示,通过标号为1,2的针脚控制显示的是个位或是十位的数码管。 要通过数码管显示具体数字,7SEG-MPX2-CA由于是一个阳极的数码管,所以需要接收在针脚上接收相应的低电平来显示,如如果要显示数字0,则标号a-dp的针脚需要接收1100 0000也
[单片机]
AT89S51单片机实验系统的开发与应用
目前单片机应用已渗透到各个领域,单片机技术的发展也因此日新月异。作为实践性很强的应用型学科,单片机研发及教学离不开实验。传统的单片机实验系统需要频繁拔插烧写单片机芯片来编程,依赖于仿真机调试,实验成本高且效率低,已不适应现代科技开发需求。如何充分合理利用单片机的性能,方便用户高效学习与开发产品成为当前的研究热点。 单片机在电子产品中的应用已经越来越广泛,并且在很多学校也开设了相关的课程。通过对在校学生的调查,以及网络上收集到资料的综合分析,得知:目前无论是社会上还是在校学生,学习单片机的人数呈不断增加之势,对于单片机实验板的需求也不断增加。但是由于目前多数实验板价钱较高,实验项目不适于初学者学习。所以,开发出一套价格低廉,易
[单片机]
AT89S<font color='red'>51单片机</font>实验系统的开发与应用
51单片机控制RTL8019AS实现以太网通讯
摘要:介绍以太网的帧协议和以太网控制芯片RTL8019AS的结构特性;介绍51单片机控制RTL8019AS实现以太网通讯的硬件设计方案;采用C51语言实现ARP协议(地址解析协议),并进行了系统的调试与验证。 关键词:RTL8019AS Ethernet 51单片机 TCP/IP协议 互联网络硬件、软件的迅猛发展,使得网络用户呈指数增长,在使用计算机进行网络互联的同时,各种家电设备、仪器仪表以及工业生产中的数据采集与控制设备在逐步地走向网络化,以便共享网络中庞大的信息资源。在电子设备日趋网络化的背景下,利用廉价的51单片机来控制RTL8019AS实现以太网通讯具有十分重要的意义。 1 以太网(Ethernet)协议 一个标
[工业控制]
基于51单片机的电子钟闹钟温度显示设计
仿真图proteus7.8及以上 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:S0057 1.主要功能: 基于51单片机AT89C51/52(与AT89S51/52、AT89C51/52、STC89C51/52等51内核单片机通用) 1、通过DS18B20检测环境温度。 2、能通过LCD1602显示年月日时分秒和温度。 3、有整点报时和闹钟功能。 4、具有高低温报警功能,上下限值可调,蜂鸣器提醒。 5、可以通过按键调整年月日时分秒和闹钟功能,具有闰年判断,自动计算星期功能。 需注意仿真中51单片机芯片是兼容的,AT89C51,AT89C52是51单片机的具体型号,内核是一样的。相同的原理图里,无论stc还是
[单片机]
基于<font color='red'>51单片机</font>的电子钟闹钟温度显示设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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