收藏 分销(赏)

谈谈51单片机的指令字节数.doc

上传人:仙人****88 文档编号:12021555 上传时间:2025-08-28 格式:DOC 页数:14 大小:70.50KB 下载积分:10 金币
下载 相关 举报
谈谈51单片机的指令字节数.doc_第1页
第1页 / 共14页
谈谈51单片机的指令字节数.doc_第2页
第2页 / 共14页


点击查看更多>>
资源描述
谈谈51单片机的指令字节数 现在的单片机程序大多都用C语言来编写了,汇编看起来有点OUT了。可是有时候汇编却很有用,因为它执行的效率高,而且每条指令占用的字节数和时钟周期都是确定的,这对于查表编程及对时钟要求严格的地方来说,是非常有用的。在嵌入式操作系统的移植中,有一部分代码是得用汇编来写的,不过这跟今天要谈的内容无关。现有来谈谈MCS-51单片机的指令的字节数。 汇编语言的语句的格式为: 标号段: 操作码段 第一操作数,第二操作数 ;注释段 (如 START: MOV A,#00H ;把0赋给A) 其中操作码段是必段的,其他的段是根据不同的指令而不同,操作数段可以只有一个操作数,也可以有两个操作数,有时还会有三个操作数的情况。 在51单片机中,有单字节指令、双字节指令和三字节指令。只要理解了指令占用的这些字节都是用来存放哪些量的,那自然就会判断不同的指令是多少字节指令了。 1、操作码段占用一个字节。 2、8位立即数占用一个字节,16位立即数占用两个字节。 3、8位操作数地址占用一个字节,16位操作数地址占用两个字节。 4、CPU内部的各种寄存器不占用指令字节,如A, B, R0, R1, DPTR等。 现在就可以判断51的指令占用的字节数了: MOV A, R0 ; 这是单字节指令,其中MOV占用一个字节,A和R0是CPU内部寄存器,不占用指令字节。 MOV A, #07H ;这是双字节指令,其中MOV占用一个字节,8位立即数#07H占用一个字节。 MOV DPTR, #0106H ;这是三字节指令, MOV占用一个字节,16位立即数#0106H占用两个字节。 MOV 07H, #07H ;这是三字节指令,MOV占用一个字节,8位地址07H占用一个字节,8位立即数#07H占用一个字节。 关于 BCD 码减数求补的问题 2009-11-23 2:40 有这样一个问题: 汇编程序如下: ORG 0100H MOV R1, #50H MOV R0, #60H CLR C CALL BSUB MOV 40H, A . . . BSUB: MOV A, #9AH SUBB A, @R0 ADD A, @R1 DA A INC R0 INC R1 CPL C RET 问:其中 9AH 的作用是什么,能不能换成别的数! 问题补充:BCD 码减法程序。 ========================================================== 做而论道 回答:     | 五级 2009-8-29 09:58 这是 MCS-51 单片机的汇编语言,很多人都不懂的。 程序实现了 (50H)-(60H)-->(40H) 的 BCD 码减法运算;并且对源数据的地址指针进行了修正。 BCD码的运算之后,应(使用 DA A指令)进行十进制调整,将运算结果修正为 BCD 码; 只是 MCS-51 单片机的 DA A 指令只能放在加法之后,它对减法不起作用。 为此,BCD 码的减法必须变换成加法,才能用 DA A 指令进行十进制调整。 借用手表倒拨15分,和正拨45分,效果相同的方法,可将:     (50H) - (60H) 等效变换为:     (50H) + [100 - (60H)] 式中的 100,又等效写成 9AH,不信,你对它 DA A 试试,马上就是 100H,这就是 100 的 BCD码,你说它能写成别的数吗 ? ========================================================== 后记: 上面的回答,并没有得到提问者的青睐,看来还是没有说明白,下面再解释一下。 关于“减数求补”的问题,是 MCS-51 单片机的汇编语言中,特有的问题。 两个 BCD 码相减,如果想要得到 BCD 码形式的结果,就应该进行十进制调整。 但是 MCS-51 单片机的十进制调整指令 (DA A) 只能放在加法指令之后,它对减法不起作用。 为此,BCD 码的减法,必须变换成加法进行,才能使用 DA A 指令进行十进制调整。 减法怎么变换成加法呢?这里就涉及到“补数”的问题。 大家知道,钟表倒拨 15 分和正拨 45 分,效果是相同的。 那么,可通过: 60-15=45 求出 15 对 60 的补数 45。 而 2 位十进制数字的补数,要用如下公式进行计算: 99+1 - (减数) = 补数 (BCD码最大值为99,加1以后就溢出,在计算机溢出以后又回0,有个模的概念,9AH=99+1,正好是100,加个溢出值不影响本数,所以就为9A-减数,这和2进制的概念一样,2进制是FF-减数+1,而FF-减数就是取反,所以求补是取反加1,明白码?) 求出补数后,再把补数和被减数相加,得到的“和”就是原来要求出的“差”了。 注意:此时用的是加法。那么,现在就可以使用 DA A 指令进行调整了。 上面公式中的 100,可等效写成 9AH,当对它进行 DA A 调整后,它就会变成 100H。 9AH 和 100H,都是 100 的 BCD 码。 注意:求“补数”和求“补码”都是相同的。 例如,已知十进制减法运算是: 87 - 34 = 53 在单片机里面的计算步骤就是: 9AH -34H = 66H 87H + 66H = EDH DA A后得:153H 把进位 1 丢弃,结果就是 53 的 BCD 码 53H。 注意!DA A也会改变PSW中的进位标志位! 例如:示例:如果累加器中的内容为56H(01010110B),表示十进制数56的BCD码,寄存器3的内容为67H(01100111B),表示十进制数67的BCD码。进位标志为1,则指令 ADDC A,R3 DA A 先执行标准的补码二进制加法,累加器A的值变为0BEH,进位标志和辅助进位标志被清零。 接着,DA执行十进制调整,将累加器A的内容变为24H(00100100B),表示十进制数24的BCD码,也就是56、67及进位标志之和的后两位数字。DA指令会把进位标志置1,这表示在进行十进制加法时,发生了溢出。56、67以及1的和为124。 说白了:中断入口地址其实就是个地址而已!!!呵呵!! 也就是说,一旦有中断,硬件会使现在的主程序停止执行,而跳往中断入口地址,在中断入口地址处有 中断处理函数 ;等执行完中断处理函数之后,就返回到原先的地方继续执行!! 怎么会有中断的呢,,人家厂商做的,没办法,,更可恨的是,把中断入口地址从0003H 开始 ,每隔7 个单元 放一个 中断入口;;;依次是: 0003H——000BH——0013H——001B——0023H 怎么会中断的呢,,是你配置的(INT0,INT1,T0,T1,串口)中断类型; 怎么会跳转的呢??:是 硬件 自动跳到,不归你管啊!!! 要是隔着的那七个地址单元不过 写中断处理函数怎么办呢???那就先跳转到另一个空地上,等做好事情后再 调回来,,之后 再跳回到 程序停止的 地方!!! 呵呵!!!!!不知明白了没????? 关于单片机、嵌入式的学习,有时间看看 我的空间,,谢谢!!! 串行通信中,奇偶校验是什么意思 答: 并行接口是指数据的各位同时进行传送;串行通信是指数据一位位地顺序传送. 奇偶校验是为了防止在信号传输过程中出现误码,在需要传输的信息位以外添加一位校验位,奇校验是设定校验位为"1"或"0"使整个单元"1"的个数为奇数,偶校验则使"1"的个数为偶数. 当接受端发现受到信息的特征和校验位不一致时就丢弃那个单并要求发送端重发. 这种校验方法用于检验这个单元发生的1位误码,如果错误码多于一位就失去了检错的作用. 表示信号传输实际有效速度的是比特率,即单位时间内传输的二进制码的有效位数(如bit/s). 而波特率是指信号对载波的调制速率,载波调制信号用载波的不同调制状态来表示二进制的信号,如单相调制有两个状态,分别表示"0"和"1", 四相调制有4个状态 表示二位二进制数"00", "01", "10"和"11",八相调制有3位,以此类推. 因此,单相调制的波特率和比特率相等,四相调制的比特率是波特率的2倍,八相是3倍.....kpt希望采纳我的 三角波,梯形波,正旋波的产生 8.1 利用dac0832产生三角波 程序介绍:单片机通过DAC0832转换在LM358的7脚输 出三角波。实际应用如:函数波形发生器。 程序实例(0832shan.asm): ORG 0000H MAIN: MOV DPTR,#0BFFFH ;选通地址 STR1: MOV R6,#00H ;通过上升和下降来产生三角波/////////////////// ;电压随时间上升/////////////////////////////// STR2: MOV A,R6 MOVX @DPTR,A INC R6 CJNE R6,#0FFH,STR2 ;///////////////////////////////////////////// ;电压随时间下降/////////////////////////////// STR3: DEC R6 MOV A,R6 MOVX @DPTR,A CJNE R6,#00H,STR3 ;///////////////////////////////////////////// AJMP STR1 END 8.2 利用dac0832产生方波 程序介绍:程序介绍:单片机通过DAC0832转换在 LM358的7脚输出方波。实际应用如:函数波形发生器。 程序实例(0832fan.asm): ORG 0000h MAIN: MOV DPTR,#0BFFFH ;通过高低电平地的变化来输出方波/////////// LOOP1: MOV A,0 MOVX @DPTR,A ;向选通地址送低电平地 ACALL DELAY MOV A,#0FFH MOVX @DPTR,A ;向选通地址送高电平 ACALL DELAY AJMP LOOP1 ;///////////////////////////////////////////// DELAY: MOV 30H,#0FFH ;延时,通过改变它的大小 可以改变占空比 D2: DJNZ 30H,D2 RET END 8.3 利用dac0832产生正弦波 程序介绍:程序介绍:单片机通过DAC0832转换在 LM358的7脚输出正弦波。实际应用如:函数波形发生器。 程序实例(0832xuan.asm): ORG 000H MAIN: MOV R1,#00H ;取表格初值 LOOP1: ;在表格里取数送到指定地址///////////////////// MOV A,R1 MOV DPTR,#SETTAB MOVC A,@A+DPTR MOV DPTR,#0BFFFH MOVX @DPTR,A ;///////////////////////////////////////////// INC R1 ;表格加一 AJMP LOOP1 ;循环 SETTAB: ;正弦表格///////////////////////////////////// DB 80H,83H,86H,89H,8DH,90H,93H,96H DB 99H,9CH,9FH,0A2H,0A5H,0A8H,0ABH,0AEH DB 0B1H,0B4H,0B7H,0BAH,0BCH,0BFH,0C2H,0C5H DB 0C7H,0CAH,0CCH,0CFH,0D1H, 0D4H,0D6H,0D8H DB 0DAH,0DDH,0DFH,0E1H,0E3H, 0E5H,0E7H,0E9H DB 0EAH,0ECH,0EEH,0EFH,0F1H, 0F2H,0F4H,0F5H DB 0F6H,0F7H,0F8H,0F9H,0FAH, 0FBH,0FCH,0FDH DB 0FDH,0FEH,0FFH,0FFH,0FFH, 0FFH,0FFH,0FFH DB 0FFH,0FFH,0FFH,0FFH,0FFH, 0FFH,0FEH,0FDH DB 0FDH,0FCH,0FBH,0FAH,0F9H, 0F8H,0F7H,0F6H DB 0F5H,0F4H,0F2H,0F1H,0EFH, 0EEH,0ECH,0EAH DB 0E9H,0E7H,0E5H,0E3H,0E1H, 0DEH,0DDH,0DAH DB 0D8H,0D6H,0D4H,0D1H,0CFH, 0CCH,0CAH,0C7H DB 0C5H,0C2H,0BFH,0BCH,0BAH, 0B7H,0B4H,0B1H DB 0AEH,0ABH,0A8H,0A5H,0A2H, 9FH, 9CH, 99H DB 96H, 93H, 90H, 8DH, 89H, 86H, 83H, 80H DB 80H, 7CH, 79H, 78H, 72H, 6FH, 6CH, 69H DB 66H, 63H, 60H, 5DH, 5AH, 57H, 55H, 51H DB 4EH, 4CH, 48H, 45H, 43H, 40H, 3DH, 3AH DB 38H, 35H, 33H, 30H, 2EH, 2BH, 29H, 27H DB 25H, 22H, 20H, 1EH, 1CH, 1AH, 18H, 16H DB 15H, 13H, 11H, 10H, 0EH, 0DH, 0BH, 0AH DB 09H, 08H, 07H, 06H, 05H, 04H, 03H, 02H DB 02H, 01H, 00H, 00H, 00H, 00H, 00H, 00H DB 00H, 00H, 00H, 00H, 00H, 00H, 01H, 02H DB 02H, 03H, 04H, 05H, 06H, 07H, 08H, 09H DB 0AH, 0BH, 0DH, 0EH, 10H, 11H, 13H, 15H DB 16H, 18H, 1AH, 1CH, 1EH, 20H, 22H, 25H DB 27H, 29H, 2BH, 2EH, 30H, 33H, 35H, 38H DB 3AH, 3DH, 40H, 43H, 45H, 48H, 4CH, 4EH DB 51H, 55H, 57H, 5AH, 5DH, 60H, 63H, 66H DB 69H, 6CH, 6FH, 72H, 76H, 79H, 7CH, 80H END 8.4 利用dac0832产生梯形波 程序介绍:程序介绍:单片机通过DAC0832转换在 LM358的7脚输出梯形波。实际应用如:函数波形发生器。 程序实例(0832ti.asm): ORG 0000h MAIN: MOV DPTR,#0BFFFH STEP: MOV R6,#19H MOV R4,#0AH MOV A,0 LOOP1: MOVX @DPTR,A ;选通地址 ACALL DELAY ;延时 ADD A,R6 ;每次以19H的梯度增加 DJNZ R4,LOOP1 ;梯度等待的时间 AJMP STEP ;循环 DELAY: D2: MOV 31H,#0FFH D1: DJNZ 31H,D1 RET END MCS-51单片机在执行短调用指令(ACALL)时,在调用操作之前为什么PC要先加2? 首先要明白什么是PC。 PC(Program Counter),是程序计数器,是一个16位的专用寄存器,用来存放下一条指令的地址。它具有自动加一的功能(注意这里的一是指地址的增加一个单元)。当CPU 要取指令时,PC的内容首先送至地址总线上,然后再从存储器中取出指令,取指令后,PC内容自动加1,指向下一条指令的地址(这句话很关键)。 ACALL是子程序调用指令,它本身占2个字节的存储单元。为了保证子程序返回后程序按原来的次序运行,所以PC内容要先加2,指向ACALL指令后的单元,以便顺序执行。 【转】谈谈51单片机延时子程序 延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器周期和指令周期的区别,不知道延时程序指令的用法,本文就此问题从延时程序的基本概念、机器周期和指令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者。 我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。例如在交通灯的控制程序中,需要控制红灯亮的时间持续30秒,就可以通过延时程序来完成。延时程序是如何实现的呢?下面让我们先来了解一些相关的概念。 一、机器周期和指令周期 1.机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51单片机的一个机器周期包括12个时钟振荡周期,也就是说如果51单片机采用12MHz晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz的晶振,那么执行一个机器周期就需要2μs。 2.指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。 在51单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。也就是说,如果51单片机采用的是12MHz晶振,那么它执行一条指令一般只需1~2微秒的时间;如果采用的是6MH晶振,执行一条指令一般就需2~4微秒的时间。 现在的单片机有很多种型号,但在每个型号的单片机器件手册中都会详细说明执行各种指令所需的机器周期,了解以上概念后,那么可以依据单片机器件手册中的指令执行周期和单片机所用晶振频率来完成需要精确延时时间的延时程序。 二、延时指令 在单片机编程里面并没有真正的延时指令,从上面的概念中我们知道单片机每执行一条指令都需要一定的时间,所以要达到延时的效果,只须让单片机不断地执行没有具体实际意义的指令,从而达到了延时的效果。 1.数据传送指令 MOV 数据传送指令功能是将数据从一个地方复制、拷贝到另一个地方。 如:MOV R7,#80H;将数据80H送到寄存器R7,这时寄存器R7里面存放着80H,就单这条指令而言并没有任何实际意义,而执行该指令则需要一个机器周期。 2.空操作指令 NOP 空操作指令功能只是让单片机执行没有意义的操作,消耗一个机器周期。 3.循环转移指令 DJNZ 循环转移指令功能是将第一个数进行减1并判断是否为0,不为0则转移到指定地点;为0则往下执行。 如:DJNZ R7,KK ;将寄存器R7的内容减1并判断寄存器R7里的内容减完1后是否为0,如果不为0 则转移到地址标号为KK的地方;如果为0则执行下一条指令。这条指令需要2个机器周期。 利用以上三条指令的组合就可以比较精确地编写出所需要的延时程序。 三、1秒延时子程序、流程图及时间计算(以单片机晶振为12MHz为例,1个机器周期需要1μs) 了解了以上的内容,现在让我们来看看 程序总共所需时间:1+10+2560+330240+660480+5120+20+2=998433μs≈1s 在这里运行这段程序共需998433μs,还差1567μs才达到1s的,所以想要达到完美的1s延时,需要在返回指令RET前再添加一些指令让它把1567μs的延时完成。有兴趣的读者可以自己试着添加完成。 最后补充一点,编写程序时一般将延时程序编写成独立的子程序,而所谓子程序也就是一个实现某个功能的小模块。这样在主程序中就可以方便地反复调用编写好的延时子程序。 小提示:循环转移指令(DJNZ)除了可以给定地址标号让其跳转外,还可以将地址标号改成$,这样程序就跳回本指令执行。例如: DJNZ R7,$ ;R7内容减1不为0,则再次执行本指令;为0则往下执行,当R7的值改为10时,则执行完该条程序所需的时间为2*10=20μs。 ------------------------------------------------------------------------------------------------------------------ 51单片机汇编延时程序算法详解 将以12MHZ晶振为例,详细讲解MCS-51单片机中汇编程序延时的精确算法。    指令周期、机器周期与时钟周期 指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。 时钟周期:也称为振荡周期,一个时钟周期=晶振的倒数。 MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。 MCS-51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12×(1/12000000)=1μs。   程序分析 例1 50ms延时子程序:   DEL:MOV R7,#200 ①   DEL1:MOV R6,#125 ②   DEL2:DJNZ R6,DEL2 ③   DJNZ R7,DEL1 ④   RET ⑤ 精确延时时间为:1+(1*200)+(2*125*200)+(2*200)+2 =(2*125+3)*200+3 ⑥ =50603μs≈50ms 由⑥整理出公式(只限上述写法)延时时间=(2*内循环+3)*外循环+3 ⑦ 详解:DEL这个子程序共有五条指令,现在分别就每一条指令被执行的次数和所耗时间进行分析。 第一句:MOV R7,#200 在整个子程序中只被执行一次,且为单周期指令,所以耗时1μs 第二句:MOV R6,#125 从②看到④只要R7-1不为0,就会返回到这句,共执行了R7次,共耗时200μs 第三句:DJNZ R6,DEL2 只要R6-1不为0,就反复执行此句(内循环R6次),又受外循环R7控制,所以共执行R6*R7次,因是双周期指令,所以耗时2*R6*R7μs。 例2 1秒延时子程序:   DEL:MOV R7,#10 ①   DEL1:MOV R6,#200 ②   DEL2:MOV R5,#248 ③   DJNZ R5,$ ④   DJNZ R6,DEL2 ⑤   DJNZ R7,DEL1 ⑥   RET ⑦   对每条指令进行计算得出精确延时时间为: 1+(1*10)+(1*200*10)+(2*248*200*10)+(2*200*10)+(2*10)+2 =[(2*248+3)*200+3]*10+3 ⑧ =998033μs≈1s 由⑧整理得: 延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+3⑨ 此式适用三层循环以内的程序,也验证了例1中式⑦(第三层循环相当于1)的成立。 注意,要实现较长时间的延时,一般采用多重循环,有时会在程式序里加入NOP指令,这时公式⑨不再适用,下面举例分析。   例3仍以1秒延时为例   DEL:MOV R7,#10 1指令周期1 DEL1:MOV R6,#0FFH 1指令周期10 DEL2:MOV R5,#80H 1指令周期255*10=2550 KONG:NOP 1指令周期128*255*10=326400 DJNZ R5,KONG 2指令周期2*128*255*10=652800 DJNZ R6,DEL2 2指令周期2*255*10=5110 DJNZ R7,DEL1 2指令周期2*10=20 RET 2 延时时间=1+10+2550+326400+652800+5110+20+2 =986893μs约为1s 整理得:延时时间=[(3*第一层循环+3)*第二层循环+3]*第三层循环+3 ⑩ 结论:针对初学者的困惑,对汇编程序的延时算法进行了分步讲解,并就几种不同写法分别总结出相应的计算公式,只要仔细阅读例1中的详解,并用例2、例3来加深理解,一定会掌握各种类型程序的算法并加以运用。 --------------------------------------------------------------------------------------------------------- 1)延时为:20ms 晶振12M 1+(1+2*248+2)*4+1+1+1=20000US=20MS 用汇编..优点就是精确...缺点就是算有点复杂. DELAY20MS: MOV R7,#4 D1:MOV R6,#248 DJNZ R6,$ DJNZ R7,D1 NOP NOP RET 2)0.1s延时子程序(12MHz晶振): MOV R7,#200 ;单周期指令(1us) D1: MOV R6,#250 ;单周期指令(1us) DJNZ R6,$ ;双周期指令(2us)//该指令自身执行R6次 DJNZ R7,D1 ;双周期指令(2us)//D1执行R7次 RET ;双周期指令(2us) T=1+(1+2*R6+2)*R7+2 =100603us ≈0.1s 3)0.5s延时子程序(12MHz晶振): MOV R7,#5 ;单周期指令(1us) D1: MOV R6,#200 ;单周期指令(1us) D2: MOV R5,#250 ;单周期指令(1us DJNZ R5,$ ;双周期指令(2us)//该指令自身执行R5次 DJNZ R6,D2 ;双周期指令(2us)//D2执行R6次 DJNZ R7,D1 ;双周期指令(2us)//D1执行R7次 RET ;双周期指令(2us) T=1+[1+(1+2*R5+2)*R6+2]*R7+2 =503018us ≈0.5s 有一段示例程序开始是: ORG 0000H AJMP MAIN ORG 0030H 我查了ORG是为了给汇编以后的机器代码定位,可是ORG 0000H定位程序从0000H开始存放,之后就跳转到MAIN程序了啊,那后面一条ORG 0030H定位语句有什么作用 ORG是个用于定位的伪指令。 简单的说就是把从这句话开始直到下一个ORG指令或者END指令前的程序语句都顺序放在它指定的地址里。比如说你的程序里ORG只管了一个语句(AJMP MAIN),则从0000h这个地址开始放语句。放多少,看下面有几条语句(直到org或end 指令为止)。 同样ORG 0030H是把它后面的所有到下一个ORG或END命令前的所有代码都顺序放到从0030H开始的程序单元。这应该是一个子程序。就像C语言里的子函数
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服