《第14章MCS51程序设计及实用子程序.ppt》由会员分享,可在线阅读,更多相关《第14章MCS51程序设计及实用子程序.ppt(47页珍藏版)》请在三一文库上搜索。
1、第十四章 MCS-51程序设计及实用子程序,14.1 查表程序设计 14.2 数据极值查找和数据排序 14.3 散转程序设计 14.4 循环程序设计 14.5 定点数运算程序设计 14.6 数据的拆拼 14.7 码制转换,14.1 查表程序设计,查表程序是一种常用的非数值运算程序,应用广泛。 方法:该方法把事先计算的结果或实验数据按一定顺序编成表格,存于程序存储器内,然后根据输入参数值,从表中取得结果。 用途: 复杂代码转换显示 数据补偿:传感器补偿 复杂函数计算:Y=SIN(X) 特点:具有程序简单、执行速度快、精度高等优点,而这正是单片机在测控场合或智能化仪表中所需要的。,一、以DPTR为
2、基地址的查表程序,MOVC A,A+DPTR 操作步骤: 初始化DPTR: 将表格的首地址放入DPTR中,作为基地址。 初始化A: A中应该放所要查询的数据在表格中的顺序号。 执行结果: 在执行该指令后,A中存放的是在表格中查到的数据。,注意事项,在查询表格时,若所要查询的数据是双字节的,则在初始化A中的数应为顺序号的2倍,且应执行两次本指令。 对于单字节表格而言,表项的个数应不大于256个,若大于256时,则应适当修改DPTR的值。 表格的存放位置。表格可以设在64K程存的任何位置。,二、以PC为基地址的查表指令,MOVC A,A+PC,操作步骤:,用传送指令把所查数据在表格中顺序号送入累加
3、器A; 使用ADD A,#data指令对累加器A进行修正,data值由下式确定: data=数据表格首地址PC当前值 实际上data值等于查表指令和数据表格之间的字节数; 执行指令完成查表,结果存放在A中。,注意事项,对于双字节表格,其处理方法与以DPTR为基地址的情况相同。 对于单字节表格而言,其项数应不大于256。 对于双字节表格而言,其项数应不大于128。,三、两种方式的比较,PC仅能对所谓本地表格操作,即表格项数不得大于256,且偏移量可能随程序的变化而变化,计算较为麻烦,其优点是少用寄存器。 DPTR使用起来非常灵活,表项数不受限制,且表格可以放在64K的任意地方。,规则表 X的值为
4、:0,1,2,3,n Y的值为:y0,y1,y2,y3,yn y0,y1,。yn的字节长度一样,这种表格比较简单,可由y值按顺序构成表格。 查表方法: MOVC A,A+PC MOVC A,A+DPTR,四、表格形式,例:设有一个巡回检测报警装置,需对16路输入值进行比较,当每一路输入值等于或超过该路的报警值时,实现报警。 设Xi为路数,查表时Xi按0,1,2,15(i=15)取数,表中报警值是2字节数,依Xi顺序列成表格放在TAB中。进入查表程序前,路数Xi放在R2中,其输入值存于(R1R0)当中,查表结果放在(R4R3)中。若需报警,将P1.0口置1,否则清0。 报警值的单元地址=表格首地
5、址+(Xi*2),查表程序清单(方法1),TB1: MOV A, R2 ADD A, R2 ;A路数Xi*2 MOV R4, A ;保存 ADD A, #06H ; MOVC A, A+PC ;1 XCH A, R4 ;1 ADD A, #03H ;2 MOVC A, A+PC ;1 MOV R3,A ;1 RET ;1 TAB1: DW 05F0H,0E89H,0A695H,1EAAH DW 0D9BH,7F93H,0373H,26D7H DW 2710H,9E3FH,1A66H,22E3H DW 1174H,16EFH,33E4H,6CA0H,查表程序清单(方法2),ORG 1000H T
6、B1: MOV DPTR,#TAB1 ;DPTR表格首地址 MOV A, R2 ADD A, R2 ;A路数Xi*2 MOV R4,A MOVC A, A+DPTR ;取出高字节 XCH R4, A ;R4 高字节 INC DPTR MOVC A, A+DPTR ;取出低字节 MOV R3,A ;R3 低字节 CLR C MOV A,R0 ;当前输入值与报警值比较 SUBB A,R3 ;低字节相减 MOV A,R1 SUBB A,R4 ;高字节相减 JNC LOOP ;(C)=0,转移,报警 CLR P1.0 RET,查表程序清单(方法2)续,LOOP: SETB P1.0 RET ORG 2
7、000H TAB1: DW 05F0H,0E89H,0A695H,1EAAH DW 0D9BH,7F93H,0373H,26D7H DW 2710H,9E3FH,1A66H,22E3H DW 1174H,16EFH,33E4H,6CA0H,14.2 数据极值查找和数据排序,定义:数据极值查找就是在指定的数据区中找出最大值或最小值。 方法:比较交换法。,数据极值查找,例:从内存BLOCK单元开始有一个无符号数的数据块,块长度为LEN,试找出数据块中最大值,并存入MAX单元。,ORG 2000H LEN DATA 20H MAX DATA 22H MOV MAX,#00H ;MAX单元清零 MOV
8、 R0,#BLOCK ;数据块首地址送R0 LOOP: MOV A,R0 CJNE A,MAX,NEXT1;比较 NEXT1: JC NEXT ;若(A)(MAX),交换 NEXT: INC R0 DJNZ LEN,LOOP ;若未完,转LOOP SJMP $ END,数据排序,例:编写无符号数排序程序。 假设在片内RAM中,起始地址为40H的10个单元中存放有10个无符号数。试进行升序排序。,定义:数据排序是将指定数据区中的数据按升序或降序排列。 方法:冒泡排序法,解:R7:比较次数计数器,初始值为09H 位地址00H:数据互换的标志位 若(00H) =0,无互换发生,排序完毕。 (00H)
9、 =1,有互换发生。,程序流程图,14.3 散转(多分支)程序设计,散转程序是一种多分支选择程序。它根据某种输入或运算结果, 分别转向各个处理程序。在MCS-51单片机中,散转指令为JMP A+DPTR,它按照程序运行时决定的地址执行间接转移指令。,操作步骤: (1)将转移表首地址送入DPTR作为基地址。 (2)将条件标志单元内容装入A中作为变址,在装入前,还应根据转移表项内容作相应变化。 (3)实现程序转移。,根据转移表的不同可以分为三种散转程序:,一、使用转移指令表的散转程序,1.应用场合 根据标志单元的内容是0,1,n,分别转向处理程序0,处理程序1,处理程序n。 2.实现方法 用直接转
10、移指令(AJMP或LJMP指令)组成一个转移表,然后把标志单元的内容读入累加器A,转移表首地址放入DPTR中,再利用指令JMP A+DPTR实现散转。 散转点超过256时,对DPTR进行修正。,例:要求根据寄存器R7的内容转向各个处理程序。,即(R7)=0,转向PRG0 即(R7)=1,转向PRG1 即(R7)=2,转向PRG2 即(R7)=n,转向PRGn,程序清单,JUMP1: MOV DPTR,#JPTAB1 MOV A,R7 ADD A,R7 ;A(R7)*2 JNC NADD ;判断是否有进位 INC DPH ;有进位则加到高字节地址 NADD: JMP A+DPTR JPTAB1:
11、 AJMP PRG0 AJMP PRG1 AJMP PRGn,注意事项,(1)在上例中,由于AJMP指令的指令长度为2个字节,因而在散转时采用自加的方法使变址实现乘2;若改用LJMP指令,由于其指令长度为3字节,因而应使变址乘3来修正。当修正产生进位时,要将进位加到DPH中。 (2)由于使用了AJMP指令,PRG0、PRG1、等处理程序的入口与相应的AJMP指令必须在同一个2K范围内。 (3)由于R7是单字节,因而散转点不能大于256个。为了克服此局限性,可通过修改DPTR的办法来增加散转点。,二、使用地址偏移量表的散转程序,1.应用场合 转向的程序均在同一页(256字节),即转移表的大小与各
12、个处理程序的总长度必须小于256字节。 2.实现方法 利用指令JMP A+DPTR与伪指令DB汇编时的计算功能实现散转。 本方法的关键在于建立一个转向地址偏移量表(各处理程序首地址与表格首地址之间偏移量)。,例:要求按R7的内容转向5个处理程序。,JUMP3: MOV A,R7 MOV DPTR,#TAB3 MOVC A,A+DPTR JMP A+DPTR TAB3: DB PRG0-TAB3 DB PRG1-TAB3 DB PRG4-TAB3 PRG0: PRG1: PRG2: ,本例的散转范围小于256,同上例一样,本例也可通过变通的方法,使这能在64K范围内实现散转。,三、使用转向地址表
13、的散转程序,1.应用场合 转向范围较大时。 2.实现方法 建立转向地址表,它的表项为各个处理程序的入口地址。散转时使用查表指令,按某个单元的内容查表找到对应的转向地址,把它装入DPTR中,然后对累加器A清零,再利用指令JMP A+DPTR直接转向各个处理程序。,例:根据寄存器R7的内容转向相应的处理程序中去,设各处理程序入口地址分别为PRG0,PRG1,PRGn,MOV DPTR,#TAB4 ;指向地址表 MOV A,R7 ADD A,R7 ;A(R7*2) JNC NADD INC DPH ;若(R7*2)256,则加进位 NADD: MOV R3,A MOVC A,A+DPTR ;查转移地
14、址高8位 XCH A,R3 INC A MOVC A,A+DPTR ;查转移地址低8位 MOV DPL,A MOV DPH,R3 ;将转移地址赋给DPTR CLR A JMP A+DPTR ;实现散转,程序清单,TAB4: DW PRG0 ;低位字节在高地址 DW PRG1 DW PRG2 DW PRGn,程序清单(续),本例的散转范围为64K,但散转数n应小于256 (R7为8位)。可以通过双字节加法运算修改DPTR的方法来使散转点大于256个。,四、利用“RET”指令实现的散转程序,本方法的关键在于将处理子程序的目的地址压入椎栈,然后通过“RET”指令来将目的地址弹出到PC中,从而实现程序
15、转移。即利用RET指令来代替两个POP指令。 例:要求根据R7的内容转向各处处理程序,设各处理程序的转向地址分别为PRG0,PRG1,PRGn,JUMP5: MOV DPTR,#TAB5 MOV A,R7 ADD A,R7 ; A(R7*2) JNC NADD INC DPH NADD: MOV R3,A MOVC A,A+DPTR ;查高位地址 XCH A,R3 INC A MOVC A,A+DPTR PUSH ACC ;低位地址 PUSH 03H ;PUSH R3高位地址 RET ;转向地址PC,转移 TAB5: DW PRG0 ;转移地址表 DW PRG1 DW PRGn,程序清单,14
16、.4 循环程序设计,包含多次重复执行的程序段,循环结构使程序紧凑。 循环程序的构成及各个环节任务: 初始化部分 循环准备工作。如:清结果单元、 设指针、设循环控制变量初值等 循环体 循环工作部分:需多次重复处理 的工作 循环控制部分: 1.修改指针和循环控制变量。 2.检测循环条件:满足循环条件,继续循环,否则退出循环。 结束部分 处理和保存循环结果。,单重循环:循环体中不套循环。,例:求n个单字节数据的累加,设数据串已在43H起始单元,数据串长度在42H单元,累加和不超过2个字节。,SUM: MOV R0,#42H ;设地址指针 MOV A,R0 MOV R7,A ;循环计数器n CLR A
17、 ;结果单元清0 MOV R3,A ADD1:INC R0 ;修改指针 ADD A,R0 ;累加 JNC NEXT ;处理进位 INC R3 ;有进位,高字节加1 NEXT: DJNZ R7,ADD1 ;循环控制:数据是否加完? MOV 40H,A ;循环结束,保存结果 MOV 41H,R3 RET,多重循环:循环体中套循环结构。,例:延时程序设计,DELAY: MOV R7,#200 ;1个机器周期 DE1: MOV R6,#123 ;1200 NOP ;1200 DE2: DJNZ R6,DE2 ;2123200 DJNZ R7,DE1 ;2200 RET ;2,如晶体振荡器频率为12MH
18、z,则其延时时间为: 1+(1+1+2123+2)200+2=50.003ms 这是一个50ms的精确延时程序。,14.5 运算程序设计,一、多字节加法,例:设有两个4字节的二进制数2F5BA7C3H和14DF35B8H,分别放在以40H和50H为起始地址的单元中(低位在低地址),试编程求这个数之和,结果放在以40H为起始地址的单元中。,ORG 0000H LJMP MAIN ORG 0100H MAIN: MOV R0,#40H MOV R1,#50H MOV R7,#04H LCALL JASUB LJMP $ 以上为主程序,JASUB: CLR C JASUB1:MOV A,R0 ADD
19、C A,R1 MOV R0,A INC R0 INC R1 DJNZ R7,JASUB1 RET END,ADDC A,Rn ADDC A,direct ADDC A,Ri ADDC A,#data,多字节BCD码加法,与多字节加法程序类似,但需在加法指令后加一条十进制加法调整指令。主程序与前面相同。,DADD: CLR C JAD1: MOV A,R0 ADDC A,R1 DA A MOV R0,A INC R0 INC R1 DJNZ R7,JAD1 RET,ORG 0000H LJMP MAIN ORG 0100H MAIN: MOV R0,#40H MOV R1,#50H MOV R7
20、,#04H LCALL DADD LJMP $ 以上为主程序,二、多字节减法,多字节减法程序和多字节加法程序类似,只需将加法指令换为减法指令即可。 例:在43H40H依次存放被减数443ADD7BH;在53H50H中依次存放减数14DF35B8H,试编程求二者之差。,ORG 0000H LJMP MAIN ORG 0100H MAIN:MOV R0,#40H MOV R1,#50H MOV R7,#04H LCALL JIANSUB LJMP $ 以上为主程序,JIANSUB: CLR C JIAN1: MOV A,R0 SUBB A,R1 MOV R0,A INC R0 INC R1 DJN
21、Z R7,JIAN1 RET END 此程序也可以推广到N个字节的情况。,14.6 数据的拆拼,BBCD:MOV A,R0 ANL A,#0FH MOV R5,A MOV A,R0,ANL A,#0F0H SWAP A MOV R6,A RET,程序清单:,14.7 码制转换,在计算机内部,任何数据都是以二进制的形式存储,但是,当我们在作I/O操作时,往往需要其它形式的数据格式,如ASCII码、BCD码、八进制数等,这就需要做一些数据格式的互换操作。,一、ASCII码与二进制数的相互转换,二进制与ASCII码的相互关系为: 数字09对应的ASCII码为30H39H,即加30H 字母AF对应的A
22、SCII码为41H46H,即加37H,(1)ASCII到二进制的转换 通过以上介绍的二者之间的关系,不难画出流程图:,ASCTOHEX: MOV A,R2 CLR C SUBB A,#30H CJNE A,#0AH,NEXT NEXT: JC TOK SUBB A,#07H TOK: MOV R2,A RET,例:转换前R2为ASCII码,转换后R2为二进制。,(2)二进制到ASCII码,HEXTOASCII: MOV A,R2 ANL A,#0FH ;取低四位的二进制码 ADD A,#90H DA A ;若(R2)9,则加66H,且产生Cy ADDC A,#40H DA A MOV R2,A
23、 RET,例:转换前R2为二进制,转换后R2为ASCII码。,当二进制数0AH时,加30H即得相应的ASCII,当二进制数介于0AH、0FH之间(包括0AH、0FH),则加37H即得到相应的ASCII。下例为另一算法。,例:8位二进制转换成BCD码。,BINBCD1: MOV B,#100 DIV AB ;(A)=百位数 MOV R0,A INC R0 MOV A,#10 XCH A,B DIV AB ;(A)=十位数,(B)=个位数 MOV R0,A INC R0 XCH A,B MOV R0,A RET,程序名:BINBCD1 功能: 0FFH内的二进制数转换为BCD码 入口: A存要转换
24、的二进制数 出口: R0存放BCD数 百、十、个位数的地址,二、二进制数到BCD码的转换,子程序设计 子程序入口用标号作为子程序名; 调用子程序之前设置好堆栈,子程序嵌套须考虑堆栈容量; 提供足够的调用信息,如:子程序名、入口参数和出口参数等; 用返回指令RET结束子程序,并保证堆栈栈顶为调用程序的返回地址。,补充:子程序设计,子程序调用时的参数传递,入口参数:调用子程序之前,需要传给子程序的参数。 出口参数:子程序送回调用程序的结果参数。,参数传递方式: 寄存器传送参数 堆栈传送参数,设计子程序应满足通用性的要求,不针对具体数据编程。,1. 通过寄存器传递参数,这种方法应用最为广泛、也最易使
25、用,它是在调用子程序之前,对需要使用的寄存器预先修改后,再来调用子程序。,例:试编程对30H39H单元清零,MAIN: MOV R0,#30H MOV R7,#0AH LCALL SUBRT SUBRT: MOV A,#00H RESU: MOV R0,A INC R0 DJNZ R7,RESU RET,二、通过椎栈传递参数,MAIN: MOV 70H,#30H MOV 71H,#0AH PUSH 70H PUSH 71H LCALL SUBRT SUBRT:POP DPH POP DPL POP 07H ;R7 POP 00H ;R0 SUB1: MOV A,#00H,LOOP: MOV R0,A INC R0 DJNZ R7,LOOP PUSH DPL PUSH DPH RET 对于简单程序而言,这种方法反而较笨,较易引起混淆。,例:试编程对30H39H单元清零,查表程序设计,注意表格的设计:规则变量表和非 规则变量表; 数据极值查找和数据排序; 散转程序设计:三种转移表的设计及转移范围; 循环程序设计; 定点数运算程序设计; 码制转换; 子程序设计:参数传递的两种方法。,本章总结,本 章 结 束,
链接地址:https://www.31doc.com/p-2986196.html