单片机
单片机
进制转换及其加减法,补码
2,4,88,10,16进制之间的相互转化,具体内容见逻辑设计
数学基础知识
数据大小
储存容量是衡量微机内部储存器能储存二进制(Bit)信息量大小的一个技术指标
8位二进制数据称为一个字节(Byte)——最基本的计量单位,记为1B
16位二级制数据称为一个字(word)
32位二进制数据称为一个双字(Dword)
只读存储器(ROM)
ROM是一种掉电后不丢失信息的储存器。由于这个原因,ROM也成为非易失性存储器。
结构和容量
给定储存器芯片有12个地址引脚和4个数据引脚,此储存芯片有4096个位置($2^{12}=4096$),每个位置能储存4位数据,所以
结构
就是4096×4,也常用4K×4表示。其容量
是16Kb,因为总共是4K个位置,每个位置能保存4位数据一个容量是512K储存器芯片有8个数据引脚,请找出:(a)组织结构;(b)这个储存芯片的地址引脚数
(a)8个数据引脚可以保存8位数据,为了找出这个储存器芯片的位置数,需要用数据引脚数去除容量。512K/8=64K;所以储存芯片的组织结构是64K×8
(b)芯片有16根地址线,因为$2^{16}=64K$
随机访问储存器(RAM)
储存计算机运行中暂停的项目,当电脑关机时数据会丢失
总线设计
地址总线
cpu地址总线的数目决定了能与cpu进行通信的位置数,位置数通常等于$2^x$,x是地址线的数目。
每个位置最多可以有一个字节的数据,不用考虑数据总线的大小。
地址总线是单向的。
地址总线使用得越多,外设使用越多。
数据总线
数据总线是双向的,因为CPU需要使用它们接收和发送数据。使用的数据总线越多,CPU效率越高。
控制总线
向设备提供读取或写入信号,以提示CPU是否正在请求信息。
1 | ORG 0 |
pop代表把栈顶的值赋值给r几
例如pop 3就是把栈顶的值赋值给R3
1 | ORG 0 |
 
8051系统概述
8051控制器的内部框图
8501的主要特性
特性 | 数量 |
---|---|
ROM | 4KB |
RAM | 128KB |
定时器 | 2 |
I/O引脚 | 32 |
串行端口 | 1 |
中断源 | 6 |
8051及其成员对比
特性 | 8051 | 8052 | 8031 |
---|---|---|---|
ROM | 4KB | 8K | 0K |
RAM | 128KB | 256KB | 128KB |
定时器 | 2 | 3 | 2 |
I/O引脚 | 32 | 32 | 32 |
串行端口 | 1 | 1 | 1 |
中断源 | 6 | 8 | 6 |
大多数的8051单片机的寄存器是8位的,所以也叫8051为8位单片机
8051中常用的寄存器有A(累加器)、B、RO、R1、R2、R3、R4、R5、R6、R7、DPTR(数据指针)以及PC(程序计数器)寄存器。除DPTR和程序计数器是16位外,以上寄存器都是8位。
MOV指令
1 | MOV 目的操作数,源操作数 |
1.可直接将数值装载到A、B或R0~R7的任意意一个寄存器当中。然而,为表示装载的是立即数,必须在数值前加上符号(#),如下:
2.如果将0~F的值装载到8位寄存器中,则其余的位就默认为0.例如,对于指今MOV A,#5”而言,结果是A=05,用二进制表示就是A=00000101。
3.装载太大的值到寄存器中时会出错。(装载的值超过八位)
4.将数值装载到寄存器中时,必须在数值前加上符号(#),否则就表示装载的是存储器中的数。例如,MOV A,17H”指令代表的就是将存储单元17H中的数装载到A中,结果就是任意值。
ADD指令
1 | ADD A,源操作数; |
指令中的源操作数即可以是寄存器,也可以是立即数;
寄存器A必须存在于任何的算数运算中,但其只能是任何算术运算中的目的操作数而不能是源操作数。
8051汇编语言简介
1.汇编语言程序由一连串的汇编指令组成
2.一条汇编指令由4个字段组成
1 | [标签:] 助记符 [操作数] [;注释] |
助记符即为指令
3.方框号代表里面的字段是可选的,不是每条指令都必须包含
4.ADD和MOV就是助记符,即产生操作码的部分。ORG和END就是伪代码(指示符),这些指示符不产生任何机器代码(操作码),仅供汇编使用。
8051中的程序计数器和ROM空间
1.编写汇编语言需要将汇编程序写好写入asm文件中
2.asm源文件被送入8051汇编器,汇编器将指令换成机器代码,然后产生目标文件(obj)和列表(lst)文件
3.汇编器的第三步是链接:链接程序接受一个或多个目标文件并生成带有扩展名”abs”的绝对目标文件
4.将“abs”文件送入名为”OH”的程序(目标文件转16进制)中,从而产生即将烧入ROM中的扩展名位”hex”的文件。
- DOS EDIT编辑器产生asm文件
- 8051编译器产生obj和lst文件
- 链接器程序产生abs文件
- OH程序产生HEX文件
8051中的程序计数器和ROM空间
8051中的程序计数器(PC)
- 程序计数器指向下一条将执行指令的地址。
- 当CPU从程序ROM中得到操作码时,程序计数器就会自动增加并指向下一条指令
- 8051中的程序计数器为16位,能访问的程序地址范围是0000H~FFFFH,共64KB代码。
上电8051唤醒的位置
- 当上电后,8051程序计数器中的值就是0000,就表示第一个操作码存储在ROM地址0000H中。
- 8051系统中,第一个操作码就必须烧人程序ROM的存储位置0000H中,因为这是启动后它寻找第一条指令的位置。
8051数据类型和指令
BD
DB指令是汇编器中使用最广泛的数据指示符之一,它用于定义8位数据。
十进制后面的D是可选的,但是二进制的B和十六进制的H是必须加的。
汇编指示符
1.ORG:用于ROM中表示起始地址
2.EQU:用于定义常量,但是不占用系统空间
3.END:告诉汇编器源文件(asm)末尾所处的位置。END指令是8051程序的最后一位,意味着END指令之后的源代码都会被汇编器忽略。
8051标志位和PSW寄存器
8051中也有表示算数运算状态的标志寄存器,如进位标志
。
8051中的标志寄存器叫做程序状态字(PSW)寄存器
PSW(程序状态字)寄存器
PSW寄存器是一个8位寄存器,也叫标志寄存器,但是在8051中,PSW只用了6位,剩余两位是用户自定义标志位。
6为中有4位是状态标志位
也就是一些指令执行后的结果状态,分别是CY(进位)、AC(辅助进位)、P(奇偶校验位)以及OV(溢出位)
PSW.3和PSW.4位被分别设计为了RS0和RS1,用于选择组寄存器。
PSW.5和PSW.1是通用状态标志位,供程序员使用。
名称 | 位置 | 解释 |
---|---|---|
CY | PSW.7 | 进位标志 |
AC | PSW.6 | 辅助进位标志 |
F0 | PSW.5 | 可用于用户的通用目的 |
RS1 | PSW.4 | 寄存器组选择器位1 |
RS0 | PSW.3 | 寄存器组选择器位0 |
OV | PSW.2 | 溢出标志 |
— | PSW.1 | 用户可定义位 |
P | PSW.0 | 奇偶标志。通过硬件每条指令周期设置/清0 来指明是累加器中的奇/偶位数。 |
ADD指令和PSW
分析ADD指令对PSW寄存器中CY、AC以及P标志位的影响。
1 | MOV A,#38H |
相加之后:CY=0,因为D7位没有进位。
AC=1,因为有来自D3到D4位的进位
P=1,因为累加器有奇数个1(5个1)
8051寄存器组和栈
8051微控制器中共有128个字节的RAM
8051中的RAM存储分配
8051中有128个字节的RAM(一些成员,如8052,有256个字节的RAM),其所分配的地址范围是00~7FH。它们可直接作为存储器位置进行访问。这128个字节可分成如下三部分:
- 从00至1F(十六进制)共有32个字节用于寄存器组和栈
- 从20H至2FH共有16个字节用于位可寻址读/写存储器。
- 从30H至7FH共有80个字节用于读/写存储,也通常称为高速暂存器(scratch pad)。这80个RAM位置被8051程序员广泛应用于存储数据以及相关参数中。
第一组寄存器与栈使用的是同样的RAM空间。这点在8051编程时尤其要注意,要么回避使用第第一组寄存器,要要么分配另一块RAM区域给栈。
默认寄存器组
如果RAM位置00~1F地址被用于四个寄存器组,那么上电后可以访问的R0~R7的寄存器组就是寄存器组0
也就是说,当编写8051程序时,RAM位置0、1、2、3、4、5、6和7分别被名字为R0、R1、R2、R3、R4、R5、R6以及R7的符号进行访问。使用R0、R1等名字来访问RAM位置地址相比于用存储器位置访问容易得多。
如何切换寄存器组
8051上电后,默认寄存器组的是寄存器组0.但我们可以通过使用PSW寄存器切换到其他的寄存器组。PSW的D4位和D3位用于选择需要的寄存器组.。
8051中的堆
栈是RAM中的一段空间,为CPU暂时存储信息。这些信息可以是数据或是地址。CPU需要该存储区域是因为寄存器数目有限。
8051如何访问栈
如果栈是RAM的一段空间,CPU中就必须有指向这段空间的寄存器。用于访问栈的寄存器称为SP(栈指针)寄存器
。8051中的栈指针仅8位宽,这就意味能得到的值的范围是00~FFH。
当8051上电后,SP寄存器的值是07(因为默认寄存器组1的第一位为8),就意味着RAM位置08是8051栈的第一个位置。
将CPU寄存器中的值存人栈称为PUSH(压栈),从栈中取出值放入寄存器中称为POP(出栈),也就是说,一个寄存器被压人栈中就是保存数据,而从栈中弹出则是重新得到该数据。当进行压栈和出栈的操作时,SP的作用很重要。
压栈(push)
在8051中,栈指针指向栈的最后一个位置。如果将数据压入栈中,栈指针就自增1。
例如:PUSH 1;就是将R1中的数据压入堆栈中(第一次位置为08,压入后的位置是09)
1 | MOV R6,#25H |
出栈(POP)
每次弹出时,栈顶的字节会压入到所写寄存器中,同时栈指针自减一次。
例如:POP 3;就是将栈顶指针对应的字节压入R3中。
栈上限
8051的RAM位置地址范围08~1F用于栈,这是因为RAM位置地址20-2FH只能用于位可寻址存储,而不能用于栈。
如果某程序需要大于24字节(08~1FH=24字节)的栈,则可以改变SP指向RAM中30~7FH的位置。完成此操作的指令是:MOV SP,#xx
栈和寄存器组1的冲突
默认的寄存器组为寄存器0,默认栈的起始点为寄存器1的R0。
寄存器组1和栈使用的是同样的存储空间。如果一个程序需要使用寄存器组1和组2时,就必须重新分配RAM空间给栈。例如,可分配RAMM位置地址60H甚至更高的位置地址给栈。
1 | MOV SP,#5FH;RAM位置地址60H,即栈的第一个位置 |
提高CPU效率的方法
微处理器设计者可使用三种方法来提高CPU的处理效率。
- 增加芯片的时钟频率。这种方法的缺点是:频率越高,则功耗和热损耗就越大,功耗和散热对掌上型设备尤其是大问题。
- .通过增加导线成为哈佛体系结构,从而将更多的信息(代码和数据)装载到CPU中处理。而在x86和一些通用微处理器中,哈佛体系结构价格昂贵且不切实际,但是在今天的单芯片计算机中(微控制器),这已不是问题。
- 改变CPU的内部结构,使用RISC结构。
跳转、循环和调用指令
8051中的循环
在8051中,循环操作通过指令“DJNZ reg,label”来实现。该指令中,寄存器递减,如果非零,则跳转至标签所示的目标地址。在循环开始之前,寄存器预存人循环次数。
上诉代码所实现的功能为:
- 累加器清零
- 将3加入累加器中10次
注意:上述代码以R2为累加器,而R2为8位寄存器,它能储存的最大值为FHH(十进制的255),因此每次循环的最多次数也为256,如需更多的循环则需要进行循环的嵌套。
循环嵌套
上述代码实现的功能:
- 将数55H存入累加器ACC中
- 对累加器ACC执行700次取补码。
其他条件跳转指令
注意:重点记忆JZ
和JNC
所有的条件跳转指令都是短跳转指令
必须指出,所有的条件跳转指令都是短跳转指令,也就是说,跳转指令的目标地址必须在程序计数器(PC)的-128~+127字节之内。
无条件跳转指令
无条件跳转指令是一种不需要任何条件,程序就可以跳转到目标地址的指令。
在8051中,这样的指令有两种:长跳转(LJMP)指令和短跳转(SJMP)指令
LJMP(长跳转指令)
它是一个3字节指令,其中第一个字节是操作码,第二个和第三个字节表示16位目标地址。2字节的目标地址允许程序在存储单元00000H~FFFFH中任意跳转。
SJMP(短跳转指令)
它是一个2字节指令,第一个字节是操作码,第二个字节是目标地址的相对跳转地址。相对跳转地址的范围为00H~FFH,相对跳转地址又分为前向跳转地址和后向跳转地址,即在相对于当前PC地址的-128~+127字节存储器范围内。如果是前向跳转地址,则目标地址可以在距当前PC的127字节范围内;如果是后向跳转地址,则目标地址可以在距当前PC的-128字节范围内。
调用指令
另一个控制跳转指令是CALL指令,该指令用于调用子程序。子程序常用于完成经常实现的任务。这样做不仅可以节省存储器空间,而且让程序更加结构化。在8051系列中,有两种调用指令:长调用(LCALL)指令及绝对调用(ACALL)指令。
LCALL(长调用指令)
它是一个3字节指令,其中第一个字节是操作码,第二个和第三个字节是子程序人口地址。因此,长调用指令可以调用存放在8051中64KB程序存储器任意位置的子程序。
为保证8051在调用子程序执行结束后能够知道返回到哪里并继续执行,处理器自动将长跳转指令的下一条指令地址保存到栈中。当一个子程序被调用时,控制器跳转到该子程序,并且处理器将PC值保存到栈中,同时开始获取一条新的指令地址。当子程序执行结束时,返回指令RET将控制器返回到调用位置。
==每一个子程序都需要一条返回指令作为结束。==
RET指令的功能是将地址从栈中弹出并放入程序计数器中,从而恢复执行在CALL指令之后的指令。
ACALL(绝对调用指令)
由于ACALL是2字节指令,子程序的目标地址就必须在2KB字节范围内,这是因为2字节中只有11位表示地址。
8051芯片的延时
8051的机器周期
CPU执行指令时须花费一定的时钟周期,8051系列中,这些时钟周期就叫做机器周期(machine cycle,MC)。
最原始的8051中,1个机器周期可占用12个振荡器(时钟)周期。因此,要想计算8051的机器周期,我们采用1/12的晶振频率,然后再取倒数。
在一个时钟周期内,能运行的机器周期越多,当然效率就越高,如上图,从上到下机器运行的效率是逐渐增加的。
8051的延时计算
DELAY的子程序一般由两部分构成:
- 计数器设置
- 延时
增加延时时间的一种方式是在循环中使用NOP指令。NOP表示“空操作”,简单地浪费时间。
循环内套用循环延时
关于各种IC的延时计算
- 根据时钟周期与机器周期的比计算出,结合晶振频率计算出运行一个机器周期所需要的时间
- 计算延时函数中所运行机器周期的个数
- 如果是单个循环,则计算出的时间=循环所需的时间+循环外的指令运行时间;如果是嵌套循环,延时时间=内循环时间+外循环时间。它与所有其他延时循环一样,对它的延时计算只是约数,因为忽略了子程序的第一条及最后一条指令所产生的延时。
使用$符号和SSJMP表示跳转到自身
如果芯片中不存在要监视的程序,就需要使用跳转到自身指令使得微控制器不处于空闲状态。简单的做法是在JUMP后面写上$符号,代表跳转的位置也就是如下情况:
1 | HERE: SJMP HERE |
也可以如下使用:
1 | SJMP $ |
8051的I/O端口编程
8051中一共有4个端口可以进行I/O操作,即P0-P3,每个端口有8个引脚。
8051有40个引脚,其中32个引脚属于4个端口,余下的引脚分别是$V_{cc}$,GND,XTAL1,XTAL2,RST,EA,ALE/PROG和PSEN。
I/O端口引脚及其功能
所有端口在RESET(复位)时都配置成输入,并准备用作输入。
当第一个0写入某端口时,该端口便成为输出。若将该端口重新配置成输入,则必须将1送入该端口。若想将任何端口用做输入端口,则必须编程。
将个位读入进位标志
读取输出端口锁存内容
有些指令读取的是内部端口锁存内容而不是外部引脚的状态。如“ANL & P1,A”,执行该指令时会产生如下一系列的动作:
1.读取端口内部锁存内容,并将该数据传送给CPU。
2.将这些数据与寄存器A中的内容相与。
3.结果写入端口锁存。
4.端口引脚数据改变,内容与端口锁存内容一致。
80511寻址方式
CPU可使用多种方式访问数据。数据可存放在寄存器、存储器中,或者以立即数的形式存在。访问这些数据的不同方法称为寻址方式(addressing modes)。
8051共提供5种寻址方式,如下:
1.立即寻址方式;
2.寄存器寻址方式;
3.直接寻址方式;
4.寄存器间接寻址方式;
5.变址寻址方式
立即寻址方式
直接将源操作数加载至任意寄存器,注意:立即数必须加前缀“#”
寄存器寻址方式
寄存器寻址方式是将寄存器中的内容加载到另一个寄存器中,而不是操作数本身。如下所示:
直接寻址方式
1.RAM地址00~1FH分配给寄存器组和栈。
2.RAM地址20-2FH用于位可寻址空间保存单点数据。
3.RAM地址30~7FH用于保存字节数据。
使用直接寻址方式可以访问RAM的128字节,但通常情况下它只访问RAM地址30~7FH空间,这是因为寄存器组位置由名为RO~R7的寄存器访问,而RAM中除了寄存器空间之外再没有对应的名字。
在直接寻址方式中,存放在RAM存储器中的数据对应的地址就是指令中给出的地址。而在立即寻址方式中,指令执行的数据就是操作数本身。是否有前缀“#”是两种寻址方式的主要区别。如下例所示(注意没有百“#标志):
SFR寄存器
在8051单片机中,寄存器A、B、PSW和DPTR通常称为SFR(特殊功能寄存器)
关于SFR地址,需注意以下两点:
1.特殊功能寄存器地址范围是80H~FFH。地址大于80H的原因是00H~7FH地址属于8051内部RAM。
2.不是80H~FFH范围中的所有地址都用于SFR。未使用的保留,且不可被8051程序员使用。
寄存器间接寻址方式
在寄存器间接寻址方式中,寄存器可作为数据指针。若数据存在于CPU内部,则只能使用寄存器R0或R1将数据取出。当R0和R1用作指针保存RAM中的数据地址时,则须加上前级“@标志,如下所示:
简单解释是将一个寄存器中数据的地址加载到另一个寄存器中。而不是数据本身。
如上,我们如果不佳@,那么就会将后面寄存器中的数据进行操作,而不是地址。
变址寻址方式
变址寻址方式广泛用于访间8051单片机的ROM空间的查找表入口数据,指令是“MOVC A,@A+DPTR”。16位的寄存器DPTR和寄存器A存放在片上ROM中的数据元素地址,因为数据元素存放在8051ROM代码区,所以使用指令MOV C,而不是MOV。“C”指代码。该指令将寄存器A中的内容与16位寄存器DPTR中的内容相加,形成所需数据的16位地址,如下所示:
算术逻辑指令与程序
在8051中,为了将数值相加,就必须使用累加器(寄存器A),ADD指令如下:
1 | ADD A,源操作数;A = A + 源操作数 |
ADD指令
ADD指令的功能是将两个操作数相加,通常,目的操作数是寄存器A中的内容,而源操作数可以是立即数、寄存器中的内容或存储器中的内容。请记住,在8051汇编算术操作中不允许存储器-存储器式的操作。指令的执行将影响标志位AC、CY和P,这取决于执行的操作数。溢出标志位OV只有带符号数运算时才受影响。
ADDC以及16位数加法
当两个16位的操作数相加时,需注意进位。指令ADDC(带进位加法指令)自的功能就是把源操作数的内容和进位标志CY都加入累加器A中。如下是3CE7H+3B8DH的相加操作:
DA指令
8051中的DA(十进制加法调整)指令用于解决两个BCD码相加不是BCD码的问题。助记符有一个操作数,就是累加器“A当有必要时,DA指令将6加入低位或高位,否则就不干涉结果。如下所示。
DA操作总结
只能在ADD或ADDC指令执行之后才能执行。
1.若低位(4位)大于9,或AC=1,就将0110加入低4位。
2.若高位(4位)大于9,或CY=1,就将0110加入高4位。
事实上,AC(辅助进位)标志位除了用于纠正BCD加法之外,并无其他用处。例如,相加29H和18H,结果是41H,但这对于BDC码来说是错误的。
无符号数相减
1 | SUBB A,源操作数;A = A - 源操作数 -CY |
SUBB(带借位减法),CY=0
算术减法中,8051微处理器(几乎涵盖所有的CPU)采用的是补码的方法。每个CPU中都包含加法电路,而因为减法电路的设计复杂(占用太多晶体管),因此8051使用加法电路来实现减法。如果8051执行减法指令时,须预设置CY=0。CPU硬件执行SUBB无符号数减法指令的步骤如下。
1.得到减数源操作数的补码。
2.将值与被减数(A)相加。
3.进位反相。
无符号数乘法和除法
1 | MUL AB ;AXB,将16位结果分别放入B和A |
字节乘法中,其中一个操作数须放人寄存器A中,而另一个操作数则须放在寄存器B中,相乘后,结果分别放人寄存器A和B中,寄存器A保存低位字节,寄存器B保存高位字节。如下所示:225H与65H相乘的结果是16位数据,分别存入寄存器A和B中,如表所示。
无符号数相除
字节相除时,分子必须放在寄存器A中,分母放在寄存器B中。除法指令完成之后,商存放入寄存器A中,余数存人寄存器B中。如下列代码和表6-3所示。
CPL A(累加器取反)
此指令将寄存器内容的1变成0,反之亦然,所以称为取反(1’scomplement)。
比较指令
8051中含有比较指令。语法如下:
1 | CJNE 目的操作数,源操作数,相对地址 |