CPU访问外部ROM时,先从P0口输出低八位地址信号,当CPU从ALE端输出有效信号时(高电平),可将低八位地址信号送至锁存器373保存并输出,这样由P2口和锁存器共同输出十六位地址信号,然后CPU从PSEN端(低电平有效)输出读外部ROM数据有效低电平信号选通外部ROM,这时CPU就可通过P0口从数据总线上读入外部ROM指定单元送出的数据。
由此可见,ROM芯片必须在PSEN(低电平有效)有效期内将指定单元的数据送到数据总线上,否则CPU将读不到数据。
CPU访问外部RAM时,先从P0口输出低八位地址信号,当CPU从ALE端输出有效信号时(高电平),可将低八位地址信号送至锁存器373保存并输出,这样由P2口和锁存器共同输出十六位地址信号,然后RD/端输出读外部数据存储器信号(低电平有效)选通外部RAM,这样CPU就可通过P0口从数据总线上读入外部RAM指定单元送出的数据。
由此可见,外部RAM芯片必须在RD/有效期内(低电平有效)将指定单元的数据送到数据总线上,否则CPU将读不到数据。CPU对外部RAM进行写操作时,除用WR/信号取代RD/信号以外,其余工作时序与读操作相同。
1、8051为用户提供了三种不同的存储空间,它们的地址有部分重叠。通过利用特定地址的寻址指令,解决了地址重叠
的问题。
DATA和IDATA区寻址使用MOV指令;
MOV R1,#22H
MOV R0,#0A9H
MOV A,@R1
MOV @R0,A
XDATA区寻址
MOV DPTR,#3048
MOVX A,@DPTR
CODE区寻址
MOV DPTR,#TABLE_BASE
MOV A,index
MOVC
A,@A+DPTR
2、有些单片机具有附加的128字节的内部RAM,位于从80H开始的地址空间中,被称为IDATA。因为IDATA区的地址和SFRs的地址
是重叠的,通过区分所访问的存储区来解决地址重叠问题,因为IDATA区只能通过间接寻址来访问。
3、8051可对存储区直接或间接寻址。这些是典型的寻址方式。直接寻址是指在指令中直接包含所须寻址的字节地址,直接寻址只能在DATA区和
SFR中进行。
4、间接寻址要使用DPTR,PC,R0,R1寄存器,用来存放所要访问数据的地址,指令使用指针寄存器,而不是直接使用地址。用间接寻址方式
可访问CODE,IDATA,XDATA存储区。对DATA存储区也可使用间接寻址。只能用直接寻址方式对位进行寻址。
5、当执行“MOVX A,@DPTR”时,读信号RD自动有效,实现外部对象的数据读入到单片机累加器里;当执行“MOVX
@DPTR,A”时,写信号WR自动有效,实现单片机累加器里的数据送出给外部对象。
6、数据总线:51单片机的数据总线为P0口,P0口为双向数据通道,CPU从P0口送出数据和读回数据。
地址总线:51系列单片机地址总线为16位,为了节约芯片引脚,P0口复用,P0口除了作为数据总线外,在ALE引脚信号时序匹配下,通过外置数据锁存
器,在总线访问前半周期送出低8位地址总线,后半周期用作数据总线。高8位地址通过P2口送出。
控制总线:51系列单片机控制总线为读控制信号P3.7和写控制信号P3.6,分别作为总线模式下数据读回和数据写出使能信号。
7、指令MOVX @DPTR,A即可实现向P2口和P0输送地址和数据,输送时序如下。
单片机时序分析:完成一次总线(读写)操作周期为T,P0口分时复用,在T前半时间内,P0口送出低8位地址数据,在ALE的下降沿完成数据锁存,产生低
8位地址信号,在T后半时间段,P0口作为数据总线使用,可以送出数据或读入数据,数据的读写操作在读写控制信号低电期间完成,需要注意的是,在控制信号
(读写信号)有效期间,P2口送出高8位地址,配合数据锁存器输出的低8位地址,实现16位地址总线即64K的寻址范围。
所以地址编排从P2.7-P2.0-P0.7-P0.0,地址从0000H-FFFFH。
8、ALE下降锁存信号由MCU硬件控制。
9、MOVX A,@DPTR
MOVX @DPTR,A
MOVX A,@R0
MOVX
@R1,A
这些是寻址外部I/O接口和变量的标准指令。使用高级语言时,对程序员是透明的。
上面是看资料获得的点滴知识,也是单片机扩展外部SRAM的基础知识。所以按总线要求连接好电路,使用MOVX指令即可访问外部RAM。
在使用C语言编程时,把变量定义成XDATA类型,那么系统就会把此变量存储在外部RAM中。对此变量的读写操作就会自动从外部RAM中读写。
下面是一个先往外部RAM写数据,然后读取数据并显示的例子:
ORG 00H
JMP START
ORG 30H
START: MOV P1,#00H
MyWR: MOV
DPTR,#TABLE
MOV A,#00H
MOVC A,@A+DPTR
MOV DPTR,#0102H
MOVX
@DPTR,A
MOV DPTR,#TABLE
MOV A,#01H
MOVC A,@A+DPTR
MOV
DPTR,#0103H
MOVX @DPTR,A
MOV DPTR,#TABLE
MOV A,#02H
MOVC A,@A+DPTR
MOV
DPTR,#0104H
MOVX @DPTR,A
MOV DPTR,#TABLE
MOV A,#03H
MOVC A,@A+DPTR
MOV
DPTR,#0105H
MOVX @DPTR,A
RDandSHOW:
CALL DELAY
CALL DELAY
MOV DPTR,#0102H
MOVX
A,@DPTR
MOV P1,A
CALL DELAY
CALL DELAY
MOV DPTR,#0103H
MOVX A,@DPTR
MOV P1,A
CALL DELAY
CALL
DELAY
MOV DPTR,#0104H
MOVX A,@DPTR
MOV P1,A
CALL DELAY
CALL
DELAY
MOV DPTR,#0105H
MOVX A,@DPTR
MOV P1,A
CALL DELAY
CALL
DELAY
JMP MyWR
DELAY: MOV R2,#0FFH
MOV R3,#0FFH
DELAY1: NOP
NOP
DJNZ
R3,DELAY1
MOV R3,#0FFH
DELAY2: DJNZ R2,DELAY1
RET
TABLE: DB 06H,5BH,4FH,66H
END
采用仿真示波器可以看到往SRAM写数据的时序为:
C语言实现代码,用示波器可以看到和上面同样的时序。当执行P1=show_data[i]时,单片机会从外部SRAM读取数据,从P0口输
入,然后赋值给P1。
unsigned char xdata show_data[]={0x06,0x5b,0x4f,0x66};
void delay()
{
int i,j;
for(i=999;i>0;i--)
for(j=20;j>0;j--)
;
}
void main()
{
int i=4;
for(i=0;i<4;i++)
{
P1=show_data[i];
delay();
}
}