精品文档 你我共享
时程序。前面程序中已用过这样的程序,这里详细分析如下:
延时程序的功能相当于硬件定时器的功能。延时程序的延迟时间就是该程序的执行时间为512T(0FFH*2=512)。若取每条指令执行时间是T=1us (12MHZ),则最长的延时为512μs,故可采用双重循环程序实现延时100 ms。 程序如下:
ORG 4000H 指令延时 DEYPRG:MOV R2,#COUNTS ;置外循环计数器R2初值为COUNTS,如#0FFH 1μs LOOPS:MOV B,#COUNTR ;置内循环计数器B初值为COUNTR COUNTS﹡2μs LOOPR:DJNZ B,LOOPR ;内循环计数并判内循环结束否? COUNTR* COUNTS﹡2μs
DJNZ R2,LOOPS ;外循环计数并判外循环结束否? COUNTS﹡2μs END
下面计算COUNTR及COUNTS的值。设内循环程序的延时为500us,则COUNTR*2μs =500μs 于是可得COUNTR=250=0FAH,
外循环程序要求执行时间为100ms,则1μs +(500+2+2)μs *COUNTS=100 000μs 可得COUNTS=198.8取199=0C7H。此延迟程序的实际延迟时间为
[1+(502+2)*199]*1us=100.098ms 把每条指令执行次数乘指令周期即为总延时。
例3.11 设在单片机8031内部RAM的数据缓冲区存放一无符号数数组,其长度为100,起始地址为30H。要求将它们从大到小顺序排列,排序后存放在原数据缓冲区中,试编写相应的程序。
程序如下: ORG 4000H
BUBBLE:MOV RO,#30H ;置地址指针RO初值 MOV R2,#100 ;置长度计数器R2初值#64H CLR 10H ;交换标志位(10H单元)清0 DEC R2 ;长度计数
BULOOP:MOV A,@RO ;取比较的第一个数 MOV 20H, A ;暂存
INC RO ;修改指针R0,以指向下一单元 MOV 21H,@RO ;取数比较的第二个数
CJNE A,21H,BUNEU ;两个比较,若(20H)-(21H),转BUNEU BUNEU: JNC BUNEXT ;若(20H)≥(21H),则转BUNEXT MOV A,@RO ;若(20H)<(21H),则两者交换 MOV @RO,20H ;(20H)的数小送高地址
DEC RO
MOV @RO,A ; (21H)数大送低地址
INC RO ;恢复RO原值,准备下一次比较。 SETB 10H ;置交换标志位为1
BUNEXT:DJNZ R2, BULOOP ;长度计数器为0?若不为0,则继续比较 JB 10H,BUBBLE ;判交换标志。若为1,则继续循环 END ;为0则循环结束,完成排序
腹有诗书气自华
精品文档 你我共享
3.5.1、子程序结构
在程序设计的实践中,经常会遇到在不同的程序中或在同一程序不同的地方,要求实现某些相同的操作,如延时、代码转换、数制转换、检索与排序、函数计算以及对某些外设的实时控制等。
例3.15 十六进制数的ASCII码转换成相应的十六进制子程序SUBASH。
十六进制的ASCII码值不是连续的:0~9的ASCII码为30~39H此时只要将ASCII码值减去30H即可得到相应的十六进制数;而0AH~0FH的ASCII码为41H~46H,此时要将ASCII码值减去37H才是相应的十六进制数。由于本程序是子程序,所以(SP)及(SP)-1所指示的是返回地址,而(SP)-2所指示的才是欲转换的ASCII码,SUBASH子程序流程大家分析程序后自己画出。 ;子程序名称:SUBASH
;入口参数:被转换的十六进制数的ASCII码存放在(SP)-2所指示单元中 ;出口参数:转换后的十六进制数仍放在原单元中 ;所用寄存器:A,RO ;子程序清单:
SUBASH:MOV RO,SP ;SP值不能改变,否则不能正确返回 DEC RO DEC RO
XCH A,@RO ;从堆栈取出被转换的数送A CLR C
SUBB A,#3AH ;为0~9的ASCII码否?小于3AH?, 共减30H JC ASCDTG ;若是小于,则转ASCDTG
SUBB A,#07H ;若否,则再减去7,(A)-3A-7+0A=(A)-37 ASCDTG:ADD A,#0AH ;转换成十六进制数, XCH A,@RO ;转换后的十六进制数压入堆栈 RET 调用程序设计见下例。
例3.16 设有50个十六进制数的ASCII码存放在8031单片机内部RAM以30H为首址的连续单元中。要求将其转换成相应的十六进制数并存放到外部RAM以4100H为首址的25个连续单元中。根据上述要求,试编制SUBASH子程序的调用程序。 相应的程序如下: ORG 4000H
MAIASH: MOV RO,#2FH ;置取数指针RO初值, 从30H开始 MOV DPTR ,#40FFH ;置数据指针DPTR,下一个地址是4100H MOV SP,#20H ;置堆栈SP初值
MOV R2,#19H ;置循环计数器R2初值25 NELOOP: INC RO :修改RO
INC DPTR ;修改DPTR指下一个
MOV A,@RO ;取被转换时ASCII码并压入堆栈 PUSH ACC
ACALL SUBASH ;调用SUBASH子程序(上一例) POP IFH ;相应的十六进制数送1FH单元 INC RO ;修改RO
腹有诗书气自华
精品文档 你我共享
MOV A,@RO ;取被转换时ASCII码并压入堆栈 PUSH ACC
ACALL SUBASH ;调用SUBASH子程序 POP ACC ;相应的十六进制数送A
SWAP A ; 作高四位
ORL A,1FH ;合成两位十六进制数 MOVX @DPTR,A ;送存数单元
DJNZ R2,NELOOP ;转换结束否?若未完,则继续 SJMP $
在实际设计子程序入口及出口的参数传递方法时,可根据具体情况灵活处理,不必拘泥于采用一种方法。
3.5.3、查表及查表程序设计 1、查表
查表程序是一种常用程序,它广泛使用于LED显示器控制、打印要以及数据补偿、计算、转换等功能程序中,具有程序简单、执行速度快等优点。 查表,就是根据变量X在表格中查找Y,使Y=f(X)。
2、查表程序设计 下面介绍几种常用查表程序
例3.17 设有一个巡回检测报警装置,需对16路输入进行控制,每路有一个最大允许值,它为双字节。控制时,需根据测量的路数,找出该路的最大允许值。再判断输入值是否大于最大允许值,如大于则报警。
设路数为X(0≤X≤)Y为最大允许值,放在表格中。路数放在R2中。查表后,最大值放在R3,R4中。 程序如下:
ORG 4000H
4000H EA PM1: MOV A,R2 ;其值是:00H~0FH共十六字如04 4001H 2A ADD A,R2 ;(A)←(R2)×2,每数两个字节 4002H FB MOV R3,A ;(R3)←(R2)×2 =08 4003H 2406 ADD A,#6 ;加偏移量(400C-4006=#6)
4005H 83 MOVC A,@A+PC ;查第一字节 地址=400CH+8=4015H 4006H CB XCH A,R3 ;存第一字节33,准备取第二字节 4007H 2403 ADD A,#3 ;加偏移量(400C-400A+1=#3) 4009H 83 MOVC A,@A+PC ;查第二字节 400AH+0B=4016H 400AH FC MOV R4,A ;存第二字节88 400BH 22 RET
400CH 2520372142647560 TABI: DW 2520,3721,4264 ,7560 ;最大值表 4015H 3388326578839943 DW 3388,3265 ,7883,9943 401DH 1050405167858931 DW 1050,4051,6785, 8931 4025H 5468587132846688 DW 5468,5871,3284, 6688
本例程序中,表格长度不能超过256字节。若表格长度大于256字节,必须用MOVC A,@A+DPTR指令。
例3.18 在8031单片机内部RAM的LOC单元中存放一位非压缩BCD码,求其立方值并
腹有诗书气自华
精品文档 你我共享
将它存放到内部RAM的RESULT及RESULT+1单元中。试编制相应程序。
分析:
为了简化程序设计,数的立方值不是通过计算求得而是由查表求得。由于一位BCD码的是0~9,数9相应的立方值为729。如用压缩BCD码表示,则需用两个单元来存放。按上述假定可将0~9的立方值依次存入外部RAM以TABLE为首址的存储空间(即建立方表,表首址为TABLE)。某数立方值在表中的地址与表首址TABLE的关系为:
某数立方值第一字节地址=TABLE+2×该数 该数立方值第二字节地址=TABLE+2×该数+1
其中低地址单元中存放立方值的高位,高地址单元中存放立方值的低位,大家自画求某数立方值的流程图。
程序如下:
ORG 4000H
LOP DATA 50H ; 定义单元地址 RESULT DATA 60H ;定义结果第一字节地址 SUBRTE: MOV A,LOC ;取数 MOV R2,A ADD A,R2 ;该数×2 MOV R2,A ;暂存,以备后用 MOV DPTR,#TABLE; ;DPTR置立方值首址 MOVC A,@A+DPTR ;查表,得立方值的高位 MOV RESULT,A ;送结果 INC R2
MOV A,R2
MOVC A,@A+DPTR ;查表,得立方值的低位 MOV RESULT+1,A ;送结果
RET
TABLE: DW 0000H 0001H,0008H,001BH,0040H,… 3.5.4、散转程序及其设计
在设计单片机应用程序时经常遇到需要根据不同的输入或运算结果决定所执行的处理程序,即根据存储单元或寄存器的内容决定程序的流向,这就是散转程序。 2、散转程序的设计
下面通过具体例子介绍几种常用的散转程序设计方法。 (1)用转移指令表散转程序
例3.19 根据标志单元R2中的内容,分别转各个处理程序。 程序如下:
PJ1: MOV DPTR ,#TAB1 CLR C MOV A,R2
ADD A,R2 ;(R2) ×2←A JNC NADD
INC DPH ;(R2) ×2>256时,16位数据指针高8位加1 NADD: JMP @A+DPTR
TAB1: LJMP PRG0 ;转处理程序0的首地址
腹有诗书气自华
相关推荐: