当前位置:首页 > 单片机 > 正文内容

传统51单片机的RAM

haohao2年前 (2023-12-21)单片机216

传统51单片机RAM大体分为片内RAM(IDATA)和片外RAM(XDATA)。根据需要,可以通过外接RAM芯片的方式,将片外RAM最大扩充至64KB,现阶段不做研究

片内RAM共有256个单元,又可以按照功能分为低128个单元(DATA区)和高128个单元(SFR区)。低128个单元的地址范围:00H~7FH,高128个单元地址范围:80H~FFH。

寄存器的字节地址

DATA区(00H~7FH)是单片机内部真正的RAM,用于存放程序执行时的变量。

SFR区(80H~FFH) 是单片机内部用于对CPU各种功能部件进行控制和监控的特殊RAM单元,即特殊功能寄存器(special Function Register),例如在上一篇中使用的P1口,查表可知,它所对应的寄存器就是90H,其最低位对应P1.0引脚,最高位对应P1.7引脚,通过改变此寄存器的值即可控制P1端口输出的电平,反之,也可通过读取此寄存器的值来读取外部输入到引脚的电平。

特殊功能寄存器名称及地址映像见《stc89c51rc-rd.pdf》第59页。

回到上次的程序1,代码P1=0xDE可以直接改变90H寄存器的值,从而改变P1端口的输出电平。可是,编译器为什么会知道P1端口的寄存器地址呢?其实,大部分寄存器的名称及其对应的地址已经在头文件reg51.h中定义了。

/* reg51.h部分代码 */
...
sfr P0   = 0x80;
sfr P1   = 0x90;
sfr P2   = 0xA0;
sfr P3   = 0xB0;
...
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0  = 0x8A;
sfr TL1  = 0x8B;
sfr TH0  = 0x8C;
sfr TH1  = 0x8D;
sfr IE   = 0xA8;
sfr IP   = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
...

Keil C51对标准C语言的语法进行了扩充,新增了一些关键字,例如sfr、sbit、interrupt、code等,其中,sfr关键字用来定义特殊功能寄存器。所以,我们以后只需要在程序中包含reg51.h头文件就不用我们自己去定义特殊寄存器了。(自行尝试在不包含reg51.h头文件的情况下实现点灯程序)

如果只想单独对一个引脚进行操作,其实还可以按位访问寄存器。sbit关键字用来定义特殊功能寄存器中的位寻址位,例如程序2中的sbit d1=P1^0,意思是定义了90H寄存器中的第0位为d1。这样,在接下来的程序中对d1进行操作就相当于直接对90H寄存器第0位的值进行操作,例如d1=0。但需要注意的是,只有能被8整除的特殊功能寄存器地址才可以进行位操作,这样的寄存器称为可位寻址寄存器,不能够被8整除的则不可以进行位操作。例如P1口的地址是90H可被8整除,可进行位操作;TCON的地址88H可被8整除,可进行位操作;TMOD的地址89H不能被8整除,不可进行位操作。

寄存器的位地址

可位寻址寄存器中的每一位,都对应了一个位地址,例如P1端口的寄存器地址90H,它第0位的位地址是90H,它的第1位的位地址是91H,以此类推。

特殊功能寄存器的位地址表见《stc89c51rc-rd.pdf》第60页。

所以,下面的程序也可实现程序2的功能:

#include <reg51.h>

sbit d1=0x90; //sbit d1=P1^0;
sbit d6=0x95; //sbit d6=P1^5;

main()
{
    d1=0;
    d6=0;
    while(1){}
}

在reg51.h中,已对一些位地址进行了定义:

/* reg51.h部分代码 */
...
/*  TCON  */
sbit TF1  = 0x8F;
sbit TR1  = 0x8E;
sbit TF0  = 0x8D;
sbit TR0  = 0x8C;
sbit IE1  = 0x8B;
sbit IT1  = 0x8A;
sbit IE0  = 0x89;
sbit IT0  = 0x88;
/*  IE   */
sbit EA   = 0xAF;
sbit ES   = 0xAC;
sbit ET1  = 0xAB;
sbit EX1  = 0xAA;
sbit ET0  = 0xA9;
sbit EX0  = 0xA8;
...
/*  SCON  */
sbit SM0  = 0x9F;
sbit SM1  = 0x9E;
sbit SM2  = 0x9D;
sbit REN  = 0x9C;
sbit TB8  = 0x9B;
sbit RB8  = 0x9A;
sbit TI   = 0x99;
sbit RI   = 0x98;
...

关于两种地址的区分

例如TCON寄存器的地址是88H,它第1位的位地址是89H,相应代码sbit IE0 = 0x89;然而TMOD寄存器的地址是89H,相应代码sfr TMOD = 0x89;看起来,他们的地址不是冲突了吗?然而并不会,用sfr定义的寄存器会按字节地址访问,而sbit按字节中的位访问的,编译器会自动进行处理。

image.png

相关文章

点亮LED(快速体验)

点亮LED(快速体验)

部分电路原理图 点亮D1、D6(将P1.0、P1.5口置低电平)程序1#include <reg51.h> main() {    P1...

Keil_C51、Proteus下载

Keil C51下载 网盘地址https://cowtransfer.com/s/564c008d42134f Proteus下载 网盘地址https://cowtransfer.com/s...

创建Keil工程及进行仿真的步骤

创建Keil工程及进行仿真的步骤

创建Keil工程(以《led_test》工程为例) 启动Keil软件菜单栏->Project->New uVision Project在合适的位置,手动创建工程文件夹,以《led_tes...