51单片机内部只有128字节的RAM(8051),而8052有256字节的RAM,低128字节RAM直接或间接寻址都可以,高128字节RAM与SRF特殊功能寄存器共用地址,SFR只能直接寻址,高128字节RAM只能间接寻址。所以通常用总线方式扩展一片RAM。一般用62256(32kX8bit RAM)。访问方式可参考我的博文:
http://blog.ednchina.com/tengjingshu/218041/message.aspx
现在新出的51单片机都在内部扩展了外部RAM。这个RAM还是叫外部RAM,不过在芯片内部,之所以还叫外部RAM,是因为是用外部总线连接的,访问方式还是用MOVX访问。可以参考STC89C58RD+,扩展了1024字节(byte)RAM。所以STC89C58RD+一共有1024byte+256byte=1280byte这么多字节的RAM。
内部扩展RAM的使用
STC89C58RD+内部扩展RAM的使用是通过对特殊功能寄存器AUXR赋值实现的。
Mnemonic |
Add |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
复位值 |
AUXR |
8Eh |
— |
— |
— |
— |
— |
— |
EXTRAM |
ALE0FF |
xxxx,xx00 |
其中
EXTRAM Internal/External RAM access 内部/ 外部 RAM 存取
0: 内部扩展的EXT_RAM 可以存取.
RD+ 系列单片机
在00H 到3FFH 单元(1024 字节),使用MOVX @DPTR 指令访问,超过400H 的地址空间总是访问外部数据存储器(含400H 单元),MOVX @Ri 只能访问00H 到FFH 单元
RC 系列单片机
在00H 到FFH 单元(256 字节),使用MOVX @DPTR 指令访问,超过100H 的地址空间总是访问外部数据存储器(含100H 单元),MOVX @Ri 只能访问00H 到FFH 单元
1: External data memory access.
外部数据存储器存取,禁止访问内部扩展RAM,此时MOVX @DPTR / MOVX @Ri 的
使用同普通8052 单片机
调试经过
之前的板子是使用STC89C51RD+总线方式驱动62256,但只用到1024字节的RAM,而STC89C51RD+自身就有内部扩展的1k(外部)RAM,所以这次先没焊接62256。沿用以前程序(问题就处在这!!!)。(以下程序经过简化)
#include <reg52.h> #include <stdio.h> #include <stcmcu.h> void Serial_Init(void); void printValue(void); void main(void) { AUXR=0x03; Serial_Init(); printValue(); ); } void Serial_Init(void) { //--------serial init--------------------- //串口初始化 SCON = 0x50; //8 bit UART,enable TMOD |= 0x20; //t1 8 bit reload PCON |=0x80; //bandrate X 2 TH1 = 0xFF; //0xfa set bandrate 9600 with crystal 11.0592M TL1 = 0xFF; //0xff : 57600 TR1 = ; //t1 start ES=; //serial interrupt enable REN=; //recieve enable } void printValue(void) { //串口输出ScanData,一共3个值 unsigned int j; xdata unsigned ]; TI=; //开串口定时器 ;j<;j++) { ScanData[j]=; } ;j<;j++){ printf("%d\n",ScanData[j]); } Delayms(); TI=; //关串口定时器 }
printf串口输出。应该输出ScanData[0], ScanData[1], ScanData[2],都为0,可是确输出
0
256
512
我很吃惊,这么简单的程序都会出错,所以一直找问题。问题出在AUXR=0x03,之前是用了62256的,但这次没有用,xdata的数据应该存储在内部扩展的RAM里面,但确因为AURX这个寄存器进行相应改动,仍然访问外部RAM(62256)。因改为AUXR=0x01 / AUXR="0x00"。(AUXR第一位是ALEOFF,用于ALE禁止输出)。改了之后,串口输出:
0
0
0
正确了,后来程序又改为:
#include <reg52.h> #include <stdio.h> #include <stcmcu.h> void Serial_Init(void); void printValue(void); xdata unsigned ]; void main(void) { AUXR=0x01; Serial_Init(); printValue(); ); } void Serial_Init(void) { //--------serial init--------------------- //串口初始化 SCON = 0x50; //8 bit UART,enable TMOD |= 0x20; //t1 8 bit reload PCON |=0x80; //bandrate X 2 TH1 = 0xFF; //0xfa set bandrate 9600 with crystal 11.0592M TL1 = 0xFF; //0xff : 57600 TR1 = ; //t1 start ES=; //serial interrupt enable REN=; //recieve enable } void printValue(void) { //串口输出ScanData,一共3个值 unsigned int j; xdata unsigned ]; TI=; //开串口定时器 ;j<;j++) { ScanData[j]=; } ;j<;j++){ printf("%d\n",ScanData[j]); } Delayms(); TI=; //关串口定时器 }
定义了一个全局变量数组adData[512],这个数组的元素是int型的(16bit),所以一共占用1024字节RAM,加上3字节的ScanData数组,一共使用了1027个字节,编译后也可以在keil的Output Window中看出。
Program Size: data="32".1 xdata="1027" code="1175"
此时,虽然AUXR=0x01,定义成访问内部扩展RAM,但由于adData[512]是全局变量,定义时就分配RAM,所以但在printValue里分配局部变量ScanData时,RAM已经超过的STC89C58RD+的1024内部扩展RAM的上限,所以串口输出出错,和之前一样,输出
0
256
512
所以,千万要注意外部RAM够不够,不够的话,就不要省一片62256了J
注意的话:
快速使用的数 用内部RAM,只有128字节(8051)/256字节(8051) 访问只用1个机器周期
存储的数据 内部扩展的RAM 要注意芯片DataSheet上内部扩展RAM的大小
外部RAM 用总线方式访问,如32kX8 RAM 62256
51单片机最大可64k寻址