keil c51编译器的一些使用心得

发布者:灵感之翼最新更新时间:2016-11-22 来源: eefocus关键字:keil  c51  编译器  使用心得 手机看文章 扫描二维码
随时随地手机看文章

现在的存储器已经不像七八年前那样昂贵了,但是ram相对于rom和eeprom的价格还是不可同样看待的,所以程序中节省内存在现在看来还是非常关键的。原因有以下几点:

1.ram的存取速度相对于eeprom的存取速度要快很多倍,不在一个数量级上,主要是因为eeprom的存储要想写入就必须先擦除,而且eeprom的擦出需要成块擦除(这是由于eeprom的擦除原理是场效应管的栅极上电擦除的,为了节省成本厂家一般都是8Bytes/page 64Bytes/page),所以使用ram来处理中间的数据是能够符合速度要求的。

2.无论是xram还是eeprom都是外部存储器,在负值时都要用到16bit地址空间(8位机),这样无形中就增大了程序的code的体积并且使得速度上也受到影响,所以尽量把indata区的ram用到极限是非常有意义的。

本人总结了一些节省内存的规律,提供给大家讨论一下,看看是否可行。

1.内存分配的基本原理:

keil与其他的c语言编译器我认为从内存分配的原理上是基本相同的。总结起来,其实很简单,就是选最长的路径进行编译(话糙理不糙),例如下面的两段程序

program 1:

unsigned char a();

void b();

void main()

{

unsigned char byte1;

unsigned char byte2;

byte1 = byte2 = 3;

if( a() == 3)

{

   b();

}

a();

return;

}

// a function

unsigned char a()

{

unsigned char byte_a1;

unsigned char byte_a2;

byte_a1 = byte_a2 = 3;

byte_a1 = 4;

byte_a2 = 5;

return byte_a1;

}

// b function

void b()

{

unsigned char byte_b1;

unsigned char byte_b2;

unsigned char byte_b3;

byte_b1 = byte_b2 = byte_b3 = 3;

return;

}

program 2:

void a();

void b();

void main()

{

unsigned char byte1;

unsigned char byte2;

byte1 = byte2 = 3;

a();

return;

}

// a function

void a()

{

unsigned char byte_a1;

unsigned char byte_a2;

byte_a1 = byte_a2 = 3;

if (byte_a1 == 3)

{

   b();

}

byte_a1 = 4;

byte_a2 = 5;

return;

}

// b function

void b()

{

unsigned char byte_b1;

unsigned char byte_b2;

unsigned char byte_b3;

byte_b1 = byte_b2 = byte_b3 = 3;

return;

}

两段程序的作用是相同的,都是先执行函数a,然后根据byte_a1的值判断去执行b程序,但是用keil编译的结果却不相同program 1 编译的结果是data:14 code:48,而program 2 编译的结果是data:16 code:56,可见program 1 比 program 2 即节省了code又节省了内存。

看一下反汇编代码,就可以了解原因了,在a函数中调用b函数,a函数定义的byte_a1和byte_a2变量没有被释放,所以program 2 的内存分配是 8(SFR) + 1(STACK) + 2(MAIN FUNC) + 2(A FUNC) + 3(B FUNC) = 16 Bytes,而program 1 的内存分配是 8(SFR) + 1(STACK) + 3(B FUNC) = 14Bytes, 由于B函数和A函数是并行的,所以节省了a函数需要的2个字节。

这样总结看来程序不要串行,应尽量并行,充分利用有限的ram资源,这样既可以使code区变小,也可以使速度变快。

2.uncalled segment 影响内存分配:

不知道大家是否发现过当存在没有调用的函数时,内存空间很有可能会溢出,这个原因其实也非常简单例如:

program 3:

void a();

void b();

void c(unsigned char byte_input);

void main()

{

unsigned char byte1;

unsigned char byte2;

byte1 = byte2 = 3;

a();

c(3);

return;

}

// a function

void a()

{

unsigned char byte_a1;

unsigned char byte_a2;

byte_a1 = byte_a2 = 3;

if (byte_a1 == 3)

{

   b();

}

byte_a1 = 4;

byte_a2 = 5;

return;

}

// b function

void b()

{

unsigned char byte_b1;

unsigned char byte_b2;

unsigned char byte_b3;

byte_b1 = byte_b2 = byte_b3 = 3;

return;

}

void c(unsigned char byte_input)

{

unsigned char byte_c;

byte_c = byte_input;

return;

}

program 3 所示如果再main.c里面调用c(3)编译后data:16,而如果不调用c(3),编译后data:17,原因是调用c(3) data = 8(SFR) + 1(STACK) + 2(MAIN FUNC) + 2(A FUNC) + 3(B FUNC) = 16Bytes,而如果不调用c(3) data = 8(SFR) + 1(STACK) + 2(MAIN FUNC) + 2(A FUNC) + 3(B FUNC) + 1(C FUNC) = 17 Bytes。

所以,建议大家如果暂时不调用的函数最好屏蔽掉,以免影响整体的内存分配。


关键字:keil  c51  编译器  使用心得 引用地址:keil c51编译器的一些使用心得

上一篇:AT89C51芯片烧录驱动源程序
下一篇:Keil C51软件使用详解

推荐阅读最新更新时间:2024-03-16 15:21

DSP编程技巧之7---揭开编译器神秘面纱之预处理与诊断
   在 编程 软件例如 CCS 中 编程 时,代码分析工具可以方便我们对代码进行分析,例如我们把鼠标指向一个函数名的时候,所指的地方就能出来一个实时菜单,使得我们可以直接定位到函数的声明、被调用的位置或者某个宏定义等等,非常方便。这种功能是如何实现的呢?在编译器的前端是一个语义 解析器 ,它负责把源程序中的token找出来,然后 解析器 parser(也有的地方叫分析器)就可以解析这些token,并产生树状表,供 编程 环境使用;此外 解析器 还可以完成一部分的语法错误检查功能。如果希望了解关于解析器的更详细的信息,可以参考编译原理方面最著名的“龙书”,即《Compliers: Principles,
[嵌入式]
TLC2543驱动程序(c51)
/************************************** TLC2543驱动程序 *************************************/ #include reg51.h #include intrins.h /************************************** 2543控制引脚宏定义 *************************************/ #define CLOCK p17 /*2543时钟*/ #define D_IN p16 /*2543输入*/ #define D_OUT p14 /*2543输出*/ #def
[单片机]
C51单片机学习(二):中断系统和定时器
中断系统: 中断概念 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生); CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断 。 中断的结构图 其中一些说明: 1、(P3.2)可由IT0(TCON.0)选择其为低电平有效还是下降 沿有效。当CPU检测到P3.2引脚上出现有效的中断信号时, 中断标志IE0(TCON.1)置1,向CPU申请中断。 2、(P3.3)可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当CPU检测到P3.3引脚上出现有效的中断信号时,中
[单片机]
<font color='red'>C51</font>单片机学习(二):中断系统和定时器
keil环境下stm32f030程序运行的说明
我们先来看看STM32 正常的程序运行流程: STM32 的内部闪存(FLASH)地址起始于0x08000000,一般情况下,程序文件就从此地址开始写入。此外STM32 是基于Cortex-M3 内核的微控制器,其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是0x08000004,当中断来临,STM32 的内部硬件机制亦会自动将PC 指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。 环境配置: map文件 中断向量表: SRAM堆栈分配: 程序占用空间: FLASH所占
[单片机]
keil MDK之RTX的调试方法
一、准备一个RTX的工程并编译 二、点击MDK的调试按钮,如图红色框 三、进入调试状态下,选择System and Viewer 选择后就可以弹出下面这样的窗口 四、选择Debug里面的-》OS Support- Event Viewer,如下 选择后会弹出如下窗口 五、使能调试状态下的窗口周期性更新功能 六、点击全速运行 之后我们就可以观察到任务的实时运行情况  Timer Number:0 表示使用芯片的滴答定时器,1 表示使用外设定时器。  Tick Timer:RTX 的时钟节拍周期。  Roud Robin Timeout:时间片溢出时间
[单片机]
<font color='red'>keil</font> MDK之RTX的调试方法
keil+stm32+jlink利用swd方式进行printf输出
使用ITM机制实现调试stm32单片机,实现printf与scanf。 1. ITM简介 ITM机制是一种调试机制,是新一代调试方式,在这之前,有一种比较出名的调试方式,称为半主机(semihosting)方式。 在pc上编写过C语言的人都知道,printf可以向控制台输出,scanf可以从控制台获取输入,这里的printf/scanf都是标准库函数,利用操作系统的这些函数,我们可以很方便的调试程序。在嵌入式设备上(如stm32单片机平台上)开发工具(如MDK/IAR)也都提供了标准库函,自然也提供了printf/scanf函数,那么这些函数是否可以使用呢? 问题来了,printf向哪里输出呢?并且大部分情况下,也没有键盘,又如何
[单片机]
<font color='red'>keil</font>+stm32+jlink利用swd方式进行printf输出
MDK (Keil For ARM) 与 Proteus 联调 的设置方法
之前想用ADS来编译ARM,可是ADS不能像KEIL那样与Proteus联调,只能先生成HEX文件,然后再加载到Proteus中去,这样的话显然效率会降低好多,也不方便。所以在这里给大家介绍下MDK与Proteus的联调方法,希望对大家有所帮助。 安装之前的准备: 1、MDK4.0(Keil uVision 4) 有网友说4.0之前的版本在联调的时候会出现死机或连接不成功的情况,我没有试过,建议大家用4.0或其之后的版本。 2、Proteus 7.5 sp3 这个是目前最新的版本吧,对Proteus没有特别的要求,当然也可以用其他的版本。 3、vdmagdi.exe 这个是一个联调的补丁,就像
[单片机]
KEIL51用汇编语言建立工程的具体过程
1、启动keil 2、project-new project 3、找一个地方保存工程文件 4、在树形目录中点击atmel-at89c51,然后确定 5、file-new,出来一个空白框 6、file-save as,保存在你找的地方,输出文件名.asm 7、右击左右source group 1-add files to group source group 1 8、找到刚才的asm文件,选中后点add,再点close 9、现在就可以在那个空白框内写汇编程序了。写完后按F7编译。
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

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

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

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