1、2013 XuYue 微软中国 2013/11/30 单片机汇编程序 【例5-2】在89C51单片机的引脚外接脉冲信号,要求每送来一个脉冲,把30H单元值加1,若30H单元计满则进位31H单元。现利用中断编制脉冲计数程序。 主程序部分: ORG 0000H AJMP MAIN ;设置主程序入口地址 ORG 0003H ;中断入口地址 AJMP SUBG ;设置中断服务程序入口地址 ORG 0100H
2、 MAIN: MOV A, #00H ;30H、31H两单元清零 MOV 30H,A MOV 31H,A MOV SP, #70H ;设置堆栈指针 SETB IT0 ;设为边沿触发 SETB EA ;开中断 SETB EX0 ;允许中断 AJMP $ ;等待中断 中断服务程序: ORG 0200H ;设置中断
3、服务子程序位置 SUBG: PUSH ACC ;保护现场 INC 30H ;中断后将脉冲计数值加1 MOV A, 30H JNZ BACK INC 31H BACK: POP ACC ;恢复现场 RETI ;返回 【例5-3】设计一个比赛抢答器,电路如图5-9所示,P1.0~P1.3分别接按钮S1~S4,当其中任何一个按钮按下时,都能立即从P3.3发出铃声信号,并点亮相应的发光二
4、极管。即S1点亮VL1,S2点亮VL2,S3点亮VL3,S4点亮VL4。电路连接如图5-8。 图5-8 例5-3电路图 主程序部分:初始化,等待中断 0RG 0000H LJMP START 0RG 0003H LJMP 0300H ORG 0100H START: MOV SP,#70H ;设置栈区 SETB IT0 ;脉冲触发方式 WAITOFF:CLR P3.3 ;响铃控制 SETB EA
5、 ;CPU中断允许 SETB EX0 ;中断允许 SJMP $ 中断服务程序: 查按钮,有按钮按下时响铃 ORG 0300H ;中断服务程序 ZDP: MOV A,P1 ;查哪个按钮按下 ANL A,#0FH SWAP A ;转换为点亮发光管信号 ORL A,#0FH MOV P1,A LCALL RING
6、 ;响铃 LCALL DELAY RETI 延时子程序: RING: MOV R5, #20H ; 时间常数 RIN0: MOV R6, #60H ; 时间常数 RIN1: MOV R7, #0F0H ; 时间常数 RIN2: DJNZ R7, RIN2 SETB P3.3 DJNZ R6, RIN1 DJNZ R5, RIN0 RET DELAY: MOV R6, #0FFH DE2:
7、MOV R7, #0FFH DE1: DJNZ R7, DE1 DJNZ R6, DE2 RET 【例5-4】设定时器T0工作在方式0,在P1.0引脚上输出周期为2ms的方波(定时时间为1ms),fosc=6MHZ。编程实现其定时功能。 解:当T0处于工作方式0时,加1计数器为13位。设T0的初值为X。(1机器周期=2µs) 1. 计算T0初值X 则:X=7692;转换为二进制数:1111000001100B;结果为(TH0)=F0H,(TL0)=0CH. 2. 初始化 选择T0并确定工作方式:(TMOD)=00H
8、 装入初始值:(TH0)=0F0H (TL0)=0CH 选择数据传输方式:中断方式:允许T0中断 SETB EA SETB ET0 查询方式:禁止T0中断 CLR ET0 3. 程序清单 将上述的分析过程用指令表示出来。 方法1:中断法。在定时器初始化时要开放对应的中断允许(ET0或ET1)和总允许EA,在启动后等待中断。当计数器溢出中断,CPU将程序转到中断服务程序入口,因此应在中断服务程序中安排相应的处理程序。 主程序: ORG 1000H PTOMD :MOV TMOD, #00H
9、 ;T0方式0 MOV TL0, #0CH ;送初值 MOV TH0, #0F0H SETB EA ;CPU开中断 SETB ET0 ;开T0中断 SETB TR0 ;启动定时 SJMP $ ;等待中断 中断服务程序: ORG 0120H ITOP: MOV TL0, #0CH ;
10、重新装入初值 MOV TH0, #0F0H CPL P1.0 ;P1.0取反输出方波 RETI 方法2:查询法。在定时器初始化并启动后,在程序中安排指令查询TF0的状态。 MOV TMOD, #00H ;设置T0为模式0 MOV TL0, #0CH ;送初值 MOV TH0, #0F0H CLR ET0 ;禁止T0中断 SETB TR0 ;启动T0 LOOP: JBC TF0, NEXT
11、 ;查询定时时间是否到? SJMP LOOP NEXT: MOV TL0, #0CH ;重装计数初值 MOV TH0, #0F0H CPL P1.0 ;输出取反 SJMP LOOP ;重复循环 【例5-5】 用89C51单片机产生方波信号,晶振频率为6MHz,用T0定时,通过并行口P1.0输出频率为lKHz的方波的程序。用查询方式。 ORG 2000H START: MOV TMOD,#01H ;T0工作于方式1 MOV TL0, #06H
12、 ;时间常数初值低8位 MOV TH0, #0FFH ;时间常数初值高8位 CLR ET0 ;禁止T0中断 SETB TR0 ;启动T0 LOOP: JBC TF0, DONE ;检查T0溢出否 SJMP LOOP ;未计满再查 DONE: MOV TL0, #06H ;计满重装时间常数初值 MOV TH0, #0FFH CPL P1.0 ;将P1.0输出电平反相; SJMP
13、LOOP 【例5-6】利用定时器T1的模式2对外部信号计数。要求每计满100次,累加器A加1。 解: 计算T1的计数初值 :X=28-100=156D=9CH 因此,TL1的初值为9CH,重装初值寄存器TH1=9CH. 程序清单: ORG 0000H LJMP MAIN ORG 001BH ;中断服务程序入口 LJMP INTT1 MAIN: MOV TMOD, #60H ;T1为模式2计数方式 MOV TL1, #9CH ;赋初值 MO
14、V TH1, #9CH MOV IE, #88H ;定时器T1开中断 SETB TR1 ;启动计数器 HERE: SJMP HERE ;等待中断 中断服务程序: INTT1: CPL P1.0 RETI 【例5-7】用T0方式3,分别产生200μs和300μs的定时,并使P1.0和P1.1分别产生400μs和600μs的方波。(fosc=6MHz) 解:本题需要2个定时器TH0和TL0 计数初始值计算:(28-初始值)×2=200/300
15、 TH0的初值=156=9CH ; TL0的初值=106=6AH 初始化:TMOD:03H且TR0=1和TR1=1 程序: ORG 3000H START: AJMP MAIN ;转主程序 ORG 000BH ;转TR0溢出中断 AJMP PIT0 ORG 001BH ;转TR1溢出中断 AJMP PIT1 MAIN: MOV TMOD, #03H MOV TH0, #6AH MOV TL0, #9CH MOV IE,
16、8AH MOV TCON, #50H SJMP $ PIT0:MOV TH0, #6AH ;定时300us CLP P1.0 RETI PIT1:MOV TL0, #9CH ;定时200μs CLP P1.1 RETI 【例5-8】用定时器/计数器T0监视一生产线,每生产100个工件,发出一包装命令,包装成一箱,并记录其箱数。硬件电路如图5-15所示。 图5-15 例5-8题图 用T0作计数器,T为光敏三极管。当有工件通过时,三极管输出高电平,即每通过一个工件,便会产生一个计数脉冲。 T0工作
17、于计数器方式的方式2,方式控制字为TMOD:00000110B;计数初值为TH0=TL0=256-100=156=9CH;用P1.0启动包装机包装命令;用R5、R4作为箱数计数器。 程序如下: ORG 0000H LJMP MAIN ;主程序 ORG 000BH ;T0中断服务程序 LJMP COUNT ORG 0030H MAIN: MOV SP, #60H CLR P1.0 MOV R5,#0 ;箱数计数器清“0” MOV R4,#
18、0 MOV TMOD,#06H ;置T0工作方式 MOV TH0, #9CH MOV TL0, #9CH SETB EA ;CPU开中断 SETB ET0 SETB TR0 SJMP $ ;模拟主程序 COUNT : MOV A, R4 ;箱数计数器加1 ADD A, #01H MOV R4,A MOV A, R5 ADDC A, #00H MOV R5,A S
19、ETB P1.0 ;启动包装 MOV R3,#100 DLY: NOP ;给外设一定时间 DJNZ R3,DLY CLR P1.0 RETI ;中断返回 END 【例5-9】设系统时钟频率为12MHz,编程实现P1.1引脚上输出周期为1s,占空比为20%的脉冲信号。 分析:根据输出要求,脉冲信号在一个周期内高电平占0.2s,低电平占0.8s,超出了定时器的最大定时间隔,因此利用定时器0产生一个基准定时配合软件计数来实现。取10ms作为基准定时,采用工作方式1,这样整个周期需要100
20、个基准定时,其中高电平占20个基准定时,低电平占80个基准定时。 程序代码如下: ORG 0000H LJMP MAIN ORG 000BH LJMP T0INT ORG 0030H MAIN: MOV SP,#60H MOV R7,#0 MOV TMOD,01H ;初始化 MOV TH0, #0D8H MOV TL0, #0F0H SETB EA SETB ET0 SETB TR0 SJMP $ 中断服务程序: T0INT:
21、MOV TH0,#0D8H ;重载初始值 MOV TL0,#0F0H INC R7 CJNE R7,#20,LL1 CLR P1.1 SJMP LLEND LL1: CJNE R7,#100,LLEND SETB P1.1 MOV R7,#00H LLEND: RETI 【例5-10】试编写利用T0产生1s定时的程序。使得由P1口控制的8个LED指示灯每隔一秒轮流闪亮(输出为低电平时亮),设fosc=6MHz。 解: 1) 定时器T0工作模
22、式的确定 因定时时间较长,使用51单片机的定时器/计数器进行定时,即使按工作方式l,其最大定时时间也只能达到131 ms,离ls还差很远。为此,我们把秒计时用硬件定时和软件计数相结合的方法实现, 采用哪一种工作模式合适呢?可以算出: 模式0最长可定时16.384ms; 模式1最长可定时131.072ms; 模式2最长可定时512μs。 题中要求定时1s,可选模式1,每隔100ms中断一次,中断10次为1s。 初始值X(设fosc=6MHZ,振荡脉冲经12分频得到机器周期) ∵(216-X) ∴X=15536=3CB0H 因此,(TL0)=0B0H,(TH0)=3CH。
23、 2) 实现方法 对于中断10次计数,可使T0工作在计数方式,也可用循环程序的方法实现。本例采用循环程序法。 3)程序设计: ORG 0000H LJMP MAIN ;上电,转向主程序 ORG 000BH ;T0的中断入口地址 AJMP DVT0 ;转向中断服务程序 ORG 2000H ;主程序 MAIN: MOV SP, #60H ;设堆栈指针 MOV R2, #0AH ;设循环次数 MOV TMOD,
24、 #01H ;设置T0工作于模式1 MOV TL0, #0B0H ;装入计数值低8位 MOV TH0, #3CH ;装入计数值高8位 SETB TR0 ;启动定时器T0 SETB ET0 ;允许T0中断 SETB EA ;允许CPU中断 SJMP $ ;等待中断 中断服务程序: DVT0: MOV TH0,#3CH MOV TL0,#0B0H
25、 DJNZ R2,RTN RL A ;左移一位 MOV P1,A MOV R2,#20 RTN: RETI 【例5-11】门控位GATE的应用 利用定时/计数器T0的门控位GATE,测量引脚上出现的脉冲宽度,并将结果(机器周期数)存入内部RAM 30H和31H单元中。 解: 1)由题意分析,外部脉冲由引脚输入,可设T0工作于定时方式1,计数初值为0,在一个完整的外部脉冲宽度内对机器周期计数(定时方式),显然计数值乘上机器周期就是脉冲宽度。
26、2)设定GATE=1,当TR0置1时,由外部脉冲上升沿启动T0开始工作。加1计数器开始对机器周期计数;引脚变为低电平时,停止计数,这时读出TH0、TL0的值,该计数值即为被测信号的脉冲宽度对应的机器周期数。测试过程如5-16图所示. 图5-16 例5-11题图 3)工作方式字TMOD=00001001B 计数初值TH0=00H,TL0=00H 4)程序设计 ORG 0000H LJMP MAIN ORG 0030H MAIN: MOV TMOD,#09H ;GATE=1 MOV TH0,
27、 #00H ;置计数初值 MOV TL0, #00H MOV R0, #30H WAIT1: JB P3.2,WAIT1 ;等待变低 SETB TR0 ;预启动T0 WAIT2: JNB P3.2,WAIT2 ;等待变高、启动计数 WAIT2: JB P3.2,WAIT3 ;等待再变低 CLR TR0
28、 ;停止计数 MOV @R0,TL0 ;读取计数值,存入指定单元 INC R0, MOV @R0,TH0 AJMP DATA ;转数据处理程序 【例6-1】利用串行口工作方式0扩展出8位并行I/O口,驱动共阳极LED数码管显示0~9。电路连接如图6-16。 把89C51串行口8位状态码串行移位输出后,TI置“l”,把Tl作为状态查询标志,则使用查询方法完成的串行口和CD4094驱动共阳极LED数码管(查表)显
29、示0-9数字的参考子程序如下: DSPLY:MOV DPTR, #TABLE MOVC A, @A+DPTR MOV SBUF, A JNB TI, $ CLR TI RET TABLE:DB 0C0H,0F9H,0A4H 0B0H,99H DB 92H,82H,0F8H,80H,90H 图6-16 共阳极LED与单片机的联接 图6-17 串行移位输入电路连接 用方式0加上并入一串出移位寄存器可扩展一个8位并行输入口。移位寄存器必须带有预置/移位的控制端,由单片机的一个输出端子加以控制,以实
30、现先由8位输入口置数到移位寄存器,然后再串行移位从单片机的串行口输入到接收缓冲器,最后再读入到CPU中。 【例6-2】用51单片机串行口外加移位寄存器CD4014(或74LSl65,166)扩展8位输入口,输入数据由8个开关提供,另有一个开关K提供联络信号。当K=0时,表示要求输入数据,输入的8位为开关量,提供逻辑模拟子程序的输入信号。如图6-17所示。 解:串行口方式0的接收要用SCON寄存器中的REN位作为开关来控制。因此,初始化时,除了设置工作方式之外,还要使REN位为l,其余各位仍然为0。 对RI采用查询方式来编写程序,当然,先要查询开关K是否闭合。 参考程序:
31、START:MOV SCON,#10H ;串行口方式0初始化 JB P1.l,$ ;开关K未闭合,等待 SETB Pl.0 ;P/=1,并行置入数据 CLR Pl.0 ;P/=0,开始串行移位 JNB RI,$ ;查询RI CLR RI ;查询结束,清RI MOV A,SBUF ;读数据到累加器 ACALL LOGSIM ;进行逻辑模拟 SJMP START ;
32、准备下一次模拟 甲机发送主程序: ORG 0023H AJMP ACINT ORG 0030H MOV TMOD,#20H ;设置定时器l工作方式2 MOV TLl,#0F3H ;定时器Tl数初值 MOV THl,#0F3H ;计数重装值 SETB EA ;中断总允许 CLR ES ;禁止串行中断 MOV PCON,#00H ;波特率不倍增 SETB TRl
33、 ;启动定时器l MOV SCON,#50H ;设置串行口方式l,REN=1 MOV SBUF,#40H ;发送数据区首地址高位 SOUTl: JNB Tl,$ ;等待一帧发送完毕 CLR Tl ;清发送中断标志 MOV SBUF,#00H ;发送数据区首地址低位 SOUT2: JNB Tl,$ ;等待一帧发送完毕 CLR TI MOV SBUF,#40H ;发
34、送数据区末地址高位 SOUT3: JNB Tl,$ ;等待一帧发送完毕 CLR Tl ;清发送中断标志 MOV SBUF,#lFH ;发送数据区末地址 SOUT4: JNB Tl,$ ;等待一帧发送完毕 CLR TI MOV DPTR,#4000H ;数据区地址指针 MOVX A,@DPTR ;读第一个数据 INC DPTR MOV R7,#20H
35、 ;数据个数 SETB ES ;开放串行中断 MOV SBUF,A ;启动发送第一个数据 DEC R7 AHALT: AJMP $ ;等待中断 甲机中断服务程序: ORG 0100H ACINT: MOVX A,@DPTR ;读数据 CLR TI ;清发送中断 MOV C,P ;奇偶标志赋予 MOV
36、 ACC.7, C ;送ASCII码高位 MOV SBUF,A ;发送字符 DEC R7 CJNE R7,#00H,AEND2 ;没发送完转AEND2 CLR ES ;发送完禁止串行中断 CLR TRl ;定时器l停止计数 AJMP AENDl AEND2: INC DPTR AENDl: RETI ;中断返回 乙机接收主程序: 0RG 0023H AJMP
37、 BCINT ORG 0030H MOV TMOD,#20H ;设置定时器l工作方式2 MOV THl,#0F3H ;定时器l计数初值 MOV TLl,#0F3H ;计数重装值 SETB EA ;中断总允许 CLR ES ;禁止串行中断 MOV PCON,#00H ;波特率不倍增 SETB TRl ;启动定时 MOV S
38、CON,#50H ;设置串行口方式l,REN=1 MOV DPTR,#5000H ;数据存放首地址 MOV R7,#24H ;接收数据个数 SINl: JNB Rl,$ ;等待一帧接收完 CLR Rl ;清接收中断标志 DEC R7 MOV A,SBUF ;接收数据区首地址高位 MOVX @DPTR,A ;存首地址高位 INC DPT
39、R ;地址指针增量 SIN2: JNB RI,$ CLR RI DEC R7 MOV A,SBUF ;接收数据区首地址低位 MOVX @DPTR,A ;存首地址低位 INC DPTR SIN3: JNB RI,$ CLR RI DEC R7 MOV A,SBUF ;接收数据区未地址高位 MOVX @DPTR,A ;存
40、本地址高位 INC DPTR SIN4: JNB RI,$ CLR RI DEC R7 MOV A,SBUF ;接收数据区未地址低位 MOVX @DPTR,A ;存末地址低位 INC DPTR SETB ES ;开放串行中断 BHALT: AJMP $ ;等待中断 乙机中断服务
41、程序: ORG 0100H BCINT: MOV A,SBUF ;接收数据 MOV C,P ;奇偶标志赋予C JNC BEND3 ;C≠l为偶数转至BEND3 ANL A,#7FH ;为奇数删去校验位 BEND3: MOVX @DPTR,A ;存数据 CLR RI ;清接收中断标志 DEC R7 CJNE R7,#00H,BENDl;没接收完转
42、BENDl CLR ES ;接收完禁止串行中断 CLR TR1 ;定时器l停止计数 AJMP BEND2 BENDl: INC DPTR BEND2: RETI ;中断返回 【例6-4】设计一个发送程序,将片内RAM 50H~5FH中的数据串行发送,串行口设定为方式2状态。TB8作奇偶校验位。在数据写入发送缓冲器之前,先将数据的奇偶位P写入TB8,这时第9位数据作奇偶校验用。 参考程序如下: TRT: MOV SCON,#80H
43、方式2设定 MOV PCON,#80H ;取波特率为fosc的1/32 MOV R0,#50H ;首地址50H送R0 MOV R7,#10H ;数据长度10H送R7 LOOP: MOV A,@R0 ;取数据送A MOV C,PSW.0 MOV TB8,C ;P送TB8 MOV SBUF,A ;数据送SBUF启动发送 WALT: JBC TI,CONT ;判
44、断发送中断标志 SJMP WALT CONT: INC R0 DJNZ R7,LOOP RET 【例6-5】设计一个接收程序,将接收的16个字节数据送入片内RAM 50H~5FH单元中。设串行口方式3状态工作,波特率为2400bps。定时钟数器Tl为工作波特率发生器时, SMOD=0,计数常数为F4H。 参考程序如下: RVE: MOV TMOD,#20H ;Tl编程为方式2定时状态 MOV TH1,#0F4H ;计数常数送Tl MOV TL1,#0F4H SETB TRl
45、 ;启动Tl MOV R0,#50H ;R0置初值 MOV R7,#10H ;数据长度10H送R7 MOV SCON,#0D0H ;串行El编程方式3接收 MOV PCON,#00H ;置SMOD=0 WAIT: JBC RI,PRI ;等待接收到数据 SJMP WAIT PRI: MOV A,SBUF JNB PSW.0,PNP ;奇偶校验判P=R1387 JNB RB8,PER ;出错转
46、至PER结束 SJMP RIGHT PNP: JB RB8,PER RIGHT:MOV @R0,A ;数据送缓冲器 INC R0 DJNZ R7,WAIT ;判数据块接完否? CLR PSW.5 ;正确接收完l6个字节置标志 PER:RET 【例8-1】对8255A各口作如下设置:A口方式0输入,B口方式1输出,C口高位部分为输出,低位部分为输入。设控制寄存器地址为003AH。 按各口的设置要求,工作方式控制字为10010101,即95
47、H。初始化程序段应为: MOV R0,#3AH MOV A,#95H MOVX @R0, A 【例8-2】若要求8255A工作在方式0,且A口作为输入口,B口、C口作为输出口,则8255A的初始化程序如下。 ORG 3000H MOV A,#90H ;置方式控制字 MOV DPTR,#2503H ;控制寄存器地址 MOVX @DPTR,A ;写控制字 MOV DPTR,#2500H ;A口地址 MOVX A,@DPTR ;从A口读数据
48、 INC DPTR ;B口地址 MOV A,#DATA1 ;需要输出的数据 MOVX @DPTR,A ;将数据送B口输出 INC DPTR ;C口地址 MOV A,#DATA2 ;需要输出的数据 MOVX @DPTR,A ;将数据送C口输出 (2)8255A的C口8位中的任意一位,都可用指令来置位或复位。 【例8-3】若想把C口的第5位PC4置1,相应的控制字为:00001001B=09H,程序如下。 MOV DPT
49、R,#2500H ;设控制寄存器地址为2500H MOV A,#09H ;控制字 MOVX @DPTR,A ;把控制子送到控制口 【例8-4】已知8255A的端口地址为02E1H~02E4H,请实现对端口C的PC2置位和PC4复位。 解: MOV DPTR,#02E4H ;大于8位的端口地址送DX MOV A,#05H ;位操作控制字=0000 0101B MOVX @DPTR,A ;置位PC2 MOV A,#08H
50、 ;位操作控制字=0000 1000B MOVX @DPTR,A ;复位PC4 【例8-5】请在8255A端口C的PC7位输出一个正脉冲(设原来PC7=0)。 解:程序段如下 MOV A, #0FH ;置位PC7,操作控制字=00001111 MOV DPTR,#CTRL_PORT ;控制端口地址 MOVX @DPTR, A ;写入控制端口 CALL DELAY ;延时产生脉宽 MOV A, #0EH ;复位PC7,操作控制字= 00001110