51手记之寄存器&寻址篇
0赞题记:刚开始练51时就用C语言,现在想再加强一下汇编,所以不得不对单片机的硬件结构,特别是地址空间的分配方面详细的做一下了解了。 于是决定拿起课本北航的《智能化测量控制仪表原理与设计》重新学一遍。书本是基础,然后应该把自己的一些应用体会实例什么的也加上去,这样学起来就事半功 倍了毕竟这是再学习不是入门了。
51单片机的存储器结构:
在物理上可以分为4个 存储器空间:即片内ROM,片外ROM,片 内RAM,片外RAM。51/52单片机有64KB(2的16次方,16条 地址线寻址)的ROM地址空间。其中51有4KB的片内ROM,52有8KB的片内ROM。至于使用片内还是片外的存储器,可以靠控制信号EA脚 来设置,当从片内存储器开始取指令时,EA脚接正(对于ROM型 单片机,通常采取此方式),此时如果指令地址超过4KB空间,则自动从片外开始取指令。而如果不使 用片内存储器只从片外存储器取指令时,将EA接地即可。
ROM中有些单元是保留给系统使用的:0000-0002H单 元是所有执行程序的入口地址,复位后程序总是从0000H单元开始执行。(所以在汇编的开始总是一 句
ORG 0000
LJMP nnnn ;主程序中断入口
这个语句的意思是在0000这个地址上存放着LJMP nnnn这个语句,这里的nnnn是程序的入 口地址,也就是编程者希望上电后程序从哪个地方开始执行)。
0003-002AH单元均匀的分为5段, 用于5个中断服务程序的入口。(例如
ORG 00BH
LJMP BT0 ;TO中断入口
也就是说00BH上存放着LJMP BTO这个语句,当产生TO中断时,前提当然 是此中断处于开启状态了,程序将执行该语句,然后跳转到BT0所指的地址上的程序继续执行)。
51/52的片内数据存储器RAM有256Byte,其中00H-7FH地址空间是直接寻 址区。该区从00H-1FH是工作寄存器区,有4组 工作寄存器组,至于使用哪一组则有PSW的RS0和RS1的状态决定。片内RAM的20H-2FH地址为位寻址区。片内RAM的80H-FFH地址空间是特殊功能寄存器(SFR) 区。52系列有26个特殊功能寄存器。下面 就把头文件reg52.h里的部分内容贴出来。(对于寄存器地址参考头文件就足够了,对于别的一些CPU也差不多)。
/*-------------------------------------------------------------------
REG52.H
Header file for generic 80C52 and 80C32 microcontroller.
Copyright (c) 1988-2001 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
-------------------------------------------------------------------*/
/* BYTE Registers */
sfr P0 = 0x80;
sfr P1 = 0x90;
sfr P2 = 0xA0;
sfr P3 = 0xB0;
sfr PSW = 0xD0;
sfr ACC = 0xE0;
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
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;
/* 8052 Extensions */
sfr T2CON = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2 = 0xCC;
sfr TH2 = 0xCD;
关于MCU的时钟问题:
一般用的是12MHz的 晶体,而MCU执行一个机器周期需要12各 时钟周期(所谓时钟周期,就是指晶体振荡一个周期的时间),那么正好是1us,一般的指令需要1-2个机器周期即可完成,乘除指令的运算量比较大需要4各 机器周期。
寻址方式:
51单片机有7种 寻址方式。
1、寄存器寻址:前面提到 了内部RAM中的00H-1FH地址单元作 为工作寄存器使用。一共是有32各地址单元,分成四组,每组有8个寄存器,命名为R0-R7,每次可以使用其中的一 组。当使用R0-R7来表示操作数时,就属于寄存器寻址方式。
例如:MOV A,R0;把寄存器R0的内容送入累加器A中
2、直接寻址:在指令中直 接给出操作数地址,就属于直接寻址方式。此时指令的操作数部分直接是操作数的地址。
例如:MOV A,2AH ;把RAM地 址2AH的内容送入累加器A中
3、立即寻址:
例如:MOV A,#3AH ;该指令就是表示把立即数3AH送入累加器A中,立即数前加上一个#,和直接寻址方式区分
4、寄存器间接寻址:若以 寄存器的名称直接给出操作数的地址,则称为寄存器间接寻址。
例如:MOV A,@R0 ;该指令是把RO里 的内容作为地址,这个地址的数据送入累加器A,注意前面需要加@
5、变址寻址:变址寻址是 以某个寄存器的内容为基本的地址,然后在这个基址上加以地址的偏移量,才是真正的操作数地址。
例如:MOV A,@A+DPTR ;地址是A+DPTR的 值,这个地址的内容送如累加器A
6、相对寻址:相对转移指 令需要用到相对寻址方式,此时操作数部分给出的是地址的相对偏移量部分。
目的地址 = 源地址+ 指令 字节数+ rel(rel可正可负)
例如:SJMP rel
7、位寻址:概念就不做解 释了。还是把reg52.h这个头文件贴出来说。
/* BIT Registers */
/* PSW */
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit P = PSW^0; //8052 only
/* TCON */
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;
/* IE */
sbit EA = IE^7;
sbit ET2 = IE^5; //8052 only
sbit ES = IE^4;
sbit ET1 = IE^3;
sbit EX1 = IE^2;
sbit ET0 = IE^1;
sbit EX0 = IE^0;
/* IP */
sbit PT2 = IP^5;
sbit PS = IP^4;
sbit PT1 = IP^3;
sbit PX1 = IP^2;
sbit PT0 = IP^1;
sbit PX0 = IP^0;
/* P3 */
sbit RD = P3^7;
sbit WR = P3^6;
sbit T1 = P3^5;
sbit T0 = P3^4;
sbit INT1 = P3^3;
sbit INT0 = P3^2;
sbit TXD = P3^1;
sbit RXD = P3^0;
/* SCON */
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0;
/* P1 */
sbit T2EX = P1^1; // 8052 only
sbit T2 = P1^0; // 8052 only
/* T2CON */
sbit TF2 = T2CON^7;
sbit EXF2 = T2CON^6;
sbit RCLK = T2CON^5;
sbit TCLK = T2CON^4;
sbit EXEN2 = T2CON^3;
sbit TR2 = T2CON^2;
sbit C_T2 = T2CON^1;
sbit CP_RL2 = T2CON^0;
从前面的特殊功能寄存器地址里已经了解了它们在RAM中的存 放地址,这里又对它们中的部分寄存器的各个位做了定义,也就是说,这些各个位做了定义的寄存器,它们的每一个位是可以单独进行操作的。
例如STEB EA;EA置1,表示开总中断,EA又是IE寄存器的最高位,这里单独对它进行操作,可以免去对整个IE寄 存器做赋值操作,优化程序
通过这些知识的复习,我觉得下一步该动手写程序感受一下了。