STC8051系列单片机中很多具有内部扩展的数据存储器SRAM(单片机内部的RAM一般都是SRAM,区别于SDRAM,下面叙述中的RAM,即表示SRAM),所谓的内部扩展RAM,即是说在基本型的8051基础上扩展数据存储空间。从逻辑上来说,扩展的RAM空间应该是在芯片外部通过外部总线读取的,但从物理上看却又是在芯片内部的,一定数目的RAM空间被集成到了单片机内部,从而扩大了单片机的RAM。
STC系列单片机内部RAM及其可扩展情况如下图1所示:
图1
Idata空间表示单片机自身具有的基础RAM,xdata即是STC额外扩展的位于芯片内部的RAM。Idata和xdata所代表的意思即是是说数据到底是在片内的低256字节还是扩展的RAM地址上。
在程序中可以通过在类型后面声明来指定位置,如果不声明的话,数据存放的默认位置和编译器的SRAM编译设置有关。(此点后面介绍)。
Eg:
Unsigned char idata a;//定义一个uchar型变量,将会在程序运行时,被分配到低256或128字节的RAM上去
Unsigned int xdata b;//定义一个uint型变量,程序运行建立该变量时,将会被指定到扩展的RAM区域去。
这儿注意,STC的单片机只有40个引脚以上的才可以进行片外RAM扩展,最多支持片外字节地址为64KB。
其实,低256字节的RAM空间也并不是全部能通用访问的,其中还有工作组寄存器,堆栈指针寄存器,SFRs等,大体分布如图2,这些都是很多8051书上讲得很详细了,这里就不再赘述。
图2
STC8051的内部RAM计量方法是:标称RAM=集成RAM+扩展RAM。例如:stc15f2k60s2,内部具有2K的ram,这2K的RAM其实是由256字节的集成RAM和1792字节的扩展RAM构成的。在Keil中开发时,如果需要使用超过256字节的RAM,则应该在Keil的工程Option中设置MemoryModel为:Large:Variables in XDATA.,并勾选”use on-chip XRAM选项”(如图3所示),这样在代码中默认声明的变量即为xdata型变量,如果要使用集成RAM那部分空间,还需要额外声明idata.
图3
以上为STC 8051单片机的一般性RAM使用方法。接下来说一下STC单片机片外扩展RAM的使用和设置方法。
在工程中,我们可能遇到需要较大的数据暂存空间的情况,这个时候内部的2K、4K RAM就完全不够用了。使用单片机内部自带的EEPROM或Flash存储空间不失为一种方法,不过存在擦写次数有限和操作周期长的问题,在某些对实时性要求较高的场合,会耽误MCU对其它任务的处理。
这儿先来介绍下STC单片机扩展片外RAM的物理连接方式:通过使用P0、P2端口来进行地址、数据传输,其中P0口为数据/地址复用端口,并通过锁存芯片进行地址锁存。其他使用的信号还包括:ALE(P4.5),用于控制P0口连接的数据/地址数据线的锁存芯片,RD(P4.4)和WR(P4.2)用于对RAM存储芯片进行读写指示。具体的连接示例如图4所示:
图4
STC单片机片外扩展RAM空间的逻辑地址最大支持64Kbyte,此64KB是指除了单片机内部基本的256字节之外能扩展的地址,所以如果单片机内部进行了RAM扩展,使用了一部分地址,那么片外扩展的存储芯片地址就不一定能全部使用。
例如:stc15f2K60s2,如果同时使用内部和外部扩展的RAM空间地址,那么扩展的片外RAM空间最多只能访问:64k-(2k-256)=62.75k个字节地址了。
根据STC手册,控制是否使用内部扩展的RAM决定于AUXR寄存器的EXTRAM位。当该位为1,则不使用单片机内部扩展的RAM,而直接使用片外扩展的RAM。所以如果此时外部扩展了一片64K字节的RAM芯片,那该RAM芯片的所有地址都是可以访问到的。如果该位为0,则内部扩展的RAM和片外扩展的RAM都会使用,扩展地址总和同样是64K,但由于单片机内部扩展的RAM使用了一部分扩展地址,所以此时所能使用到的片外RAM 空间为64K与内部扩展RAM地址空间的差值了。如图5
在EXTRAM为0情况下,STC单片机会首先使用内部扩展RAM,当地址超过了内部扩展RAM地址时,会自动地使用外部RAM的,这就不用我们操心了。(STC 单片机复位时,EXTRAM位为0,即默认是内部和外部扩展RAM都会使用的。)
图5
同时,要使用片外的扩展RAM,在Keil中同样要进行相应的设置,指定外部RAM的起始字节地址以及大小。如图6所示:
图6
我实际使用的是 STC15F2K60S2(2K RAM,60K ROM)型单片机并使用32KByte的RAM芯片进行片外扩展,起始地址Start由图6可以看出是:0x0700。这个起始地址是这样计算的:2K(2048)-256=1792=0x0700,这就是片外扩展的RAM起始地址。空间大小Size由图6可以看出是:0x7D00,计算过程为:32K=32*1024=32768=0x8000.这样就完成了Keil中使用片外扩展RAM的配置。
我在程序中如此定义一个变量:
#define DATA_NUM 32768
uchar xdata P_rBuff1[DATA_NUM];
其它还有一些定义的idata和xdata变量。
Keil中程序编译结果如图7:
图7
程序经过测试,也能正常运行。
最后还有一点,STC15系列还有一个特殊功能寄存器(SFR)专门用于控制外部64K数据总线速度:BUS_SPEED。该寄存器的低两位:EXRTS[1:0]可以控制片外RAM访问动作的建立、保持、读或写所需的CPU时钟周期。
众所周知的是,片外RAM访问,时序大致分这样几个阶段:地址数据建立、地址数据保持(MCU的ALE管脚控制锁存地址数据)、数据的读或写。如图8所示:
图8
所以访问外部的RAM所需要的时钟周期也至少是这几部分动作的周期和,再加上额外的一些CPU跳转周期。而BUS_SPEED就是控制这些动作所需持续的时间的。
所以该寄存器数值和访问速度关系如图9所示:
图9
图9中两条MOVX命令都是访问片外RAM的,只是前者是访问片外RAM 8位地址,后者是访问片外RAM 16位地址,差别仅为一个周期,所以不用过多纠结此处。
接下来请看图10和图11:
图10
图11
图10是读写片内扩展RAM所需时钟周期,图11是读写片外扩展RAM(BUS_SPEED已设置为最快速度)所需时钟周期。8位的读写也是与此类似的。从对比中我们可以知道,片外扩展的RAM访问所需时间是片内扩展RAM所需时间的2~3倍。所以即便是在考虑使用片外扩展的RAM,也要注意其存取速度是否能够满足要求。另外还要考虑的是存储芯片的数据信号跳变所需时间。