目录
在 51 单片机中,寻址方式是指在执行指令时,CPU 寻找操作数所在存储单元地址的方法。
由于计算机的指令执行过程中,常常需要对数据进行操作,而这些数据存储在不同的位置,如寄存器、存储器等,因此需要特定的方式来找到这些数据的地址,从而完成指令的操作。寻址方式的合理运用能够提高程序的执行效率、节省存储空间。
51 单片机有 7 种寻址方式,分别是:立即数寻址 、直接寻址 、寄存器寻址 、寄存器间接寻址 、变址寻址 、位寻址 和指令寻址。
可以分为两类:操作数寻址和指令寻址,在7种寻址方式中,除了指令寻址之外,其余六种都属于操作数寻址。
每种方式都有其特点和适用场景,以下作详细介绍。
一、立即数寻址
1、 概念
立即数寻址是指在指令中直接给出操作数 ,该操作数紧跟在操作码之后,作为指令的一部分存放在程序存储器中。
在执行指令时,CPU 直接从指令中获取操作数,而不需要再通过其他方式去寻找操作数的地址。
例如,指令 "MOV A, #30H",其中 "#30H" 就是立即数,这条指令的功能是将立即数 30H 传送到累加器 A 中。
2、特点
(1)优点 :寻址方式简单直接,执行速度快。 因为操作数直接包含在指令中,CPU 无需额外的时间去访问内存来获取操作数,所以能快速完成数据的传输和运算。
(2)缺点 :操作数是固定在指令中的,缺乏灵活性。 如果需要修改操作数,就需要修改指令本身,这在一些需要动态改变数据的情况下不太方便。
3、适用场景
(1)初始化操作 :在程序开始时,常常需要对一些寄存器或内存单元进行初始化赋值,使用立即数寻址可以方便地将初始值直接传送给相应的寄存器或内存单元。
(2)常数运算 :当进行一些与常数相关的运算时,立即数寻址可以直接将常数作为操作数参与运算,无需先将常数存储在内存中再进行访问。
4、例子
(1)数据传送 :"MOV R0, #50H",这条指令将立即数 50H 传送给寄存器 R0,即将 50H 这个值赋给 R0,使得 R0 存储单元中的内容变为 50H。
(2)加法运算 :"ADD A, #0AH",该指令是将累加器 A 中的内容与立即数 0AH 相加,结果存放在累加器 A 中。例如,若 A 中原来的内容是 30H,执行该指令后,A 中的内容变为 3AH(30H + 0AH = 3AH)。
二、直接寻址
1、概念
在 51 单片机里,直接寻址指的是在指令里直接给出操作数所在的内存单元地址。CPU 依据该地址,直接从对应的内存单元读取或者写入操作数。
例如,指令 "MOV A, 30H",此指令中的 "30H" 即为操作数所在的内存单元地址,CPU 会把地址为 30H 的内存单元中的内容传送到累加器 A 里。
2、特点
(1)优点:
① 操作直观。 指令中直接给出内存单元地址,很容易理解和编写程序,开发者能清晰知晓操作的具体内存位置。
②****可访问特定单元。****能对内部数据存储器的特定单元进行操作,像特殊功能寄存器(SFR),这些寄存器对单片机的各种功能进行控制,直接寻址能方便地对它们进行读写操作。
(2)缺点:
①寻 ****址范围受限。****只能访问内部数据存储器,包括低 128 字节(地址范围 00H - 7FH)以及特殊功能寄存器(地址范围 80H - FFH),不能访问外部数据存储器。
②****灵活性欠佳。****当需要操作多个连续的内存单元时,使用直接寻址需要为每个单元单独编写指令,不够灵活高效。
3、适用场景
(1)访问特殊功能寄存器 :特殊功能寄存器控制着单片机的众多功能,例如定时器、串口、中断等。通过直接寻址可以方便地对这些寄存器进行配置和控制 。
(2)访问内部数据存储器的特定单元 :当程序需要对内部数据存储器中的特定单元进行读写操作时 ,可使用直接寻址。
4、例子
(1)访问特殊功能寄存器 :"MOV P1, #0FFH",P1 是一个特殊功能寄存器,代表单片机的 P1 端口。此指令将立即数 0FFH 传送到 P1 端口,也就是把 P1 端口的 8 个引脚都置为高电平。
(2)访问内部数据存储器单元 :"MOV 30H, A",这条指令把累加器 A 中的内容传送到内部数据存储器地址为 30H 的单元中。若 A 中的内容为 55H,执行该指令后,地址 30H 单元的内容就变为 55H。
三、寄存器寻址
1、概念
51 单片机的寄存器寻址是指操作数存放在寄存器中,指令中直接给出寄存器名,CPU 通过指定的寄存器来获取操作数或存放运算结果。
在 51 单片机里,可用于寄存器寻址的寄存器有工作寄存器 R0 - R7、累加器 A、寄存器 B、数据指针 DPTR 等。
例如指令 "MOV A, R2",该指令就是将工作寄存器 R2 中的内容传送到累加器 A 中。
2、特点
(1)优点:
① 执行速度快:由于寄存器位于 CPU 内部,访问寄存器的速度比访问内存要快很多,所以采用寄存器寻址的指令执行效率较高。
②代码简洁:指令中只需指定寄存器名,无需额外的地址信息,使得指令长度较短,代码更加简洁。
(2)缺点:
① 寄存器数量有限:51 单片机中可用于寄存器寻址的寄存器数量相对较少,这限制了同时可操作的数据数量。当需要处理较多的数据时,可能会出现寄存器不够用的情况。
② 数据存储容量小:每个寄存器的存储容量有限,通常为 8 位(如 R0 - R7、A、B 等),对于一些需要处理大数据的情况不太适用。
3、适用场景
(1)频繁数据操作 :当需要对数据进行频繁的读取、写入和运算操作时,使用寄存器寻址可以提高程序的执行速度。例如在循环计算中,将中间结果存放在寄存器中进行快速处理。
(2)控制操作 :在对单片机的一些控制操作中,使用寄存器寻址可以方便地对控制寄存器进行读写 ,实现对单片机各种功能的控制。
4、例子
(1)数据传送 :"MOV R3, A",这条指令将累加器 A 中的内容传送到工作寄存器 R3 中。若累加器 A 中的内容为 20H,执行该指令后,R3 中的内容就变为 20H。
(2)加法运算 :"ADD A, R5",该指令将累加器 A 中的内容与工作寄存器 R5 中的内容相加,结果存放在累加器 A 中。假设 A 中的内容为 30H,R5 中的内容为 10H,执行该指令后,A 中的内容变为 40H(30H + 10H = 40H)。
四、寄存器间接寻址
1、概念
51 单片机的寄存器间接寻址是指操作数的地址存放在寄存器中,指令通过指定的寄存器来间接获取操作数的实际地址 ,进而访问该地址对应的内存单元以获取操作数或存放运算结果。
在 51 单片机里,可用于寄存器间接寻址的寄存器有 Ri(i = 0, 1,即R0、R1 )和数据指针 DPTR ,使用时需在寄存器名前加 **"@"**符号来表示间接寻址。
例如,指令 "MOV A, @R0",它的作用是把寄存器 R0 所存放的地址对应的内存单元中的内容传送到累加器 A 中。
2、特点
(1)优点:
① 灵活性高:可以通过改变寄存器中的地址值,方便地访问不同的内存单元,适用于处理连续存储的数据块,如数组、表格等。例如使用 R0、R1 或 DPTR 间接寻址时,通过改变其存储的地址,就能灵活访问不同的片内或片外 RAM 单元。
② 可动态访问内存:在程序运行过程中,能根据实际情况动态地改变寄存器中的地址,从而实现对不同内存区域的访问,增强了程序的灵活性和适应性。
(2)缺点:
① 执行速度稍慢:相较于寄存器寻址,寄存器间接寻址需要先从寄存器中获取地址,再根据该地址去访问内存单元,多了一个中间步骤,所以执行速度会稍慢一些。
② 增加编程复杂度:使用寄存器间接寻址时,需要对寄存器中的地址进行管理和维护,这增加了编程的复杂度,对程序员的要求较高。
3、适用场景
(1)访问连续存储的数据 :当需要处理连续存储在内存中的数据时,如数组、表格等,可以使用寄存器间接寻址,通过改变寄存器中的地址值,依次访问数组或表格中的各个元素。
(2)动态内存访问 :在程序运行过程中,根据不同的条件需要访问不同的内存区域时,可使用寄存器间接寻址。通过动态改变寄存器中的地址,实现对不同内存区域的灵活访问。
4、例子
① 使用 Ri 间接访问片内 RAM 空间
在 51 单片机里,R0 和 R1 能够当作间接寻址寄存器去访问片内 RAM 的低 128 字节(地址范围是 00H - 7FH)。示例代码如下:
MOV R0, #30H ; 将地址 30H 存入 R0
MOV A, @R0 ; 把片内 RAM 地址 30H 单元的内容传送到累加器 A
这里,R0存放着操作数的地址,通过@R0就能间接访问该地址对应的片内 RAM 单元。
② 使用 Ri 间接访问片外 RAM 空间
R0 和 R1 同样可用于间接访问片外 RAM 的低 256 字节(地址范围是 00H - FFH)。要使用 MOVX 指令,示例代码如下:
MOV R0, #20H ; 将地址 20H 存入 R0
MOVX A, @R0 ; 把片外 RAM 地址 20H 单元的内容传送到累加器 A
在此,R0****存放片外 RAM 的地址,借助 @R0 间接访问对应的片外 RAM 单元。
③ 使用 DPTR 间接访问片外 RAM 空间
数据指针 DPTR 是一个 16 位的寄存器,可用来间接访问整个 64KB 的片外 RAM 空间(地址范围是 0000H - FFFFH)。同样使用 MOVX 指令,示例代码如下:
MOV DPTR, #1000H ; 将地址 1000H 存入 DPTR
MOVX A, @DPTR ; 把片外 RAM 地址 1000H 单元的内容传送到累加器 A
这里,DPTR 存放片外 RAM 的地址,通过 @DPTR 间接访问对应的片外 RAM 单元。
五、变址寻址
1、概念
51 单片机的变址寻址是以数据指针 DPTR 或程序计数器 PC 作为基址寄存器 ,以累加器 A 作为变址寄存器 ,将两者的内容相加得到操作数的地址,再通过该地址访问程序存储器中的操作数。
这种寻址方式主要**用于访问程序存储器中的常数表格。**变址寻址指令有两条,分别是"MOVC A, @A + DPTR"和"MOVC A, @A + PC"。
2、特点
(1)优点:
① 方便访问表格数据:在程序存储器中可以存放一些固定的数据表格,如字符的段码表、三角函数表等,通过变址寻址可以方便地根据累加器 A 中的偏移量来访问这些表格中的数据。
② 节省存储空间:对于一些需要重复使用的固定数据,将其存放在程序存储器中,使用变址寻址进行访问,避免了在数据存储器中重复存储这些数据,节省了存储空间。
(2)缺点:
① 寻址范围受限:变址寻址主要用于访问程序存储器,且其寻址范围受限于基址寄存器和变址寄存器的组合。对于较大规模的数据表格,可能需要更复杂的处理方式。
② 执行速度相对较慢:由于需要进行基址和变址的相加运算来得到操作数的地址,相比于直接寻址和寄存器寻址,执行速度会相对较慢。
3、适用场景
(1)查表操作 :当程序中需要根据某个变量的值来查找对应的固定数据时,如将数字转换为对应的七段数码管显示码、根据角度值查找正弦函数值等,变址寻址是一种非常有效的方法。
(2)代码的复用和优化 :对于一些固定的数据和算法,可以将其存储在程序存储器中,通过变址寻址来调用,提高代码的复用性和程序的执行效率。
4、例子
① 使用 MOVC A, @A+DPTR 指令访问表格数据
ORG 0000H
START:
MOV A, #02H ; 将偏移量 2 送入累加器 A
MOV DPTR, #TABLE ; 将表格的起始地址送入 DPTR
MOVC A, @A + DPTR ; 根据 A 和 DPTR 的内容计算地址,访问表格中的数据
SJMP $ ; 程序暂停
TABLE:
DB 01H, 02H, 03H, 04H, 05H ; 定义一个数据表格
END
在这个例子中,首先将偏移量 2 送入累加器 A,然后将表格的起始地址 TABLE 送入 DPTR。
执行 MOVC A, @A + DPTR 指令时,将 A 和 DPTR 的内容相加,得到操作数的地址,从程序存储器中读取该地址处的数据,并将其送入累加器 A。由于偏移量为 2,所以最终 A 中的值为 03H。
② 使用 MOVC A, @A + PC 指令访问表格数据
ORG 0000H
START:
MOV A, #01H ; 将偏移量 1 送入累加器 A
ADD A, #03H ; 补偿 PC 的值,因为执行 MOVC 指令时 PC 已经指向下一条指令
MOVC A, @A + PC ; 根据 A 和 PC 的内容计算地址,访问表格中的数据
SJMP $ ; 程序暂停
TABLE:
DB 10H, 20H, 30H, 40H, 50H ; 定义一个数据表格
END
在这个例子中,首先将偏移量 1 送入累加器 A。由于 MOVC A, @A + PC 指令执行时,PC 已经指向下一条指令,所以需要对 A 的值进行补偿(这里补偿值为 3,具体补偿值取决于 MOVC 指令和表格之间的指令字节数)。
执行 MOVC A, @A + PC 指令时,将 A 和 PC 的内容相加,得到操作数的地址,从程序存储器中读取该地址处的数据,并将其送入累加器 A。由于偏移量为 1,经过补偿后,最终 A 中的值为 20H。
六、位寻址
1、概念
51 单片机的位寻址是一种特殊的寻址方式,它允许对单片机内部数据存储器中的可位寻址区域的某一位进行单独的操作,包括位的置位、清零、取反、逻辑运算等。
可位寻址的区域主要有两部分 :一是内部数据存储器的 20H - 2FH 单元,这 16 个字节共 128 位,位地址范围是 00H - 7FH;二是部分特殊功能寄存器(SFR),这些特殊功能寄存器本身具有字节地址,其中部分寄存器的每一位也有独立的位地址。
2、特点
(1)优点
① 操作灵活 :可以对某一位进行单独的操作,而不影响其他位的状态,这在处理一些标志位、控制位时非常方便。例如,在控制外设时,可以通过位操作来单独控制某个引脚的电平。
② 节省存储空间 :对于只需要一位信息的场合,使用位寻址可以避免使用一个字节来存储信息,从而节省了存储空间。
③ 提高程序效率 :位操作指令通常执行速度较快,能够提高程序的执行效率,特别是在处理一些实时性要求较高的任务时。
(2)缺点
①寻址范围有限 :位寻址只能针对特定的可位寻址区域进行操作,不能对所有的内存单元进行位操作。
② 编程复杂度相对较高 :在使用位寻址时,需要准确了解可位寻址区域的位地址分配,对于初学者来说,可能会增加编程的难度。
3、适用场景
(1)状态标志管理 :在程序中,常常需要使用一些标志位来记录程序的运行状态,如溢出标志、进位标志、中断标志等 。使用位寻址可以方便地对这些标志位进行置位、清零和检测操作。
(2)控制信号处理 :在控制外部设备时,可能需要通过单片机的某些引脚输出控制信号,这些控制信号通常只需要一位信息(高电平或低电平)。使用位寻址可以直接对这些引脚对应的位进行操作,实现对外设的控制。
(3)逻辑运算 :在进行一些逻辑运算时,如与、或、非等,可以使用位寻址对单个位进行操作,实现更精细的逻辑控制。
4、例子
① 对内部数据存储器的位寻址区域进行操作
ORG 0000H
START:
SETB 20H.0 ; 将 20H 单元的第 0 位置 1
CLR 20H.1 ; 将 20H 单元的第 1 位清 0
CPL 20H.2 ; 将 20H 单元的第 2 位取反
MOV C, 20H.3 ; 将 20H 单元的第 3 位的值传送到进位标志 C
SJMP $ ; 程序暂停
END
在这个例子中,SETB 指令用于将指定的位置 1,CLR 指令用于将指定的位清 0,CPL 指令用于将指定的位取反,MOV C, bit 指令用于将指定位的值传送到进位标志 C。
② 对特殊功能寄存器的位进行操作
ORG 0000H
START:
SETB P1.0 ; 将 P1 端口的第 0 位置 1,即 P1.0 引脚输出高电平
CLR P1.1 ; 将 P1 端口的第 1 位清 0,即 P1.1 引脚输出低电平
JB P1.2, LOOP ; 如果 P1.2 引脚为高电平,则跳转到 LOOP 处执行
SJMP $ ; 程序暂停
LOOP:
; 处理 P1.2 引脚为高电平的情况
SJMP $ ; 程序暂停
END
在这个例子中,SETB 和 CLR 指令分别用于对 P1 端口的某一位进行置位和清零操作,JB 指令用于检测指定位是否为高电平,**如果为高电平则跳转到指定的地址执行。**P1 是一个特殊功能寄存器,其每一位对应单片机的一个引脚,通过位寻址可以方便地对这些引脚进行控制和检测。
七、指令寻址
在51单片机中,指令寻址使用于控制转移指令中,其操作数给出转移的目标位置的地址,访问的是code 区域。
常见的寻址方式包括绝对寻址和相对寻址,两者在跳转指令(如JMP、CALL)中尤为重要。
(一)绝对寻址
绝对寻址是在指令的操作数中,直接提供目标位置的地址或地址的一部分,CPU根据该地址直接访问存储器或外设。
51单片机的绝对寻址分为 完整地址(16位) 和 部分地址(11位) 两种形式,分别对应不同的指令和场景。
1、16位绝对寻址(完整地址)
**(1)指令示例:**LJMP(长跳转)、LCALL(长调用)
(2)特点: ① 直接指定完整的16位目标地址(例如LJMP 1000H);② 可跳转至 ROM 的任意位置(64KB范围);③ 指令长度为3字节(操作码 + 高8位地址 + 低8位地址)。
(3)适用场景: ①****跨大范围跳转(如从0000H跳转到F000H);②调用位于不同代码段的子程序。
(4)例子
ORG 0000H
LJMP INIT ; 强制跳转到INIT(地址可能超出2KB)
ORG 1000H
INIT:
MOV SP, #60H
LJMP LOOP ; 长跳转到其他代码段
ORG 2000H
LOOP:
; 主循环代码
2、11位绝对寻址(部分地址)
**(1)指令示例:**AJMP(绝对跳转)、ACALL(绝对调用)
(2)特点: ① 仅指定地址的低11位(例如AJMP 500H);②****目标地址 = 当前PC的高5位 + 指令中的11位地址(组合为16位地址);③****跳转范围限制在当前2KB页面内(11位地址范围:0~2047);④ 指令长度为2字节(操作码 + 11位地址)。
(3)适用场景: ① 页面内跳转(如代码集中在同一2KB区域);② 节省代码空间(比LJMP少1字节)
(4)例子
ORG 0000H ; 程序起始地址
AJMP MAIN ; 跳转到MAIN(假设MAIN在0x0000~0x07FF范围内)
ORG 0030H
MAIN:
MOV P1, #0FFH
ACALL DELAY ; 调用同一2KB页面内的子程序
SJMP MAIN
DELAY:
; 延时子程序
RET
(二)相对寻址
1、概念
相对寻址 通过偏移量(补码形式)实现跳转,目标地址 = 当前PC值 + 偏移量。偏移量范围为-128~+127(8位),适用于短距离跳转。
例如:SJMP LOOP 中的LOOP标签偏移量为0FEH(即-2),表示跳转到当前指令的前两条指令。
2、特点:① 位置无关性 :代码可移植到不同地址执行(偏移量不变);② 代码紧凑 :仅需1字节偏移量(如SJMP指令占2字节);③ 范围受限 :仅支持短距离跳转(-128~+127字节);④ 动态计算:运行时根据PC值计算目标地址。
3、适用场景:① 循环控制 :如DJNZ指令实现循环计数;② 条件分支 :JZ、JC等条件跳转;③ 代码优化:减少程序体积,提高执行效率。
4、例子
LOOP:
DJNZ R0, LOOP ; R0减1,若不为0则跳转到LOOP(偏移量自动计算)
SJMP $ ; 无限循环($表示当前指令地址,偏移量为0FEH)
JZ NEXT ; 若A=0,跳转到NEXT标签(相对偏移)
以上内容即为51单片机的七种寻址方式,创作不易,麻烦给个三连呗~
