1、4 MCS-51汇编语言程序设计,教学基本要求: (1)、了解MCS-51汇编语言程序设计的特点; (2)、熟悉MCS-51汇编语言伪指令的功能及用法; (3)、掌握顺序、分支、循环程序的设计方法; (4)、掌握汇编语言程序手工汇编、机器交叉汇编的方法。 教学重点: (1)、汇编语言程序机器交叉汇编的方法(ASM51软件使用); (2)、分支、循环程序的设计方法; (3)、定时、排序程序的设计方法; 教学难点: (1)、汇编语言程序手工汇编时偏移量rel的计算; (2)、利用JMP A+DPTR指令实现程序多分支; (3)、查表程序的设计方法; (4)、子程序结构与堆栈的关系。,4.1 汇编语
2、言程序设计概述,4.1.1 汇编语言的特点及其语句格式 (1)汇编语言的特点a)助记符指令和机器指令一一对应,用汇编语言编写的程序效率高,占用存储空间小,运行速度快;b)汇编语言编程比高级语言困难;c)汇编语言程序能直接管理和控制硬件设备;d)汇编语言缺乏通用性,程序不易移植。 (2)汇编语言的语句格式 标号: 操作码助记符 目的操作数,源操作数 ;注释,4.1.2 汇编语言程序设计的特点所谓程序设计,就是编写计算机程序。汇编语言程序设计,就是使用编汇指令来编写计算机程序。汇编语言程序设计必须注意如下特点: (1)设计人员必须详细了解单片机的硬件结构,以便在程序设计中熟练使用; (2)必须熟悉
3、汇编语言指令的功能和用法; (3)在程序设计前,必须分析设计任务,确定所用算法,确定程序结构,确定数据的类型、数据的结构,必须对数据的存放、寄存器和工作单元的使用以及所用硬件资源等作出具体安排; (4)根据分析,画出程序设计流程图; (5)根据程序设计流程图编写程序。,4.2 单片机汇编语言程序设计的基本结构形式,单片机汇编语言程序设计的基本结构形式一般分为以下3种形式,即顺序结构、分支结构、循环结构。 4.2.1 顺序程序顺序程序是最简单的程序结构,在顺序程序中,既无分支,循环,也不调用子程序,程序执行时一条一条地按顺序执行指令例:假定三字节无符号数相加,其中一个加数在内部RAM的50H、5
4、1H和52H单元中,另一个加数在内部RAM的53H、54H和55H单元中,要求把相加之和存放在50H、51H和52H单元中,进位存放在位寻址区的00H位中。 解:(1)分析任务:求两数之和(2)算法:加法运算(ADD或ADDC),(3)程序结构:顺序或循环结构(4)数据类型:三字节、二进制、无符号数(5)数据结构:升序或降序排列 (6)RAM单元安排: (内部RAM字节单元、位地址空间)(7)采用寄存器间接寻址方式(R0、R1),(8)程序设计流程框图;,(9)程序清单;ORG 1000HMOV RO, #52H;加数N1的低字节地址送地址指针R0MOV R1, #55H;加数N2的低字节地址
5、送地址指针R1MOV A, R0; 取N1的低字节ADD A, R1; N1、N2低字节相加MOV R0, A; 保存N1、N2低字节和DEC R0; 修改加数N1的地址指针内容DEC R1; 修改加数N2的地址指针内容MOV A, R0; 取N1的中间字节ADDC A, R1; N1、N2中间字节带低字节和进位相加MOV R0, A; 保存N1、N2中间字节和DEC R0; 修改加数N1的地址指针内容,DEC R1; 修改加数N2的地址指针内容MOV A, R0; 取N1的高字节ADDC A, R1; N1、N2高字节带中间字节和进位相加MOV R0, A; 保存N1、N2高字节和MOV 0
6、0H, C; 高字节和的进位送00H位保存END 思考题:1)上述程序中,如果只采用ADDC指令,应如何修改程序?2)如果N1、N2,N3均为十进制数,应如何修改程序?3)如果加数N1在内部RAM 50H、51H和52H单元中,而加数N2与和N3均在外部RAM0053H、0054H和0055H单元中,其它条件不变,应如何修改程序?4)如果N1、N2,N3均存放在外部RAM单元,应如何修改程序?,思考题: 1) ORG 1000HMOV RO, #52H;加数N1的低字节地址送地址指针R0MOV R1, #55H;加数N2的低字节地址送地址指针R1MOV A, R0; 取N1的低字节CLR C;
7、 清原来进位位CY的内容ADDC A, R1; N1、N2低字节相加MOV R0, A; 保存N1、N2低字节和DEC R0; 修改加数N1的地址指针内容DEC R1; 修改加数N2的地址指针内容MOV A, R0; 取N1的中间字节ADDC A, R1; N1、N2中间字节带低字节和进位相加MOV R0, A; 保存N1、N2中间字节和DEC R0; 修改加数N1的地址指针内容,DEC R1; 修改加数N2的地址指针内容MOV A, R0; 取N1的高字节ADDC A, R1; N1、N2高字节带中间字节和进位相加MOV R0, A; 保存N1、N2高字节和MOV 00H, C; 高字节和的
8、进位送00H位保存END 思考题: 2) ORG 1000HMOV RO, #52H;加数N1的低字节地址送地址指针R0MOV R1, #55H;加数N2的低字节地址送地址指针R1MOV A, R0; 取N1的低字节ADD A, R1; N1、N2低字节相加DA A; N1、N2低字节和十进制调整MOV R0, A; 保存N1、N2低字节和,DEC R0; 修改加数N1的地址指针内容DEC R1; 修改加数N2的地址指针内容MOV A, R0; 取N1的中间字节ADDC A, R1; N1、N2中间字节带低字节和进位相加DA A; N1、N2中间字节和十进制调整MOV R0, A; 保存N1、
9、N2中间字节和DEC R0; 修改加数N1的地址指针内容DEC R1; 修改加数N2的地址指针内容MOV A, R0; 取N1的高字节ADDC A, R1; N1、N2高字节带中间字节和进位相加DA A; N1、N2高字节和十进制调整MOV R0, A; 保存N1、N2高字节和MOV 00H, C; 高字节和的进位送00H位保存 END,思考题 3) ORG 1000HMOV RO, #52H;加数N1的低字节地址送地址指针R0MOV R1, #55H;加数N2的低字节地址送地址指针R1MOVX A, R1; 取N2的低字节ADD A, R0; N1、N2低字节相加MOVX R1, A; 保存
10、N1、N2低字节和DEC R0; 修改加数N1的地址指针内容DEC R1; 修改加数N2的地址指针内容MOVX A, R1; 取N2的中间字节ADDC A, R0; N1、N2中间字节带低字节和进位相加MOVX R1, A; 保存N1、N2中间字节和DEC R0; 修改加数N1的地址指针内容,DEC R1; 修改加数N2的地址指针内容MOVX A, R1; 取N2的高字节ADDC A, R0; N1、N2高字节带中间字节和进位相加MOVX R1, A; 保存N1、N2高字节和MOV 00H, C; 高字节和的进位送00H位保存END如果N2、N3的数据地址指针采用DPTR,则程序修改如下:OR
11、G 1000HMOV RO, #52H;加数N1的低字节地址送地址指针R0MOV DPTR, #0055H;加数N2的低字节地址送DPTRMOVX A, DPTR; 取N2的低字节ADD A, R0; N1、N2低字节相加MOVX DPTR, A; 保存N1、N2低字节和DEC R0; 修改加数N1的地址指针内容,MOV DPTR, #0054H;修改加数N2的地址指针内容MOVX A, DPTR; 取N2的中间字节ADDC A, R0; N1、N2中间字节带低字节和进位相加MOVX DPTR, A; 保存N1、N2中间字节和DEC R0; 修改加数N1的地址指针内容MOV DPTR, #00
12、53H;修改加数N2的地址指针内容MOVX A, DPTR; 取N2的高字节ADDC A, R0; N1、N2高字节带中间字节和进位相加MOVX DPTR, A; 保存N1、N2高字节和MOV 00H, C; 高字节和的进位送00H位保存END思考:修改加数N2的数据地址指针DPTR的内容可否采用DEC DPTR指令?,例:设内部RAM 40H,41H单元中分别存放8位二进制数,现分别取这两个单元中的半个字节,合并成一个新字节存放在42H单元中。要求如下:42H单元新字节的低半字节取自40H单元的低半字节,而高半字节取自41H单元的低半字节。 解:(1)分析任务:拆字、合字,(2)算法:逻辑运
13、算(3)程序结构:顺序(4)数据类型:单字节、二进制、无符号数(5)数据结构:升序或降序排列 (6)程序设计流程框图;,(7)程序清单;ORG 2000HSTART: MOV R1, #40H;初始化数据指针R1的内容MOV A, R1; 取40H单元内容送AANL A, #0FH;保留40H单元内容低4位SWAP A; 40H单元内容高低半字节互换INC R1; 修改数据指针R1的内容XCH A, R1; (A)与R1内容互换ANL A, #0FH;保留41H单元内容低四位ORL A, R1; 合字生成新字节INC R1; 修改数据指针R1的内容MOV R1, A; 新字节送42H单元保存E
14、ND 作业题:上例中其它条件不变,要求如下:42H单元新字节的低半字节取自40H单元的低半字节,而高半字节取自41H单元的高半字节。,(1)单分支程序单分支程序是通过条件转移指令实现的,即根据条件对程序的执行进行判断,满足条件则进行程序转移,不满足条件程序就顺序执行。在MCS-51指令系统中,可利用JZ,JNZ,CJNE,DJNZ,JC,JNC,JB,JNB,JBC等指令,完成为0、为1、为正、为负以及相等、不相等等各种条件判断。例:两个8位无符号二进制数比较大小。假设在外部RAM中有ST1、ST2和ST3共3个连续单元(单元地址从小到大),其中ST1、ST2单元中存放着两个8位无符号二进制数
15、N1,N2,要求找出其中的大数并存入ST3单元中。,4.2.2 分支程序,解:(1)分析任务:比较两个数的大小(2)算法:算术运算、控制转移(3)程序结构:单分支(4)数据类型:单字节、二进制、无符号数(5)数据结构:单元地址升序排列 (6)RAM单元安排:外部RAM单元(7)采用寄存器间接寻址方式(R0、R1或DPTR)(8)程序设计流程框图;(9)程序清单; 思考题(补充作业题):上例中,如果采用CJNE A, direct,rel指令,应如何修改程序?,返回,ORG 8000HSTART: CLR C;进位清0MOV DPTR, #ST1; 设数据指针MOVX A, DPTR; A(ST
16、1),取N1MOV R2, A; 暂存N1INC DPTR; DPTR ST2(指向N2单元)MOVX A, DPTR; 取N2存于A中SUBB A, R2;N1,N2比较(N2-N1,差在A中)JNC BIG1;N2N1,转BIG1,N2N1,顺序执行XCH A, R2;N1,N2互换,A N1SJMP BIG0 BIG1: MOVX A, DPTR;A N2BIGO: INC DPTR; DPTR ST3(指向N3单元)MOVX DPTR, A;ST3 大数END,返回,(2)多分支程序假设多分支程序中,分支序号的最大值为n,则多分支转移结构如图所示:MCS-51指令系统没有多分支转移指令
17、,无法使用单条指令完成多分支转移。要实现多分支转移,可采用以下几种方法:,假设分支序号值保存在累加器A中,则可使用 CJNE A, #data, rel指令,其分支流程如图所示:,(a)使用多条CJNE指令,通过逐次比较,实现分支程序转移,例:某温度控制系统,采集的温度值(Ta)放在累加器A中。此外,在内部RAM 54H单元存放控制温度下限值(T54),在内部RAM 55H单元存放控制温度上限值(T55)。若TaT55,程序转向JW(降温处理程序);若TaT54,则程序转向SW(升温处理程序);若T55TaT54,则程序转向FH(返回主程序)。,ORG 1000HCJNE A, 55H, LO
18、OP1;TaT55,转LOOP1AJMP FH; Ta=T55,返回主程序 LOOP1:JNC JW; (CY)=0,TaT55,转JWCJNE A, 54H, LOOP2;TaT54,转LOOP2AJMP FH; Ta=T54,返回主程序 LOOP2:JC SW; (CY)=1,Ta T54,转SWFH:RET; T55TaT54,返回主程序END例:已知:127X-128,求Y。设X,Y分别存放在外部RAM 1000H和2000H单元中。,解:(1)分析任务:解方程(2)算法:控制转移(3)程序结构:多分支(4)数据类型:单字节、二进制、有符号数(5)RAM单元安排:外部RAM单元(6)采
19、用寄存器间接寻址方式(R0、R1或DPTR)(7)程序设计流程框图;(8)程序清单;思考题(补充作业题):上例中,如果采用CJNE指令,应如何修改程序?,返回,ARE EQU 1000H;BUF EQU 2000H;ORG 1000H START:MOV DPTR, #ARE; 数据X的地址送数据指针DPTRMOVX A, DPTR; A取数据XJZ SUL; X0转SULJB ACC.7, NEG; X0转NEG,否则,X0MOV A, #01H;SJMP SUL;NEG: MOV A, #0FFH; (0FFH为-1补码)SUL: MOV DPTR, #BUF; 数据Y的地址送数据指针DP
20、TRMOVX DPTR, A; 保存Y值 END,返回,首先,在程序中建立一个差值表,并将各分支程序入口地址与该表首地址的差值按序排列其中,差值表首地址送DPTR,分支程序序号值送A中,然后可通过JMP A+DPTR指令进行分支转移。例:有BR0、BR1、BR2和BR3共4个分支程序段,各分支程序段的功能依次是从内部RAM取数、从外部RAM低256B范围取数、从外部RAM 4KB范围取数和从外部RAM 64KB范围取数。并假定R0中存放取数地址低8位地址,R1中存放取数地址高8位地址,R3中存放分支程序序号值。假定以BRTAB作差值表首地址,BR0BRTAB BR3BRTAB为差值。,(b)使
21、用查地址表方法实现多分支程序转移*,MOV A, R3; 分支程序序号送AMOV DPTR, #BRTAB;差值表首址MOVC A, A+DPTR;查表JMP A+DPTR; 转移 BRTAB: DB BR0BRTAB; 差值表DB BR1BRTAB;DB BR2BRTAB;DB BR3BRTAB; BR0: MOV A, R0; 从内部RAN取数SJMP BRE; BR1: MOVX A, R0; 从外部RAM低256B范围取数SJMP BRE;,BR2: MOV A, R1; 从外部RAM 4KB范围取数ANL A, #0FH; 高位地址取低4位ANL P2, #0F0H; 清P2口低4位
22、ORL P2, A; 发高位地址MOVX A, R0;SJMP BRE; BR3: MOV DPL, R0; 从外部RAM 64KB范围取数MOV DPH, R1;MOVX A, DPTR; BRE: SJMP $;查表方法的技巧性较强,但由于表中的差值只限于8位,使分支程序入口地址分布范围受到限制。,首先,在程序中建立一个转移指令表,在表格中存放转移指令,然后,通过查转移指令表的方式实现多分支程序转移。这种方法主要利用散转指令JMP A+DPTR,此指令采用变址寻址方式,操作过程:(PC)(A)+(DPTR),CPU根据PC的内容来实现多分支程序转移。DPTR中送转移指令表的表首地址(常用转
23、移指令表的名称标号代替),而A中送转移指令表中存放的转移指令的序号(常常从第0条开始)。例如,有多个分支程序,如要通过AJMP转移指令进行转移,则应把这些转移指令按序写入转移指令表中,并设置一个序号指针(例如R3),序号往往从0开始,然后可使用以下查表程序实现程序转移。,(c)使用查转移指令表的方法实现多分支程序转移,MOV A, R3; 分支程序序号送ARL A; 分支程序序号乘2MOV DPTR,#BRTAB; BRTAB为转移指令表名称标号,JMP A+DPTR; 也为转移指令表首地址 BRTAB:AJMP ROUT0; 分支程序0的转移指令AJMP ROUT1; 分支程序1的转移指令A
24、JMP ROUT2;AJMP ROUT127; 分支程序127的转移指令 ROUT0: ; 分支程序0 ROUT1: ; ROUT127: ; 分支程序127,由于AJMP指令是二字节指令,因此,程序中通过RL A指令将分支序号乘2。转移指令表中最多只能安排128条分支转移指令,如需多于128条,则必须另行修改程序。由于AJMP指令转移范围是2KB,因此,分支程序应安排在以JMP A+DPTR指令为中心的2KB范围之内,否则会出错。如果转移指令表中的转移指令是LJMP指令,则分支程序可安排在64KB ROM空间的任何地方。但转移指令表中的转移指令的条数最多为85条(LJMP指令是三字节指令),
25、上述程序应作相应的修改。MOV A, R3;MOV B, #03H;MUL AB;,MOV DPTR,#BRTAB; BRTAB为转移指令表名称标号,JMP A+DPTR; 也为转移指令表首地址 BRTAB:LJMP ROUT0; 分支程序0的转移指令LJMP ROUT1; 分支程序1的转移指令LJMP ROUT2;LJMP ROUT85; 分支程序85的转移指令 ROUT0: ; 分支程序0 ROUT1: ; ROUT85:; 分支程序85,例:假设键盘上有4个按键,功能说明如下表:程序流程框图,假设转移指令表名称为BRTAB,分支程序序号已在A 中。MOV DPTR, #BRTABCLR
26、CRLC AJMP A+DPTR;ORG 3000H 3000H BRTAB:AJMP ER; 转删除分支程序,3000H BRTAB:AJMP ER; 转删除分支程序 3001H 3002H AJMP DS; 转读数据分支程序 3003H 3004H AJMP XS; 转写数据分支程序 3005H 3006H AJMP CR; 转插入分支程序 3007HORG 3100H 3100H ER:; 删除分支程序ORG 3200H 3200H DS:; 读数据分支程序ORG 3300H 3300H XS:; 写数据分支程序ORG 3400H 3400H CR:; 插入分支程序END,返回,假设各分
27、支程序入口地址存放在BRTAB表中,并假定分支转移序号在R3中,则可用如下程序实现多分支程序转移。MOV DPTR, #BRTAB;分支入口地址表首址送DPTRMOV A, R3; 分支序号送ARL A; 分支序号2MOV R1, A; 暂存A值INC A;MOVC A, A+DPTR;取低位地址PUSH A; 低位地址入栈MOV A, R1; 恢复A值MOVC A, A+DPTR;取高位地址,(d)通过堆栈操作实现多分支程序转移*,PUSH A; 高位地址入栈RET; 分支程序入口地址装入PC BRTAB: DW BR0; 分支程序入口地址高8位在低DW BR1; 地址单元,低8位在高地址单
28、元DW BR127; BR0: ; 分支程序0 BR1: ; 分支程序1 BR127: ; 分支程序127特点:先将分支程序入口地址入栈,然后巧妙地利用返回指令,把分支程序入口地址装入PC,接着转去执行分支程序。,4.2.3 循环程序,MCS-51汇编语言指令系统没有专用的循环指令,但可以使用条件转移指令通过条件判断来控制循环是继续还是结束。循环程序一般由四个主要部分组成: (1)初始化部分:为循环程序做准备,如规定循环次数、给各变量和地址指针预置初值。 (2)处理部分: 为反复执行的程序段,是循环程序的实体, 也是循环程序的主体。 (3)循环控制部分: 其作用是修改循环变量和控制变量,并判断
29、循环是否结束,直到符合结束条件时,跳出循环为止。 (4)结束部分: 这部分主要是对循环程序的结果进行分析、处理和存放。,单循环程序一般有以下两种典型结构:,双重循环程序的结构:,在应用系统程序设计时,有时经常需要将数据存储器中各部分地址单元作为工作单元,以存放程序执行的中间值或执行结果, 因此,在使用这些工作单元之前,必须将工作单元清零。工作单元清零可用循环程序完成。例:假设在内部RAM区,开辟96个工作单元,工作单元首地址为20H,则工作单元清零程序子程序如下:ORG 1000HCLR0:MOV R0, #20H;循环初始化部分MOV R7, #96;CLR ALOOP:MOV R0, A;
30、 循环体部分INC R0; 修改变量DJNZ R7, LOOP;循环控制部分RETEND 思考题(补充作业题):如采用CJNE指令,应如何修改程序?,例:两个三字节二进制无符号数相加,被加数放在内部RAM 20H22H单元(低字节存放在低地址单元,高字节存放在高地址单元,即低位在前,高位在后),加数放在2AH2CH单元,和放在20H22H单元,最高位如有进位,则放在23H单元中。 解:数据类型(二、十进制数,有、无符号数);数据结构(升、降序排列),被加数 N1 高字节(8位) 中字节(8位) 低字节(8位) 加数 N2 高字节(8位) 中字节(8位) 低字节(8位) +)进位位(CY) 进位
31、位(CY) 进位位(CY) 和 N3 进位 高字节(8位) 中字节(8位) 低字节(8位)程序流程框图程序清单思考题:统计正数、负数、零的个数。,ORG 0030H ADDDUO:MOV R0, #20H; 循环初始化部分MOV R1, #2AH;MOV R7, #03H; 循环次数CLR C;LOOP:MOV A, R0; 循环体部分ADDC A, R1;MOV R0, A;INC R0; 修改指针变量INC R1;DJNZ R7, LOOP; 循环控制部分CLR A; 循环结束处理部分ADDC A, #00H;MOV R0, A;RET;END,返回,返回,例:把内部RAM中起始地址为DA
32、TA的数据串传送到外部RAM以BUFFER为首地址的区域,直到发现“$”字符的ASC码为止,同时规定数据串最大长度为32个字节。 解:(1)分析任务:数据传送;(2)算法:比较、控制转移(3)程序结构:分支、循环(4)数据类型:多字节字符串(5)RAM单元安排:内部RAM单元、外部RAM单元(6)采用寄存器间接寻址方式(R0、R1或DPTR),(7)程序流程框图;,ORG 0030H DATACS:MOV R0, #DATA; DATA数据区首地址MOV DPTR, #BUFFER;BUFFER数据区首地址MOV R1, #20H; 最大数据串长LOOP:MOV A, R0; 取数据SUBB
33、A, #24H; 判是否为“$”字符JZ LOOP1; 是“$”字符,转结束MOVX DPTR,A; 数据传送INC R0;INC DPTR;DJNZ R1, LOOP; 循环控制LOOP1:RET; 结束 END,4.3 MCS-51单片机汇编语言程序设计举例,4.3.3 定时程序在单片机的控制应用中,常有定时的需要,如定时中断、定时检测和定时扫描等。定时功能除可以使用纯硬件电路、可编程定时/计数器实现外,还可以使用软件程序(定时程序)完成。定时程序是典型的循环程序,它是通过执行一个具有固定延迟时间的循环体来实现定时的。 (1)单循环定时程序MOV R5, #TIME; LOOP: NOP;
34、NOP;DJNZ R5, LOOP;,假设单片机晶振频率fosc=6MHz,则一个机器周期为2s,NOP、DJNZ指令分别是单、双机器周期指令。定时程序的总延迟时间是循环程序段延时时间的整数倍,由于R5是8位寄存器,因此,这个定时程序的最长定时时间为:256(28)8=2048(s) (2)较长时间的定时程序(多重循环定时子程序)TIME:MOV R5, #TTME1; LOOP:MOV R4, #TEME2; LOOP1:NOP; NOP; DJNZ R4, LOOP1; DJNZ R5, LOOP2;RET;,这个定时子程序的最长定时时间为:256(28)4+2+1256(28)2+4=5
35、25828(s) (3)调整定时时间在定时程序中可通过在循环程序段中增减指令的方法对定时时间进行微调。例: MOV R0, #TTME; LOOP:ADD A, R1;INC DPTR; DJNZ R0, LOOP;由于ADD、INC、DJNZ指令的机器周期分别为1、2、2,所以,该程序定时时间为=(1+2+2)2sTime(s)。,假定要求定时时间为24us。对于这个定时程序,只须增加一条NOP指令即可实现。 MOV R0, #TIME; LOOP: ADD A, R1;INC DPTR; NOP;DJNZ R0, LOOP; 只须TIME取2,即可得到精确的24s定时。 (4)以一个基本的
36、延时程序满足不同的定时要求如果一个系统有多个定时需要,我们就可以设计一个基本延时程序,使其延时时间为各定时时间的最大公约数,然后可以以此基本程序作为子程序,通过调用的方法实现所需不同定时。,例:在单片机应用系统中,假设需要的定时时间分别为5S、10S、20S,可设计一个1S延时子程序DELAY,则5S、10S、20S的定时时间可通过调用DELAY实现。MOV R0, #05H; 5S定时LOOP: LCALL DELAY; DJNZ R0, LOOP1; MOV R0, #0AH; 10S定时LOOP2: LCALL DELAY; DJNZ R0, LOOP2; MOV R0, #14H; 2
37、0S定时LOOP3: LCALL DELAY; DJNZ R0, LOOP3; ,4.3.4 查表程序所谓查表程序,就是指预先把数据以表格形式存放在程序存储器中,然后使用程序读出,这种能读出表格数据的程序就称之为查表程序。查表操作对单片机的控制应用十分重要,查表程序常用于实现非线性修正,非线性函数转换以及代码转换等场合。MCS-51单片机指令系统中有两条专用查表指令: (1)MOVC A, A+DPTR;A(A)+(DPTR) (2)MOVC A, A+PC; A(A)+(PC) 这两条查表指令的功能是完全相同的,其共同优点是:能在不改变PC和DPTR的状态下,只根据A的内容就可以取出表格中的
38、数据。注意:A的内容均为8位无符号数。,对于第一条指令,适用于64KB ROM范围内查表(即数据表格的大小和位置可以在64KB程序存储器中任意安排,一个数据表格可以被多个程序块使用),编写查表程序时,首先把表的首地址送入DPTR中,再要将查表的数据序号(或下标值)送入A中,然后就可以使用该指令进行查表操作,并把结果送A中。对于第二条指令,常用于“本地”范围查表(即数据表格只能放在该指令后面256个地址单元之内,而且表格只能被本程序使用),编写查表程序时,首先把查表数据的序号送入A中,再把从查表指令的下一条指令的首地址到表的首地址间的偏移量与A值相加,然后再使用该指令进行查表操作,并把结果送入A
39、中。,例:设计一个子程序,其功能为根据x的内容(09之间)查平方表,求出相应的结果y(y=x2)。假设x的内容已存放在内部RAM 30H单元中,求出y的内容存放在内部RAM 40H单元中。ORG 1000H 1000H SQR: MOV A, 30H; Ax 1002H PUSH DPH; 现场保护 1004H PUSH DPL; 1006H MOV DPTR,#TAB1; DPTR表首地址TAB1 1009H MOVC A, A+DPTR;查表得y 100AH MOV 40H, A; 40Hy 100CH POP DPL; 现场恢复 100EH POP DPH; 1010H RET 1011
40、H TAB1: DB 00H,01H,04H,09H,10H,19HDB 24H,31H,40H,51H,上例中,如果使用MOVC A,A+PC指令,则编程如下: ORG 1000H 1000H SQR: MOV A, 30H; Ax 1002H PUSH DPH; 现场保护 1004H PUSH DPL; 1006H ADD A, #07H; 加偏移量 1008H MOVC A, A+PC; 查表得y 1009H MOV 40H, A; 40Hy 100BH POP DPL; 现场恢复 100DH POP DPH; 100FH RET 1010H TAB1: DB 00H,01H,04H,0
41、9H,10H,19HDB 24H,31H,40H,51H 此题中,偏移量=1010H-1009H=07H,例:有4*4键盘,键扫描后把被按键的键码存在A中,键码与处理程序入口地址对应关系为:,并假定处理程序在ROM 64KB的范围内分布。要求以查表方法,按键码转向对应的处理程序。16位入口地址在表中的顺序是低8位在前,高8位在后。程序如下:,MOV DPTR, #BS; 子程序入口地址表首址RL A; 键码值乘以2MOV R2, A; 暂存AMOVC A, A+DPTR;取得入口地址低8位PUSH A; 进栈暂存MOV A, R2; INC A; MOVC A, A+DPTR;取得入口地址高8
42、位 MOV DPH, A; 入口地址高8位送DPH PUP DPL; 入口地址低8位送DPL CLR A; JMP A+DPTR; 转向键处理子程序,BS: DB RK0L; 键码00H的处理程序入口地址DB RK0H;DB RK1L; 键码01H的处理程序入口地址DB RK1H;DB RK2L; 键码02H的处理程序入口地址DB RK2H;RK0: ; 键码00H的处理程序RK1: ; 键码01H的处理程序RK2: ; 键码02H的处理程序 RK15: ; 键码0FH的处理程序,4.3.5 数据极值查找程序*极值查找就是在给定的数据区中找出最大值或最小值。例:内部RAM 20H单元开始存放8
43、个无符号8位二进制数,找出其中的最大数。极值查找操作的主要内容是进行数值大小的比较。假定在比较过程中,以A存放大数,与之逐个比较的另一个数放在2AH单元中。比较结束后,把查找到的最大数送2BH中。程序流程框图如图所示:程序清单:,返回,MOV R0, #20H; 数据区首址MOV R7, #08H; 数据区长度MOV A, R0; 读第一个字节DEC R7; LOOP: INC R0; MOV 2AH, R0; 读下一个数CJNE A, 2AH, CHK; 数据比较 CHK: JNC LOOP1; A值大转换MOV A, R0; 大数送A;LOOP1: DJNZ R7, LOOP; 继续 MO
44、V 2BH, A; 极值送2BH单元HERE: AJMP HERE; 结束,返回,4.3.6 数据排序程序 (1)算法说明:冒泡法是一种相邻数互换的排序方法,执行时从前向后进行相邻数比较,如数据的大小次序与要求顺序不符合(逆序),就将两个数互换,否则为正序不互换。为进行升序排列,应通过这种相临数呼唤方法,使小数镶嵌移,大数向后移。如此从前向后进行一次冒泡(相邻数互换),就会把最大数换到最后;再进行一次冒泡,就会把次大数排在倒数第二的位置;。以此下去,即可完成排序。注意:a)如有N个数排序,每次冒泡需比较(N-1)次。b)对于N个数,理论上应进行(N-1)次冒泡,才能完成,排序,但实际上常常不到
45、(N-1)次就已排好序。c)控制排序结束常使用设置互换标志的方法,以其状态表示在一欠冒泡中有无数据互换进行。例:假定8个数据连续存放在20H为首地址的内部RAM单元中,使用冒泡法进行升序排序编程。设R7为比较次数计数器,初始值为07H,TR0为冒泡过程中是否有数据互换的状态标志,TR0=0表示无互换发生,TR0=1表明有互换发生。解:8个数据按升序排列,程序流程框图如图所示:ORG 8000H SORT:MOV R0, #20H; 数据区首址MOV R7, #07H; 各次冒泡比较次数CLR TR0; 互换标志清零,LOOP:MOV A, R0; 取前数MOV 2BH, A; 存前数INC R0; MOV 2AH, R0; 取后数CLR C; SUBB A, R0; 前数减后数JC NEXT; 前数小于后数不互换MOV R0, 2BH; DEC R0; MOV R0, 2AH; 二个数变换拉置INC R0; 准备下一次比较SETB TR0; 置互换标志NEXT: DJNZ R7, LOOP; 返回,进行下一次比较JB TR0, SORT; 返回,进行下一轮冒泡HERE: SJMP $; 排序结束END,