2.3 8051单片机的存储器
2.3.1 存储器的存储单位与编址
1. 常用存储单位
位(bit):它是计算机中最小的数据单位。由于计算机采用二进制数,所以1位二进制数称作1bit,如101011为6bit。
字节(Byte,单位简写为B):8位二进制数称为一个字节,1B=8bit。
字(Word):两个字节构成一个字,即1Word=2Byte。
在单片机中还有一个常用术语:字长。所谓字长是指单片机一次能处理的二进制数的位数。51单片机一次能处理8位二进制数,所以51单片机的字长为8位。
2. 存储器的编址与数据的读写说明
图2-8是一个容量为256B的存储器,内部有256个存储单元,每个存储单元可以存放8位二进制数,为了存取数据方便,需要对每个存储单元进行编号,也即对存储单元编址,编址采用二进制数,对256个存储单元全部编址至少要用到8位二进制数,第1个存储单元编址为00000000,编写程序时为了方便,一般用十六进制数表示,二进制数00000000用十六进制表示就是00H,H表示十六制数,第二个存储单元编址为01H,第256个存储单元编址为FFH(也可以写成0FFH)。
要对256B存储器的每个存储单元进行读写,需要8根地址线和8根数据线,先送8位地址选中某个存储单元,再根据读控制或写控制,将选中的存储单元的8位数据从8根数据线送出,或通过8根数据线将8位数据存入选中的存储单元中。以图2-8为例,当地址总线A7~A0将8位地址0001111(1FH)送入存储器时,会选中内部编址为1FH的存储单元,这时再从读控制线送入一个读控制信号,1FH存储单元中的数据00010111从8根数据总线D7~D0送出。
图2-8 256B存储器的编址
2.3.2 片内外程序存储器的使用与编址
单片机的程序存储器主要用来存储程序、常数和表格数据。8051单片机内部有4KB的程序存储器(8052单片机内部有8KB的程序存储器,8031单片机内部没有程序存储器,需要外接程序存储器),如果内部程序存储器不够用(或无内部程序存储器),可以外接程序存储器。
8051单片机最大可以外接容量为64KB的程序存储器(ROM),它与片内4KB程序存储器统一编址,当单片机的EA端接高电平(接电源正极)时,片内、片外程序存储器都可以使用,片内4KB程序存储器的编址为0000H~0FFFH,片外64KB程序存储器的编址为1000H~FFFFH,片外程序存储器低4KB存储空间无法使用,如图2-9(a)所示,当单片机的EA端接低电平(接地)时,只能使用片外程序存储器,其编址为0000H~FFFFH;片内4KB程序存储器无法使用,如图2-9(b)所示。
图2-9 8051单片机片内、外程序存储器的使用与编址
2.3.3 片内外数据存储器的使用与编址
单片机的数据存储器主要用来存储运算的中间结果和暂存数据、控制位和标志位。8051单片机内部有256B的数据存储器,如果内部数据存储器不够用,可以外接数据存储器。
8051单片机最大可以外接容量为64KB的数据存储器(RAM),它与片内256B数据存储器分开编址,如图2-10所示。当8051单片机连接片外RAM时,片内RAM的00H~FFH存储单元地址与片外RAM的0000H~00FFH存储单元地址相同,为了区分两者,在用汇编语言编程时,读写片外RAM时要用“MOVX”指令(读写片内RAM时要用“MOV”指令),在用C语言编程时,读写RAM时须先声明数据类型(内部数据或外部数据),若读写的数据存放在片内RAM中,要声明数据类型为内部数据类型(如用“data”声明),若读写的数据存放在片外RAM中,应声明数据类型为外部数据类型(如用“xdata”声明),单片机会根据声明的数据类型自动选择读写片内或片外RAM。
图2-10 8051单片机片内、外数据存储器的使用与编址
2.3.4 数据存储器的分区
8051单片机内部有128B的数据存储器(地址为00H~7FH)和128B的特殊功能寄存器区(地址为80H~FFH),8052单片机内部有258B的数据存储器(地址为00H~FFH)和128B的特殊功能寄存器区(地址为80H~FFH),如图2-11所示。
图2-11 8051、8052单片机的数据存储器分区
根据功能不同,8051、8052单片机的数据存储器可分为工作寄存器区(0~3组)、位寻址区和用户RAM区,从图2-11可以看出,8052单片机的用户RAM区空间较8051单片机多出128B,该128B存储区地址与特殊功能寄存器区(SFR)的地址相同,但两者是两个不同的区域。特殊功能寄存器区的每个寄存器都有一个符号名称,如P0(即P0锁存器)、SCON(串行通信控制寄存器),特殊功能寄存器区只能用直接寻址方式访问,8052单片机的新增的128B用户RAM区只能用间接方式访问。
1. 工作寄存器区
单片机在工作时需要处理很多数据,有些数据要用来运算,有些要反复调用,有些要用来比较校验等,在处理这些数据时需要有地方能暂时存放这些数据,单片机提供暂存数据的地方就是工作寄存器。
8051单片机的工作寄存器区总存储空间为32B,由0~3组工作寄存器组成,每组有8个工作寄存器(R0~R7),共32个工作寄存器(存储单元),地址编号为00H~1FH,每个工作寄存器可存储一个字节数据(8位)。4组工作寄存器的各个寄存器地址编号如下。
单片机上电复位后,默认使用第0组工作寄存器,可以通过编程设置PSW(程序状态字寄存器)的RS1、RS0位的值来换成其他组工作寄存器。当PSW的RS1位=0、RS0位=0时,使用第0组工作寄存器;RS1位=0、RS0位=1时,使用第1组工作寄存器;RS1位=1、RS0位=0时,使用第2组工作寄存器;RS1位=1、RS0位=1时,使用第3组工作寄存器,如图2-12所示。不使用的工作寄存器可当作一般的数据存储器使用。
图2-12 PSW 的RS1、RS0位决定使用的工作寄存器组号
2. 位寻址区
位寻址区位于工作寄存器区之后,总存储空间为16B,有16个字节存储单元,字节地址为20H~2FH,每个字节存储单元有8个存储位,一共有16×8=128个存储位,每个位都有地址,称为位地址,利用位地址可以直接对位进行读写。
位寻址区的16个字节存储单元与128个存储位的地址编号如图2-13所示,从图中可以看出,字节存储单元和存储位有部分相同的地址编号,单片机是以指令类型来区分访问地址为字节存储单元还是位单元,比如用字节指令访问地址20H时,访问的为20H字节单元,可以同时操作该字节单元的8位数,用位指令访问地址20H时,访问的为24H字节单元的D0位,只能操作该位的数据。
3. 用户RAM区
用户RAM区又称为数据缓存区,8051单片机的用户RAM区有80个存储单元(字节),地址编号为30H~7FH,8052单片机的用户RAM区有208个存储单元(字节),地址编号为30H~FFH。用户RAM区一般用来存储随机数据和运算中间结果等。
图2-13 位寻址区的16个字节存储单元与128个位的地址编号
图2-13 位寻址区的16个字节存储单元与128个位的地址编号(续)
2.3.5 特殊功能寄存器(SFR)
特殊功能寄存器简称SFR(Special Function Register),主要用于管理单片机内部各功能部件(如定时器/计数器、I/O端口、中断控制器、串行通信口等),通过编程设定一些特殊功能寄存器的值,可以让相对应的功能部件进入设定的工作状态。
1. 特殊功能寄存器的符号、字节地址、位地址和复位值
8051单片机有21个特殊功能寄存器(SFR),见表2-2,每个特殊功能寄存器都是一个字节单元(有8位),它们的地址离散分布在80H~FFH范围内,这个地址范围与数据存储器用户RAM区(对于8052单片机而言)的80H~FFH地址重叠,为了避免寻址产生混乱,51单片机规定特殊寄存器只能用直接寻址(直接写出SFR的地址或符号)方式访问,8052单片机新增的128B用户RAM区的80H~FFH单元只能用间接寻址方式访问。
21个特殊功能寄存器都能以字节为单位进行访问,其中有一些特殊功能寄存器还可以进行位访问,能访问的位都有符号和位地址,位地址为特殊功能寄存器的字节地址加位号。以特殊功能寄存器P0为例,其字节地址为80H(字节地址值可以被8整除),其P0.0~P0.7位的位地址为80H~87H,访问字节地址80H时可读写8位(P0.0~P0.7位),访问位地址82H时仅可读写P0.2位。
有位地址的特殊寄存器的既可以用字节地址访问整个寄存器(8位),也可以用位地址(或位符号)访问寄存器的某个位,无位地址的特殊寄存器只能用字节地址访问整个寄存器。当位地址和字节地址相同时,单片机会根据指令类型来确定该地址的类型。单片机上电复位后,各特殊功能寄存器都有个复位初始值,具体见表2-2,x表示数值不定(或1或0)。
表2-2 8051单片机的21个特殊功能寄存器(SFR)
2. 部分特殊功能寄存器介绍
单片机的特殊功能寄存器很多,可以分为特定功能型和通用型。对于特定功能型特殊功能寄存器,当往某些位写入不同的值时,可以将其控制的功能部件设为不同工作方式,读取某些位的值,可以了解相应功能部件的工作状态;通用型特殊功能寄存器主要用于运算、寻址和反映运算结果状态。
特定功能型特殊功能寄存器将在后面介绍功能部件的章节说明,下面介绍一些通用型特殊功能寄存器。
(1)累加器(ACC)
累加器又称ACC,简称A,是一个8位寄存器,其字节地址为E0H。累加器是单片机中使用最频繁的寄存器,在进行算术或逻辑运算时,数据大多数先进入ACC,运算完成后,结果也大多数也送入ACC。
(2)寄存器B
寄存器B主要用于乘、除运算,其字节地址是F0H。在乘法运算时,一个数存放在A(累加器)中,另一个数存放在B中,运算结果得到的积(16位),积的高字节存放在B中,低字节存放在A中;在除法运算时,被除数存取自A,除数取自B,运算结果得到的商(8位)和余数(8位),商存放在A中,余数存放在B中。
(3)数据指针寄存器(DPTR)
数据指针寄存器(DPTR)简称数据指针,是一个16位寄存器,由DPH和DPL两个8位寄存器组成,地址分别为83H、82H。DPTR主要在单片机访问片外RAM时使用,用于存放片外RAM的16位地址,DPH保存高8位地址,DPL保存低8位地址。
(4)堆栈指针寄存器(SP)
人们在洗碗碟时,通常是将洗完的碗碟一只一只由下往上堆起来,使用时则是将碗碟从上往下一只一只取走。这个过程有两个要点:一是这些碗碟的堆放是连续的;二是先堆放的后取走,后堆放的先取走。单片机的堆栈与上述情况类似。堆栈是指在单片机数据存储器中划分出的一个连续的存储空间,这个存储空间存取数据时具有“先进后出,后进先出”的特点。
在存储器存取数据时,首先根据地址选中某个单元,再将数据存入或取出。如果有一批数据要连续存入存储器,例如,将5个数据(每个数据为8位)依次存入地址为30H~34H的5个存储单元中,按一般的操作方法是:先选中地址为30H的存储单元,再将第1个数据存入该单元,然后选中地址为31H的存储单元,再将第2个数据存入该单元,……显然这样存取数据比较麻烦,采用堆栈可以很好地解决这个问题。
在数据存储器中划分堆栈的方法是:通过编程的方法设置堆栈指针寄存器(SP)的值,如让SP=2FH,SP就将存储器地址为2FH的存储单元设为堆栈的栈顶地址,2FH单元后面的连续存储单元就构成了堆栈,如图2-14所示。堆栈设置好后,就可以将数据按顺序依次存入堆栈或从堆栈中取出,在堆栈中存取数据按照“先进后出,后进先出”的规则进行。
图2-14 堆栈的使用
需要注意的是,堆栈指针寄存器(SP)中的值并不是堆栈的第一个存储单元的地址,而是前一个单元的地址。例如,SP=2FH,那么堆栈的第一个存储单元的地址是30H,第1个数据存入30H单元。单片机通电复位后,SP的初始值为07H,这样堆栈第一个存储单元的地址就为08H,由于08H~1FH地址已划分给1~3组工作寄存器,在需要用到堆栈时,通常在编程时设SP=2FH,这样就将堆栈设置在数据存储器的用户RAM区(30H~7FH)。
(5)程序状态字寄存器(PSW)
程序状态字寄存器(PSW)的地址是D0H,它是一个状态指示寄存器(又称标志寄存器),用来指示系统的工作状态。PSW是一个8位寄存器,可以存储8位数,各位代表不同的功能。程序状态字寄存器(PSW)的字节地址、各位地址和各位功能如图2-15所示。
图2-15 程序状态字寄存器(PSW)的字节地址、各位地址和各位功能
D7位(C):进位标志位。当单片机进行加、减运算时,若运算结果最高位有进位或借位时,C位置1,无进位或借位时,C位置0。在进行位操作时,C用作位操作累加器。
D6位(AC):半进位标志位。单片机进行加、减运算时,当低半字节的D3位向高半字节的D4位有进位或借位时,AC位置1,否则AC位置0。
D5位(F0):用户标志位0。用户可设定的标志位,可置1或置0。
D4位(RS1)、D3位(RS0):工作寄存器组选择位。这两位有4种组合状态,用来控制工作寄存器区(00H~1FH)4组中的某一组寄存器进入工作状态,具体见图2-12。
D2位(OV):溢出标志位。在进行有符号数运算时,若运算结果超出−128~+127范围,OV=1,否则OV=0;当进行无符号数乘法运算时,若运算结果超出255,OV=1,否则OV=0;当进行无符号数除法运算时,若除数为0,OV=1,否则OV=0。
D1位(F1):用户标志位1。同F0位,用户可设定的标志位,可置1或置0。
D0位(P):奇偶校验位。该位用于对累加器A中的数据进行奇偶校验,当累加器A中“1”的个数为奇数值时,P=1;若累加器A中的“1”的个数为偶数值时,P=0。51系列单片机总是保持累加器A与P中“1”的总个数为偶数值,比如累加器A中有3个“1”,即“1”的个数为奇数值,那么P应为“1”,这样才能让两者“1”的总个数为偶数值,这种校验方式称作偶校验。