《第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为基地址的查表程序,MOV
2、CA,A+DPTR操作步骤:初始化DPTR:将表格的首地址放入DPTR中,作为基地址。初始化A:A中应该放所要查询的数据在表格中的顺序号。执行结果:在执行该指令后,A中存放的是在表格中查到的数据。,注意事项,在查询表格时,若所要查询的数据是双字节的,则在初始化A中的数应为顺序号的2倍,且应执行两次本指令。对于单字节表格而言,表项的个数应不大于256个,若大于256时,则应适当修改DPTR的值。表格的存放位置。表格可以设在64K程存的任何位置。,二、以PC为基地址的查表指令,MOVC A,A+PC,操作步骤:,用传送指令把所查数据在表格中顺序号送入累加器A;使用ADD A,#data指令对累加器
3、A进行修正,data值由下式确定:data=数据表格首地址PC当前值 实际上data值等于查表指令和数据表格之间的字节数;执行指令完成查表,结果存放在A中。,注意事项,对于双字节表格,其处理方法与以DPTR为基地址的情况相同。对于单字节表格而言,其项数应不大于256。对于双字节表格而言,其项数应不大于128。,三、两种方式的比较,PC仅能对所谓本地表格操作,即表格项数不得大于256,且偏移量可能随程序的变化而变化,计算较为麻烦,其优点是少用寄存器。DPTR使用起来非常灵活,表项数不受限制,且表格可以放在64K的任意地方。,规则表 X的值为:0,1,2,3,n Y的值为:y0,y1,y2,y3,
4、yn y0,y1,。yn的字节长度一样,这种表格比较简单,可由y值按顺序构成表格。查表方法:MOVCA,A+PCMOVCA,A+DPTR,四、表格形式,例:设有一个巡回检测报警装置,需对16路输入值进行比较,当每一路输入值等于或超过该路的报警值时,实现报警。设Xi为路数,查表时Xi按0,1,2,15(i=15)取数,表中报警值是2字节数,依Xi顺序列成表格放在TAB中。进入查表程序前,路数Xi放在R2中,其输入值存于(R1R0)当中,查表结果放在(R4R3)中。若需报警,将P1.0口置1,否则清0。报警值的单元地址=表格首地址+(Xi*2),查表程序清单(方法1),TB1:MOV A,R2AD
5、D A,R2;A路数Xi*2MOV R4,A;保存ADD A,#06H;MOVC A,A+PC;1XCH A,R4;1ADD A,#03H;2MOVC A,A+PC;1 MOV R3,A;1RET;1TAB1:DW05F0H,0E89H,0A695H,1EAAH DW0D9BH,7F93H,0373H,26D7HDW2710H,9E3FH,1A66H,22E3HDW1174H,16EFH,33E4H,6CA0H,查表程序清单(方法2),ORG1000HTB1:MOV DPTR,#TAB1;DPTR表格首地址MOVA,R2ADDA,R2;A路数Xi*2MOV R4,AMOVCA,A+DPTR;取
6、出高字节XCH R4,A;R4 高字节 INC DPTRMOVCA,A+DPTR;取出低字节 MOVR3,A;R3 低字节CLRCMOVA,R0;当前输入值与报警值比较SUBBA,R3;低字节相减MOVA,R1SUBBA,R4;高字节相减JNCLOOP;(C)=0,转移,报警CLRP1.0RET,查表程序清单(方法2)续,LOOP:SETBP1.0RETORG2000HTAB1:DW05F0H,0E89H,0A695H,1EAAHDW0D9BH,7F93H,0373H,26D7HDW2710H,9E3FH,1A66H,22E3HDW1174H,16EFH,33E4H,6CA0H,14.2 数据
7、极值查找和数据排序,定义:数据极值查找就是在指定的数据区中找出最大值或最小值。方法:比较交换法。,数据极值查找,例:从内存BLOCK单元开始有一个无符号数的数据块,块长度为LEN,试找出数据块中最大值,并存入MAX单元。,ORG 2000HLEN DATA 20HMAX DATA 22HMOV MAX,#00H;MAX单元清零MOV R0,#BLOCK;数据块首地址送R0LOOP:MOV A,R0CJNE A,MAX,NEXT1;比较NEXT1:JC NEXT;若(A)(MAX),交换NEXT:INC R0DJNZ LEN,LOOP;若未完,转LOOPSJMP$END,数据排序,例:编写无符号
8、数排序程序。假设在片内RAM中,起始地址为40H的10个单元中存放有10个无符号数。试进行升序排序。,定义:数据排序是将指定数据区中的数据按升序或降序排列。方法:冒泡排序法,解:R7:比较次数计数器,初始值为09H位地址00H:数据互换的标志位 若(00H)=0,无互换发生,排序完毕。(00H)=1,有互换发生。,程序流程图,14.3 散转(多分支)程序设计,散转程序是一种多分支选择程序。它根据某种输入或运算结果,分别转向各个处理程序。在MCS-51单片机中,散转指令为JMP A+DPTR,它按照程序运行时决定的地址执行间接转移指令。,操作步骤:(1)将转移表首地址送入DPTR作为基地址。(2
9、)将条件标志单元内容装入A中作为变址,在装入前,还应根据转移表项内容作相应变化。(3)实现程序转移。,根据转移表的不同可以分为三种散转程序:,一、使用转移指令表的散转程序,1.应用场合 根据标志单元的内容是0,1,n,分别转向处理程序0,处理程序1,处理程序n。2.实现方法用直接转移指令(AJMP或LJMP指令)组成一个转移表,然后把标志单元的内容读入累加器A,转移表首地址放入DPTR中,再利用指令JMP A+DPTR实现散转。散转点超过256时,对DPTR进行修正。,例:要求根据寄存器R7的内容转向各个处理程序。,即(R7)=0,转向PRG0 即(R7)=1,转向PRG1 即(R7)=2,转
10、向PRG2 即(R7)=n,转向PRGn,程序清单,JUMP1:MOV DPTR,#JPTAB1 MOV A,R7 ADD A,R7;A(R7)*2 JNC NADD;判断是否有进位 INC DPH;有进位则加到高字节地址NADD:JMP A+DPTRJPTAB1:AJMP PRG0 AJMP PRG1 AJMP PRGn,注意事项,(1)在上例中,由于AJMP指令的指令长度为2个字节,因而在散转时采用自加的方法使变址实现乘2;若改用LJMP指令,由于其指令长度为3字节,因而应使变址乘3来修正。当修正产生进位时,要将进位加到DPH中。(2)由于使用了AJMP指令,PRG0、PRG1、等处理程序
11、的入口与相应的AJMP指令必须在同一个2K范围内。(3)由于R7是单字节,因而散转点不能大于256个。为了克服此局限性,可通过修改DPTR的办法来增加散转点。,二、使用地址偏移量表的散转程序,1.应用场合 转向的程序均在同一页(256字节),即转移表的大小与各个处理程序的总长度必须小于256字节。2.实现方法利用指令JMP A+DPTR与伪指令DB汇编时的计算功能实现散转。本方法的关键在于建立一个转向地址偏移量表(各处理程序首地址与表格首地址之间偏移量)。,例:要求按R7的内容转向5个处理程序。,JUMP3:MOVA,R7MOVDPTR,#TAB3MOVC A,A+DPTRJMPA+DPTRT
12、AB3:DBPRG0-TAB3DBPRG1-TAB3 DBPRG4-TAB3PRG0:PRG1:PRG2:,本例的散转范围小于256,同上例一样,本例也可通过变通的方法,使这能在64K范围内实现散转。,三、使用转向地址表的散转程序,1.应用场合 转向范围较大时。2.实现方法 建立转向地址表,它的表项为各个处理程序的入口地址。散转时使用查表指令,按某个单元的内容查表找到对应的转向地址,把它装入DPTR中,然后对累加器A清零,再利用指令JMP A+DPTR直接转向各个处理程序。,例:根据寄存器R7的内容转向相应的处理程序中去,设各处理程序入口地址分别为PRG0,PRG1,PRGn,MOVDPTR,
13、#TAB4;指向地址表MOVA,R7ADDA,R7;A(R7*2)JNCNADDINCDPH;若(R7*2)256,则加进位NADD:MOVR3,AMOVCA,A+DPTR;查转移地址高8位XCHA,R3INCAMOVCA,A+DPTR;查转移地址低8位MOVDPL,AMOVDPH,R3;将转移地址赋给DPTRCLRAJMPA+DPTR;实现散转,程序清单,TAB4:DWPRG0;低位字节在高地址DWPRG1DWPRG2 DWPRGn,程序清单(续),本例的散转范围为64K,但散转数n应小于256(R7为8位)。可以通过双字节加法运算修改DPTR的方法来使散转点大于256个。,四、利用“RET
14、”指令实现的散转程序,本方法的关键在于将处理子程序的目的地址压入椎栈,然后通过“RET”指令来将目的地址弹出到PC中,从而实现程序转移。即利用RET指令来代替两个POP指令。例:要求根据R7的内容转向各处处理程序,设各处理程序的转向地址分别为PRG0,PRG1,PRGn,JUMP5:MOVDPTR,#TAB5MOVA,R7ADDA,R7;A(R7*2)JNCNADDINCDPH NADD:MOVR3,AMOVCA,A+DPTR;查高位地址XCHA,R3INCAMOVCA,A+DPTRPUSHACC;低位地址PUSH03H;PUSHR3高位地址RET;转向地址PC,转移TAB5:DWPRG0;转
15、移地址表DWPRG1DWPRGn,程序清单,14.4 循环程序设计,包含多次重复执行的程序段,循环结构使程序紧凑。循环程序的构成及各个环节任务:初始化部分 循环准备工作。如:清结果单元、设指针、设循环控制变量初值等循环体 循环工作部分:需多次重复处理 的工作 循环控制部分:1.修改指针和循环控制变量。2.检测循环条件:满足循环条件,继续循环,否则退出循环。结束部分 处理和保存循环结果。,单重循环:循环体中不套循环。,例:求n个单字节数据的累加,设数据串已在43H起始单元,数据串长度在42H单元,累加和不超过2个字节。,SUM:MOVR0,#42H;设地址指针MOVA,R0MOVR7,A;循环计
16、数器nCLRA;结果单元清0MOVR3,AADD1:INCR0;修改指针ADDA,R0;累加JNC NEXT;处理进位INCR3;有进位,高字节加1NEXT:DJNZ R7,ADD1;循环控制:数据是否加完?MOV40H,A;循环结束,保存结果MOV41H,R3RET,多重循环:循环体中套循环结构。,例:延时程序设计,DELAY:MOVR7,#200;1个机器周期DE1:MOVR6,#123;1200NOP;1200DE2:DJNZR6,DE2;2123200DJNZR7,DE1;2200RET;2,如晶体振荡器频率为12MHz,则其延时时间为:1+(1+1+2123+2)200+2=50.0
17、03ms这是一个50ms的精确延时程序。,14.5 运算程序设计,一、多字节加法,例:设有两个4字节的二进制数2F5BA7C3H和14DF35B8H,分别放在以40H和50H为起始地址的单元中(低位在低地址),试编程求这个数之和,结果放在以40H为起始地址的单元中。,ORG0000HLJMPMAINORG0100HMAIN:MOV R0,#40HMOVR1,#50HMOVR7,#04HLCALL JASUBLJMP$以上为主程序,JASUB:CLRCJASUB1:MOV A,R0 ADDC A,R1 MOV R0,A INC R0 INC R1 DJNZ R7,JASUB1 RET END,A
18、DDCA,RnADDCA,directADDCA,RiADDCA,#data,多字节BCD码加法,与多字节加法程序类似,但需在加法指令后加一条十进制加法调整指令。主程序与前面相同。,DADD:CLRCJAD1:MOVA,R0ADDCA,R1DAAMOVR0,AINCR0INCR1DJNZR7,JAD1RET,ORG0000HLJMPMAINORG0100HMAIN:MOVR0,#40HMOVR1,#50HMOVR7,#04HLCALL DADDLJMP$以上为主程序,二、多字节减法,多字节减法程序和多字节加法程序类似,只需将加法指令换为减法指令即可。例:在43H40H依次存放被减数443ADD
19、7BH;在53H50H中依次存放减数14DF35B8H,试编程求二者之差。,ORG0000HLJMPMAINORG0100HMAIN:MOVR0,#40HMOVR1,#50HMOVR7,#04HLCALL JIANSUBLJMP$以上为主程序,JIANSUB:CLRCJIAN1:MOVA,R0 SUBBA,R1 MOVR0,A INCR0 INCR1 DJNZ R7,JIAN1 RET END 此程序也可以推广到N个字节的情况。,14.6 数据的拆拼,BBCD:MOVA,R0 ANLA,#0FH MOVR5,A MOVA,R0,ANLA,#0F0HSWAPAMOVR6,ARET,程序清单:,1
20、4.7 码制转换,在计算机内部,任何数据都是以二进制的形式存储,但是,当我们在作I/O操作时,往往需要其它形式的数据格式,如ASCII码、BCD码、八进制数等,这就需要做一些数据格式的互换操作。,一、ASCII码与二进制数的相互转换,二进制与ASCII码的相互关系为:数字09对应的ASCII码为30H39H,即加30H字母AF对应的ASCII码为41H46H,即加37H,(1)ASCII到二进制的转换 通过以上介绍的二者之间的关系,不难画出流程图:,ASCTOHEX:MOVA,R2CLRCSUBBA,#30HCJNEA,#0AH,NEXTNEXT:JCTOKSUBBA,#07HTOK:MOVR
21、2,ARET,例:转换前R2为ASCII码,转换后R2为二进制。,(2)二进制到ASCII码,HEXTOASCII:MOVA,R2ANLA,#0FH;取低四位的二进制码ADDA,#90HDAA;若(R2)9,则加66H,且产生CyADDCA,#40HDAAMOVR2,ARET,例:转换前R2为二进制,转换后R2为ASCII码。,当二进制数0AH时,加30H即得相应的ASCII,当二进制数介于0AH、0FH之间(包括0AH、0FH),则加37H即得到相应的ASCII。下例为另一算法。,例:8位二进制转换成BCD码。,BINBCD1:MOV B,#100 DIV AB;(A)=百位数 MOV R0
22、,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存要转换的二进制数出口:R0存放BCD数 百、十、个位数的地址,二、二进制数到BCD码的转换,子程序设计子程序入口用标号作为子程序名;调用子程序之前设置好堆栈,子程序嵌套须考虑堆栈容量;提供足够的调用信息,如:子程序名、入口参数和出口参数等;用返回指令RET结束子程序,并保证堆栈栈顶为调用程序的返回地址。,补充:子程序设计,子程序调用时的参数传递,入口
23、参数:调用子程序之前,需要传给子程序的参数。出口参数:子程序送回调用程序的结果参数。,参数传递方式:寄存器传送参数堆栈传送参数,设计子程序应满足通用性的要求,不针对具体数据编程。,1.通过寄存器传递参数,这种方法应用最为广泛、也最易使用,它是在调用子程序之前,对需要使用的寄存器预先修改后,再来调用子程序。,例:试编程对30H39H单元清零,MAIN:MOV R0,#30H MOV R7,#0AH LCALL SUBRT SUBRT:MOV A,#00HRESU:MOV R0,A INC R0 DJNZ R7,RESU RET,二、通过椎栈传递参数,MAIN:MOV70H,#30HMOV71H,#0AHPUSH70HPUSH71HLCALLSUBRTSUBRT:POPDPHPOPDPLPOP07H;R7POP00H;R0SUB1:MOVA,#00H,LOOP:MOVR0,AINCR0DJNZR7,LOOPPUSHDPLPUSHDPHRET 对于简单程序而言,这种方法反而较笨,较易引起混淆。,例:试编程对30H39H单元清零,查表程序设计,注意表格的设计:规则变量表和非 规则变量表;数据极值查找和数据排序;散转程序设计:三种转移表的设计及转移范围;循环程序设计;定点数运算程序设计;码制转换;子程序设计:参数传递的两种方法。,本章总结,本 章 结 束,