您的位置 首页 基础

MCS51单片机程序设计时仓库的计算方法解析

MCS51单片机程序设计时堆栈的计算方法解析-应该说,Cx51是C语言在MCS51单片机上的扩展,既有C语言的共性,又有它自己的特点。本文介绍的是Cx51程序设计时堆栈的计算方法。

用C言语进行MCS51系列单片机程序设计是单片机开发和运用的必然趋势。Keil公司的C51编译器支撑经典8051和8051派生产品的版别,通称为Cx51。应该说,Cx51是C言语在MCS51单片机上的扩展,既有C言语的共性,又有它自己的特色。本文介绍的是Cx51程序设计时仓库的核算方法。

1.仓库的溢出问题。MCS51系列单片机将仓库设置在片内RAM中,由于片内RAM资源有限,仓库区的规模也是有限的。仓库区留得太大,会削减其他数据的寄存空间,留得太少则很简单溢出。所谓仓库溢出,是指在仓库区现已满了的时分还要进行新的压栈操作,这时只好将压栈的内容寄存到非仓库区的特别功用寄存器(SFR)中或许仓库外的数据区中。特别功用寄存器的内容影响体系的状况,数据区的内容又很简单被程序修改,这样一来,之后进行出栈操作(如子程序回来)时内容已变样,程序也就乱套了。因而,仓库区有必要留够,宁可大一些。要在Cx51程序设计中避免仓库的溢出,要处理两个问题:榜首,准确核算体系分配给用户的仓库巨细,假定是M;第二,准确核算用户需求仓库的巨细,假定是N。要求M≥N,下面别离剖析这两个问题。

2.核算体系分配给用户的仓库巨细Cx51程序设计中,由于动态部分变量是长驻内存中的,实际上相当于部分静态变量,即便在函数调用完毕时也不开释空间(这一点不同于规范C言语)。Cx51编译器依照用户的设置,将一切的变量寄存在片内和片外的RAM中。片内变量分配好空间后,将剩余的空间悉数作为仓库空间,这个空间是最大或许的仓库空间。当然,由于Cx51是一种能够拜访寄存器的C言语(特别功用寄存器),因而可在程序中拜访SP,将仓库空间设置得小一点。不过,一般没有人这么做。

本文仅仅评论放在片内RAM的变量。咱们把变量分为两种状况:

① 用作函数的参数和函数回来值的部分变量。这种变量尽量在寄存器组中寄存。为了评论便利,假定统一用寄存器组0,详细的地址为0x00~0x07。最多能够传递3个参数,假如参数的个数比较多,就将剩余的参数放到内存(0x08今后的地址)中寄存。这儿,假定每个函数的参数都不大于3个。

② 咱们在程序中界说的全局变量,以及不是用作函数的参数和函数回来值的部分变量。以上两种变量在内存中0x08地址今后寄存,寄存完毕后将仓库指针SP指向分配了变量的片内RAM的最终一个字节。由于MCS51单片机的仓库是一种满递加仓库且仓库的宽度为8位,所以在需求压栈操作时将仓库指针先加1,后入栈有用内容。有了以上规矩,就能够准确地核算出体系分配给用户的仓库空间。以求两个数的最大公约数和最小公倍数的函数为例,代码如下:

#include

unsigned char max(unsigned char a, unsigned char b);

unsigned char min(unsigned char a, unsigned char b);

unsigned char M;

void main (void)

{

unsigned char n;

M = max(12, 9);

n = min(12, 9);

}

unsigned char max(unsigned char a, unsigned char b)

{

while(a != b)

{

if(a 》 b)

a = a – b;

else

b = b – a;

}

return a;

}

unsigned char min(unsigned char a, unsigned char b)

{

unsigned char k;

k = ab/M;

return k;

}

这段程序中资源的分配状况如下:一个全变量M(无符号字符型)寄存最大公约数;主函数中界说一个部分变量n(无符号字符型)寄存最小公倍数;求最大公约数的函数unsigned char max(unsigned char a, unsigned char b),有两个参数a和b;求最小公倍数的函数unsigned char min(unsigned char a, unsigned char b),有两个参数a和b,而且界说了一个变量k寄存函数的回来值。能够由此核算出体系分配给变量的空间。函数的参数和回来值在作业寄存器组中寄存,所以不占用0x08地址今后的空间。体系只给变量M和变量n分配存储空间,这两个变量占两个字节(地址为0x08和0x09),则仓库指针SP应该指向0x09。Cx51体系编译后生成代码的体系资源占用状况如下:全局变量M的地址为0x08,n的地址为0x09,SP的值为0x09。这与咱们的核算结果相符。

3.核算用户需求仓库的巨细。仓库区究竟留多大才算满足呢? Cx51程序设计中,用户需求仓库的巨细能够从一般子函数和中止子程序的嵌套层数来核算。一般子函数的调用比较简单,每次调用时便是将函数的回来地址保存在仓库中,这个地址占两个字节。函数嵌套调用时,从最内层的子函数算起,总的仓库需求字节数为嵌套的层数乘以2。中止子程序的仓库需求分为两种状况:

① 中止子程序运用中止产生前的寄存器组。在中止产生时,保存中止子程序的回来地址需求2个字节。中止产生后,在中止子程序中体系会主动进行如下操作:将ACC、B、DPH、DPL、PSW、R0~R7共13个寄存器压栈。加上中止回来地址,中止的仓库需求为15个字节。

② 中止子程序运用自己专用的寄存器组。这种状况下不需求保存R0~R7的内容,能够削减仓库需求,其他的内容仍需求压栈维护。中止产生时,保存中止子程序的回来地址需求2个字节。中止产生后,在中止子程序中体系会主动进行如下操作:将ACC、B、DPH、DPL、PSW共5个寄存器压栈。加上、中止回来地址,这种仓库的需求为7个字节。可是这种状况应该留意:假如中止子程序中调用子函数,且函数需求参数和回来值,则被调用的子函数和中止子程序要运用相同的寄存器组,不然会呈现不行意料的结果。

以一个温度测验体系为例。体系选用8051作为处理器,温度信号在A/D转化完毕后经过外部中止0提示单片机接纳处理。守时中止0作为监控程序,中止周期为20 ms。温度信号能够主动丈量(每秒一次)或许手动丈量(按丈量键后丈量),这两种丈量方法能够经过控制键切换。中止子程序和一般子函数的嵌套状况为:在守时中止程序中调用显现子程序,外部中止0内部没有函数调用。部分程序如下:

void int0(void) interrupt 0 using 1

{

读取转化数据;

数据处理;

}

void TIme0 (void) interrupt 1

{

计数值重装;

读键;

按键处理;

leddisp(adat);//显现

}

void main (void)

{

相关数据初始化和数码显现自检;

外部中止和守时器初始化设置;

单片机休眠;

}

void leddisp(unsigned char pt)

{

用串口作业方式0发送显现数据,并经过74LS164转化后静态显现;

}

接下来剖析这段程序的最大仓库需求。假定守时器0中止时,调用了显现函数void leddisp(unsigned char pt),在调用显现函数时A/D转化完毕产生了外部中止0的中止。这时应该是程序对仓库的最大需求,仓库的巨细是:守时器0(15字节)+显现函数(2字节)+外部中止0(7字节)=24字节。

结语:经过准确的核算编译体系分配给用户的仓库空间和用户自己最大的仓库需求,不只能从根本上处理仓库溢出的问题,还能够很好地组织单片机比较严重的资源。此外,经过在片内存储器寄存适量部分变量,还能够有用地进步软件的履行速度。
责任编辑;zl

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/zhishi/jichu/343697.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部