[例题] 指出下列指令的寻址方式
MOV A,R1 ;A←(R1) 寄存器寻址
ADD A,#05H ; A←(A)+立即数 05H 立即寻址 MOV A,@R1 ; A ←((R1)) 寄存器间接寻址 MOV 30H,4AH ; 30H ←(4AH) 直接寻址 MOVC A,@A+DPTR ;A←((A)+(DPTR)) 变址寻址
SJMP LP ; PC←(PC)+ 2 + 偏移量 相对寻址 MOV C, 65H ; Cy ← (65H)) 位寻址
【例】 MOV DPTR,#1234H ;(DPTR)=1234H 该指令也可以用两条8位数据传送指令实现: MOV DPH,#12H ;(DPH)=12H
MOV DPL,#34H ;(DPL)=34H,(DPTR)=1234H
例1:读下面程序,写出41H、42H单元内容 MOV R0, #40H MOV R1, #41H MOV A, #11H MOV 40H, #32H MOV @R1, A MOV 42H , @R0 解:(41H)=11H, (42H)=32H
例2:将片内RAM中30H~3FH单元的内容复制到50H~5FH单元中。 MOV R0,#30H ;30h → R0 MOV R1,#50H ;50h → R1 MOV R7,#10H ;10h → R7
LOOP:MOV A,@R0 ; ( (R0 )) →A
MOV @R1,A ; A → (R1 ) INC R0 ; (R0 )+1 →R0 INC R1 ; (R1 )+1 → R1
DJNZ R7,LOOP ; R7内容不为零转LOOP RET
例1 :已知外部RAM的88H单元有一个数x,试编程将x送外部RAM的1818H单元。 【解】:外部RAM中的数据是不能直接传送的,因此必须使用两次 MOVX 指令完成此操作。 ORG 2000H MOV R0,#88H ;为8位指针赋值 MOVX A,@R0 ;取 x 到累加器A
MOV DPTR,#1818H ;为16位指针赋值 MOVX @DPTR,A ;x 送RAM的1818h单元
已知RAM50h单元有一个0~9的数,试编程将它变成相应的ASCII码。 【解】:0~9的ASCII码是30h~39h,两者相差30h。 方法一:对50h单元的数据高四位组装一个30h。 mov r0,#50h ;指针赋值 mov a,#30h ;30h→A xchd a,@r0 ;(A)3~0↔(r0)3~0,在A中组成ASCII码 mov @r0,a ;A中的ASCII送回50h单元
例:设(30H)=X,(40H)=Y,试利用堆栈区域实现30H和40H单元中的数据交换
MOV SP,#60H ;设栈底的地址为60H PUSH 40H ; Y →(61H) PUSH 30H ; X →(62H) POP 40H ; X →(40H) POP 30H ; Y→(30H)
【例】编程将片内RAM中10H和20H单元的内容交换。 方法一:用交换指令。
XCH A,10H XCH A,20H XCH A,10H 方法二:用“MOV”指令。
MOV A,10H MOV 10H,20H MOV 20H,A 方法三:用堆栈。
PUSH 10H PUSH 20H POP 10H POP 20H
思考题:已知:(A)=A9H、(20H)= 98H,试问执行如下指令后累加器A和CY中的值是多少? CLR C
MOV A,#0A9H MOV R0,#20H MOV 20H,#98H SUBB A,@R0 执行结果: (A)= 11H,(PSW)=00H
【例】:已知M1、M2单元中存有两个16位无符号数x1 、x2 (低位在前)。试编程求x1+x2,并将结果放入M1、M1+1单元 (低8位在M1单元)。设两数之和不会超过16位(65535)。 【解】:
MOV R0,#M1 ;x1指针赋初值 MOV R1,#M2 ;x2指针赋初值 MOV A,@R0 ;取x1低8位送A ADD A,@R1 ;x1与x2低8位相加 MOV @R0,a ;低8位和送m1单元 INC R0
INC R1 ;修改指针
MOV A,@R0 ;取x1的高8位送A
ADDC A,@R1 ;x1与x2的高8位和Cy相加 MOV @R0,A ;结果送M1+1单元
【例】:试将A中的二进制数转换为3位BCD码,其中,百位数存放于31H单元,十位数和个位数压缩后存于30H单元中。 【解】: MOV B,#100 DIV AB
MOV 31H,A MOV A,#10 XCH A,B DIV AB SWAP A ADD A,B MOV 30H,A
已知:外部RAM的30H单元中有一个数AAH,现要将其高4位不变,低4位取反,试编程。
解1,利用MOVX A,@Ri指令: MOV R0,#30H 1 0 1 0 1 0 1 0 MOVX A,@R0 ⊕ 0 0 0 0 1 1 1 1 XRL A,#0FH 1 0 1 0 0 1 0 1 MOVX @R0,A
解2,利用MOVX A,@DPTR MOV DPTR,#0030H MOVX A,@DPTR XRL A,#0FH MOVX @DPTR,A
已知:在M1和M1+1单元有一个16位数(M1存低8位),试编程将其扩大2倍(设结果小于65535)。
解:扩大2倍可以用左移一位来实现。
CLR C ;清除Cy位 MOV R1,#M1 ;指针赋值 MOV A,@R1 ;取低8位数据 RLC A ;循环左移,Cy进低位,高位进Cy
MOV @R1,A ;移位后数据回送 INC R1 ;指针加一 MOV A,@R1 ;取高8位数据 RLC A ;循环左移Cy进低位 MOV @R1,A ;数据回送
【例】令片内RAM中DATA为起始地址的数据块中连续10个无符号数相加,并把和送到SUN单元(设其和小于256)。 ORG 1000H START:MOV R2,#0AH ;数据块长度10送计数器R2 MOV R0,#DATA ;数据块起始地址送指针R0 CLR A ;累加器清零 LOOP: ADD A,@R0 ;累加部分和 INC R0 DJNZ R2,LOOP ;若R2-1≠0则转LOOP继续 MOV SUN,A ;存累加和 END
例:试将00H位和7FH位中的内容互换。 【解】:两个位互换必须找一个位作为缓冲位。 MOV C,00H MOV 01H,C MOV C,7FH MOV 00H,C MOV C,01H MOV 7FH,C
已知:内部RAM 的M1、M2单元各有两个无符号的8位数。试编程比较其大小,并将大数送MAX单元。
【解】: MOV A,M1 ;操作数1送累加器A CJNE A,M2,LOOP ;两个数相比较 LOOP: JNC LOOP1 ;M1>=M2时转LOOP1 MOV A,M2 ;M1 【例】 已知16位二进制负数存放在R1R0中,试求 其补码,并将结果存在R3R2中。 CONT: CLR A MOV A,R0 ;读低8位 CPL A ;取反 ADD A,#01H ;加1 MOV R2,A ;存低8位 MOV A,R1 ;读高8位 CPL A ;取反 ADDC A,#80H ;加进位及符号位 MOV R3,A ;存高8位 RET 例:将R2中BCD码数转为二进制数存进R2 ORG 2000H BCD2B:MOV A, R2 ;取入口数据 ANL A, #0F0H ;取出十位 SWAP A ;高4位 低4位 MOV B, #0AH MUL AB ;十位乘10 MOV R3,A ;积暂存进R3 MOV A, R2;再取入口数据 ANL A, #0FH ;取出个位 ADD A, R3 MOV R2,A ;结果 R2 RET ;若不是子程序可用END 例:软件循环延时100mS(晶振12MHz) ☆ 1Tm =1uS 100mS = 100000 uS ☆ MOV Rn #data 和 NOP 是单机器周期指令 ☆ DJNZ Rn,rel 是双机器周期指令 ☆ 200 = 0C8H ; 248 = 0F8H ORG 1000H DELAY: MOV R6,#200 ; 1Tm LOOP1: MOV R7,#248 ; 1Tm NOP ; 1Tm LOOP2: DJNZ R7,LOOP2 ; 2Tm DJNZ R6,LOOP1 ; 2Tm RET ; 2Tm 例:软件循环延时1S(晶振12MHz) ☆ 1Tm =1uS 1S = 1000000 uS ☆ MOV Rn #data 是单机器周期指令 ☆ DJNZ Rn,rel 是双机器周期指令 ORG 1000H DL1S:MOV R7,#10 DL1: MOV R6,#200 DL2: MOV R5, #250 DL3: DJNZ R5, DL3 DJNZ R6,DL2 DJNZ R7,DL1 RET 例: 16进制数(00H—0FH)转ASCII码子程序 算法:凡≥10的十六进制数加37H;凡<10的十六进制数加 30H。 ie. 0~9 → 30H~39H, A~F → 41H~46H ORG 2000H H2ASC: MOV A,R2 ;取待转换的数据(入口) ADD A,#0F6H ;判此数是否≥10 ? 若≥10,则C=1;<10,则C=0 MOV A,R2 ;重取待转换的数据 JNC AD30H ;小于10就跳去加30H ADD A,#07H ;≥10就先加7 再去加30H AD30H: ADD A,#30H MOV R2,A ;存结果(出口) RET 例:根据16个双字节数的序号查表找出对应数据 ORG 2000H STA1: MOV A,R2 ;取待查数据的序号 X (入口) RL A ;每数占2个单元,序号要乘2 MOV R3,A ;R3 ← 序号 x2 (即偏移量) MOV DPTR,#TABL ;DPTR ← 表格首地址 MOVC A,@A+DPTR ;(A)← 查到数据低8位 XCH A,R3 ;数据低8位存进R3(出口) ;同时取出偏移量到A INC DPTR ;DPTR指向下一个单元 MOVC A,@A+DPTR ;再查到数据高8位 MOV R4,A ;将数据高8位存进R4(出口) RET TABL: DW 050FH, 0EH, 0A695H, 1EAAH, 0D9BH, 7F93H DW 0373H, 26D7H, 2710H, 9E3FH, 1A66H, 22E3H DW 1174H, 16EFH, 33E4H, 6CA0H END 例:求双字节补码程序 ORG 0100H MOV A, #80H ANL A, addr1 ;判断是否为正数 CJNE A, #0,TT SJMP LOOP TT: XRL addr1+1, #7FH ;除第一位异或取反 XRL addr1, #0FFH ;低八位取反 INC addr1 ;加1 MOV addr2, addr1 MOV A,#0 ADDC A, addr1+1 ;用ADDC MOV addr2+1, A LOOP: RET 例:利用外部中断0做一个计数器。当有脉冲时,A的内容加1。并且当A的内容大于或等于100时将P1.0置位. ORG 0000h LJMP MIN0 ORG 0003h LJMP INTB0 ORG 000bh RETI ORG 0013h RETI ORG 001bh RETI ORG 0023h RETI ORG 0030h MIN0: MOV SP,#30H SETB IT0 SETB EX0 CLR PX0 SETB EA MOV A,#00 Min1: NOP LJMP Min1 ORG 0100h INTB0: Push PSW ADD A,#01 CJNE A,#100,INTB1 LJMP INTB2 INTB1: JC INTB3 INTB2: SETB P1.0 INTB3: POP PSW RETI 例: 从P1.0 脚输出频率=1KHz方波。分析:fosc = 6MHz 1机器周期 = 2 S 1KHz方波周期 = 1 mS 半个方波周期 =500S 500uS÷2 uS = 250 设:晶振=6MHz。利用T1定时中断。 若选择模式2 工作,8位定时器最大数值为: 28 =256 =0FFH + 1 可以满足要求。 计算初值:256-250=6 ORG 0000H AJMP MAIN ORG 001BH ;T1的中断矢量 CPL P1.0 ;中断服务:P1.0取非 RETI ;中断返回 MAIN: MOV TMOD,#20H MOV TH0, #6 MOV TL0, #6 SETB ET1 SETB EA SETB TR1 HERE: AJMP HERE ;原地等待中断 END 例1:用T1产生一个50Hz的对称方波,由P1.l输出,采用程序查询方式,fosc=12MHz。 【解】:首先确定工作方式、工作模式和定时初值。 1,选定时方式(C/T=0); 2,模式1(M2 M1=01) , 3,方波周期T=l/50=O.02s=20ms,用T1定时10ms,计数初值为:X1=216-10×10-3×12×106/12=65536-10000=55536=D8F0H; 既TH1=D8H,TL1=F0H。 TMOD 0001 0000 源程序如下: ORG 0000h LJMP T1BUS ORG 0030h T1BUS: MOV TMOD,#10H ;T1模式1,定时 SETB TRl 启动T1 LOOP:MOV TH1,#0D8H ;T1计数初值 MOV TL1,#0F0H LOOP1: JNB TF1,LOOP1 ;T1没有溢出等待 CLR TF1 ;产生溢出清标志位 CPL P1.1 ;P1.l取反输出 SJMP LOOP ;循环 利用中断方式编程 ORG 0000h LJMP T1MIN ORG 001Bh LJMP LOOP ORG 0030h T1MIN: MOV TMOD,#10H ;T1模式1,定时 MOV TH1,#0D8H ;T1计数初值 MOV TL1,#0F0H SETB EA ;CPU、T1开中断 SETB ET1 SETB TRl ;启动T1 T1MIN2: NOP LJMP T1MIN2 ORG 0100h LOOP:MOV TH1,#0D8H ;T1计数初值 MOV TL1,#0F0H CPL P1.1 ;P1.l取反输出 RETI 例: 试编写由Pl.0输出一个周期为2分钟的方波信号的程序。已知fosc=12MHz。 解:此例要求P1.0输出的方波信号的周期较长,用一个定时器无法实现。解决的办 法可采用定时器加软件计数的方法 方法:将T1设置为定时器方式,定时时间为10ms(即10ms中断一次由CPU自动 调用一次中断服务程序),工作于模式1;再利用T1的中断服务程序作为软件计数器;共同实现一分钟的定时。 整个程序由两部分组成,即由主程序和T1的中断服务程序。其中主程序包括初始 化程序和Pl.0输出操作程序,中断服务程序包括毫秒(ms)、秒(s)、分(min)的定时等。 编写T1的中断服务程序时,应首先将T1初始化,并安排好中断服务程序中所用到 的内部RAM中地址单元。 T1计数初值: X=216-12×10×1000/12=55536=D8FOH。 中断服务程序所用到的地址单元安排如下: 40H作ms的计数单元,计数值为1s/10ms=100次; 4lH作s的计数单元,计数值为1min/1s=60次; 29H单元的D7位(位地址为4FH)作1分计时到的标志位,即标志用4FH 具体程序如下 主程序: ORG 0000H AJMP 0030H ORG 001BH AJMP 1100H ORG 0030H MOV TMOD,#10H ;T1定时,模式1 MOV TH1,#0D8H ;T1计数初值 MOV TL1,#0F0H SETB EA ;CPU、T1开中断 SETB ET1 SETB TR1 ;启动T1 MOV 40H,#100 ;毫秒计数初值 MOV 41H,#60 ;秒计数初值 CLR 4FH TT:JNB 4FH,TT ;等待1分钟到 CLR 4FH ;清分标志值 CPL Pl.0 ;输出变反 AJMP TT ;反复循环 T1中断服务程序:(由001BH转来) ORG 1100H PUSH PSW MOV TH1,#0D8H ;TI重赋初值 MOV TL1,#0F0H DJNZ 40H,TT1 ;1秒到否? MOV 40H,#100 ;1秒到,重赋秒的计数值 DJNZ 41H,TT1 ;1分到否? MOV 4lH,#60 ;1分到了,重赋1分钟的计数值 SETB 4FH ;置1分到标志位,告诉主程序。 TTl:POP PSW RETI ;中断返回 【例】因外中断INT0、INT1已被占用,试利用定时/计数器T0扩展成外中断。 解:利用定时/计数器T0扩展成外中断时须有两个条件: (1)是外部触发脉冲从P3.4输入(下降沿有效); (2)是将定时/计数器设置成计数临界状态,即定时初值为FFH,再来一个脉冲即能溢出触发中断。 编程如下: ORG 0000H ;复位地址 LJMP START ;复位,转初始化程序START ORG 000BH ;T0中断入口地址 LJMP IT0 ;转T0中断服务子程序IT0 ORG 1000H ;初始化程序首地址 START: MOV SP,#60H ;置堆栈 MOV TMOD,#06H ;置T0计数器方式2 MOV TH0,#0FFH ;置T0初值 MOV TL0,#0FFH ; SETB PT0 ;置T0为高优先级 MOV IE,#0FFH ;全部开中 SETB TR0 ;T0启动 SJMP MAIN ;转主程序,并等待T0中断 ORG 2000H ;T0中断服务子程序首地址 IT0: … ;T0中断服务子程序 RETI ; 例:发送程序发送一个字符,等待TI=1后再发送下一个字符。 1.查询方式: TRAM: MOV A,@R0 ;取数据 MOV SBUF,A ;发送一个字符 WAIT: JBC TI,NEXT ;等待发送结束 SJMP WAIT NEXT: INC R0 ;准备下一次发送 SJMP TRAM 2.中断方式: ORG 0023H ;串行口中断入口 AJMP SINT MAIN: … ;初始化编程 TRAM: MOV A,@R0 ;取数据 MOV SBUF,A ;发送第一个字符 H: SJMP H ;其它工作 SINT:CLR TI ;中断服务程序 INC R0 MOV A,@R0 ;取数据 MOV SBUF,A ;发送下一个字符 RETI 选用偶校验方式发送 PIPL: PUSH PSW ;保护现场 PUSH ACC CLR TI ;清发送中断标志以备下次发送 MOV A,@R0 ;取由R0所指向的单元中的数据 MOV C, P ;将奇偶标志位通过C放进TB8 MOV TB8, C ;一起发送出去 MOV SBUF,A ;启动发送 INC R0 ;指针指向下一个数据单元 POP ACC ;恢复现场 POP PSW RETI ;中断返回 选用偶校验方式接收: PIPL:PUSH PSW ;保护现场 PUSH ACC CLR RI ;清接收中断标志以备下次接收 MOV A,SBUF;读进收到的数据 MOV C, P ;奇偶标志位C =JNB P,L1 JNC L1 ;C=0时转到L1 P=0时转到L1 JNB RB8,ERR;P=1时转到L2,若RB8=0“出错” SJMP L2 ;RB8=1 则表明接收正确,转L2 L1: JB RB8,ERR;P=0且RB8=1表明“出错” L2: MOV @R0, A ;P=0且RB8=0表明接收正确 INC R0 ;指针指向下一个数据单元 POP ACC ;恢复现场 POP PSW ERR:出错处理…… RETI ;中断返回 RETI 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务