这个可以做到,如果晶振是12M的话,一下方法可以实现延时1小时,精确度在秒级别。
DELAY1H:
MOV R7,#180 ;1/1000000
DLY1H:
LCALL DELAY_20S ;18019960603s +2180
DJNZ R7,DLY1H ;2180/1000000
RET 2/1000000
共延时时间:35929s误差为71秒,如果再精确的话,再加一点延时就可以了。
DELAY_20S: ;Total=19960603s
MOV R2,# ;1
DLY1:
MOV R3,#200 ;1200
DLY2:
MOV R4,#248 ;1200200
DJNZ R4,$ ;2248200200
DJNZ R3,DLY2 ;2200200
DJNZ R2,DLY1 ;2200
RET ;2
//晶振12M
DSEG AT 30H
timetemp: DS 1
LED: DS 1
CSEG AT 00H
ORG 0000H
LJMP START
ORG 000BH
LJMP Timer0Interrupt
START:
MOV SP,#60H
MOV timetemp,#20
MOV P1,#0FFH;LED低电平点亮
LCALL InitTimer0
MOV LED,#0FEH
LOOP:
MOV P1,LED ;add your code here!
LJMP LOOP
InitTimer0:
MOV TMOD,#01H
MOV TH0,#HIGH(65536-50000)
MOV TL0,#LOW(65536-50000);延时50ms
SETB EA
SETB ET0
SETB TR0
RET
Timer0Interrupt:
PUSH ACC
PUSH PSW
CLR TR1
MOV A,TL1
ADD A,#LOW(65536-50000)+7
MOV TL1,A
CLR A
ADDC A,#HIGH(65536-50000)
SETB TR1
DJNZ timetemp,NEXTT1
MOV timetemp,#20
;========================
MOV A,LED
RL A
MOV LED,A;add your code here!
;========================
POP PSW
POP ACC
RETI
这个是循环查询定时器溢出标志位是否为一,即查询法。
ORG 00H
LJMP MAIN
ORG 30H
MAIN:
MOV TMOD,#10H
MOV TCON,#00H
MOV TL1,#78H
MOV TH1,#0ECH
SETB TR1 //启动定时器T1
LOOP:
JBC TF1,TIME1 //等待定时器溢出
SJMP LOOP
TIME1:
MOV TL1,#78H //重装初值
MOV TH1,#0ECH
SJMP LOOP
RET
END
中断法
ORG 00H
LJMP MAIN
ORG 001BH
LJMP TIME_1
ORG 30H
MAIN:
MOV TMOD,#10H
MOV TCON,#00H
MOV TL1,#78H
MOV TH1,#0ECH
SETB ET1
SETB EA
SETB TR1 //启动定时器T1
SJMP $ //等待中断,TR1置一
TIME_1:
MOV TL1,#78H //重装初值
MOV TH1,#0ECH
RETI
END
改动如下:
……
INT_SUB:
MOV TH0,#3CH;重新给定时/计数器设初值
MOV TL0,#0B0H
DJNZ R7,LOOP;判断记时次数是否够,一次50毫秒,共十次
RL A
MOV P1,A
MOV R7,#10;重新给计时循环次数赋值
LOOP:
RETI
END
这就可以了。
MODE_RG EQU 40H ;模式选择
MODE2 EQU 60H ;MODE值
MODE3 EQU 61H
MODE4 EQU 62H
MODE5 EQU 63H
MODE6 EQU 64H
MODE1 EQU 65H
HOUR EQU 41H ;小时缓冲区
MIN EQU 42H ;分钟缓冲区
SEC EQU 43H ;秒缓冲区
TEMP EQU 4AH
;闹钟缓冲区
H_ALARM EQU 6AH ;闹钟缓冲区
M_ALARM EQU 6BH
S_ALARM EQU 6CH
F_ALARM EQU 6DH
;秒表缓冲区
M_SEC EQU 76H
S_SEC EQU 77H
;LED送显示临时变量
LED0 EQU 51H
LED1 EQU 52H
LED2 EQU 53H
LED3 EQU 54H
MODE_KEY EQU P34
UP_KEY EQU P33
DOWN_KEY EQU P35
BUF EQU 49H
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP INT_0
ORG 001BH
LJMP INT_1
ORG 0080H
MAIN: MOV SP,#2FH ;堆栈初始化
MOV MODE_RG,#0 ;MODE_RG寄存器值初始化
MOV LED0,#0FEH ;初始化LED
MOV LED1,#0FDH
MOV LED2,#0FBH
MOV LED3,#0F7H
MOV MODE1,#1
MOV MODE2,#2
MOV MODE3,#3
MOV MODE4,#4
MOV MODE5,#5
MOV MODE6,#6
MOV F_ALARM,#0 ;错误2:一开始用 CLR F_ALARM,这导致在后面的时候JZ F_ALARM 运行错误,
MOV BUF,#0 ;在于 JZ 指令是对累加器A全为0或者全为1进行判断,CLR只能对一位 *** 作
MOV TMOD,#11H ;定时器初始化:定时器0,方式1,定时器1,方式1
MOV IP,#00001000B ;定时器1优先级高
MOV TH0,#3CH ;定时50MS
MOV TL0,#0B1H
MOV TH1,#0D8H ;定时10MS
MOV TL1,#0F0H
SETB EA
SETB ET0
SETB ET1
SETB TR0 ;启动定时器
MOV HOUR,#0 ;for test
MOV MIN,#0
MOV SEC,#0 ;定时器计数器,50MS中断一次,200次则刚好1S
MOV M_SEC,#0
MOV S_SEC,#0
MOV H_ALARM,#0
MOV M_ALARM,#0
MAIN1: LCALL DISPLAY12
LCALL DISPLAY34
;CLR P14 TEST
JNB MODE_KEY,KEY_SCAN
MOV A,MODE_RG
CJNE A,MODE6,Y1 ;MODE6 秒表
JNB DOWN_KEY,DEALDOWN ;判断秒表开关
JNB UP_KEY,DEALUP
Y1: MOV A,F_ALARM ;判断闹钟
JNZ ALARM
LJMP MAIN1
;-----------------------------------秒表开关程序---------------------------
DEALDOWN: LCALL DELY10MS
JB DOWN_KEY,MAIN1
H1: JNB DOWN_KEY,H1
CPL TR1
LJMP MAIN1
DEALUP: LCALL DELY10MS
JB UP_KEY,MAIN1
H2: JNB UP_KEY,H2
MOV M_SEC,#0
MOV S_SEC,#0
CLR TR1
LJMP MAIN1
;-----------------------------------闹钟扫描程序---------------------------
ALARM: MOV A,H_ALARM
CPL P12
CJNE A,HOUR,EXIT3
MOV A,M_ALARM
CJNE A,MIN,EXIT3
LJMP STARTALARM
EXIT3: SETB P36
LJMP MAIN1
STARTALARM: CPL P36
JNB DOWN_KEY,OFFALARM
LJMP S1
OFFALARM: LCALL DELY10MS
JB DOWN_KEY,MAIN1
S2: JNB DOWN_KEY,S2
MOV F_ALARM,#0
SETB P36
LJMP MAIN1
S1: LCALL DELAY
LJMP MAIN1
;-----------------------------------键盘扫描程序---------------------------
KEY_SCAN: LCALL DELY10MS
JB MODE_KEY,MAIN1
INC MODE_RG
;SETB P14 测试
K1: JNB MODE_KEY,K1 ;按键直到用户松开按键
K2: MOV A,MODE_RG
CJNE A,#0,DEALMODE ;不是在正常显示模式下则跳转到模式处理程序
LJMP MAIN1 ;返回主程序
;模式处理程序部分
DEALMODE: MOV TEMP,#0 ;凡转入MODE处理,则首先清除TEMP
MOV A,MODE_RG ;有MODE_RG值不为5、0
CJNE A,MODE2,M0 ;判断MODE_RG值,不为1跳转
LJMP H_GLINT ;模式1,小时位闪烁
M0: CJNE A,MODE3,M1 ;不是模式2,跳转
LJMP M_GLINT ;模式2,分钟位闪烁
M1: CJNE A,MODE4,M2 ;不是模式3,跳转
LJMP H_GLINT
M2: CJNE A,MODE5,M3
LJMP M_GLINT
M3: CJNE A,MODE6,M4
MOV M_SEC,#0
MOV S_SEC,#0
LJMP MAIN1
M4: CJNE A,MODE1,M5
;CLR TR1
LJMP MAIN1
M5: MOV MODE_RG,#0
LJMP MAIN1
;MODE为1,3,小时位闪烁
//MOV TEMP,HOUR ;将TEMP赋值,防止在加的时候是在随机值的基础上增加
H_GLINT: ;CPL P10
MOV R0,#28
MOV R1,#28
K4: LCALL DISPLAY12 ;分开显示
LCALL DISPLAY34
E1: JNB MODE_KEY,K21 ;检测是否有按键按下,有按下则跳转到分钟位闪烁
JB UP_KEY,E9 ;判断加位有无按键按下
LJMP UP
E9: DJNZ R0,K4
K6: LCALL DISPLAY34
JNB MODE_KEY,K21 ;检测是否有按键按下,有按下则跳转延时后进行模式判断
LJMP G1
K21: LCALL DELY10MS ;延时后确定有MODE按键按下,将
JB MODE_KEY,H_GLINT
W: JNB MODE_KEY,W
INC MODE_RG
CPL P14
LJMP DEALMODE ;确定有按下,MODE+1后返回MODE处理程序
JNB UP_KEY,UP ;判断加位有无按键按下
G1: DJNZ R1,K6
LJMP H_GLINT ;调用完毕返回,实现闪烁
K3: LJMP MAIN1 ;可省略
;MODE为2,4,分钟位闪烁
M_GLINT: MOV R0,#28
MOV R1,#28
K23: CPL P17
LCALL DISPLAY12
LCALL DISPLAY34
JNB MODE_KEY,KK ;跳转,确定是否有按键按下
JNB UP_KEY,UP ;判断加位有无按键按下
MOV A,MODE_RG
CJNE A,MODE3,E2 ;在MODE5的情况下要判断闹钟确认键有没按下
LJMP E5
E2: JNB DOWN_KEY,F2
LJMP E5
F2: LJMP ONALARM2
E5: DJNZ R0,K23
K24: LCALL DISPLAY12
JNB MODE_KEY,KK ;检测是否有按键按下,有按下则跳转
JNB UP_KEY,UP ;判断加位有无按键按下
MOV A,MODE_RG ;扫描闹钟确认键
CJNE A,MODE3,E7 ;在MODE5的情况下要判断闹钟确认键有没按下
LJMP G2
E7: JB DOWN_KEY,E8
CPL P13
LJMP ONALARM2
E8: LJMP G2
KK: LCALL DELY10MS ;去抖
JB MODE_KEY,M_GLINT
W1: JNB MODE_KEY,W1
INC MODE_RG
CPL P14
LJMP DEALMODE ;确定有按下,MODE+1后返回MODE处理程序
G2: DJNZ R1,K24
LJMP M_GLINT
;位加,处理程序
;小时调整
UP: MOV R1,#20
UP11: INC TEMP
UP12: MOV A,MODE_RG ;判断此时的MODE,根据MODE将临时变量给对应的赋值
CJNE A,MODE2,AA0 ;不是在MODE2的情况下跳转
MOV A,TEMP
CJNE A,#24,A_UP1
MOV TEMP,#0
A_UP1: MOV HOUR,TEMP ;为MODE2,将临时变量赋给小时位
LJMP UP15
AA0: CJNE A,MODE4,UP13 //UP13为分钟调整入口
MOV A,TEMP
CJNE A,#24,A_UP
MOV TEMP,#0
A_UP: MOV H_ALARM,TEMP ;模式3,将临时变量赋给闹钟的小时位
LJMP UP15 ;UP15为显示入口
;分钟调整入口
UP13: MOV A,MODE_RG
CJNE A,MODE3,UP14 ;不是模式2,跳转
MOV A,TEMP
CJNE A,#60,DISOVER2
MOV TEMP,#0
DISOVER2: MOV MIN,TEMP
LJMP UP15
UP14: MOV A,TEMP ;上面判断不是模式2,则必然是模式4
CJNE A,#60,DISOVER3
MOV TEMP,#0
DISOVER3: MOV M_ALARM,TEMP
LJMP UP15
UP15: LCALL DISPLAY12
LCALL DISPLAY34
DJNZ R1,UP01
MOV R1,#1 ;
JNB UP_KEY,UP11
UP01: JNB UP_KEY,UP12
UP16: MOV A,MODE_RG ;松开键以后按照模式判断该返回哪种状态,不能返回DEALMODE函数
CJNE A,MODE2,UP17
LJMP H_GLINT
UP17: CJNE A,MODE3,UP18
MOV SEC,#0 ;每次设置完时间后将秒钟位置零保证时间准确
LJMP M_GLINT
UP18: CJNE A,MODE4,UP19
LJMP H_GLINT
UP19: CJNE A,MODE5,UP20
LJMP M_GLINT
UP20: LJMP MAIN1
ONALARM2: LCALL DELY10MS ;延时10MS,去抖
JB DOWN_KEY,B2 ;抖动所致,返回分钟位闪烁
LJMP K42
B2: LJMP M_GLINT
K42: JNB DOWN_KEY,K42
MOV F_ALARM,#0FFH
MOV MODE_RG,#0
LJMP MAIN1
;---------------------------------------中断程序入口---------------------
;时间中断0
;错误1:中断程序EXIT处用了MAIN1,导致一直处于中断状态
INT_0: PUSH ACC
PUSH PSW
MOV TH0,#3CH
MOV TL0,#0B1H
INC BUF
MOV A,BUF
CJNE A,#20,EXIT
TIME: MOV BUF,#0
INC SEC
MOV A,SEC
CJNE A,#60,EXIT
MOV SEC,#00H
INC MIN
MOV A,MIN
CJNE A,#60,EXIT
MOV MIN,#00H
INC HOUR
MOV A,HOUR
CJNE A,#24,EXIT
MOV HOUR,#0
RETI
EXIT: POP PSW
POP ACC
RETI
;时间中断1
INT_1: MOV TH1,#0D8H ;定时10MS
MOV TL1,#0F0H
INC S_SEC
MOV A,S_SEC
CJNE A,#100,EXIT4
MOV S_SEC,#0
INC M_SEC
MOV A,M_SEC
CJNE A,#100,EXIT4
MOV M_SEC,#0
EXIT4: RETI
;---------------------------------------显示-----------------------------
DISPLAY12: MOV A,MODE_RG ;判断模式,决定是显示闹钟时间还是显示当前时间
CJNE A,MODE4,DIS0 ;模式四,显示闹钟
LJMP DIS01 ;MODE4
DIS0: CJNE A,MODE5,DIS20
DIS01: MOV R7,H_ALARM ;闹钟模式
LJMP DIS2
DIS20: CJNE A,MODE6,DIS21
MOV R7,M_SEC ;秒表模式,显示秒表高位
LJMP DIS2
DIS21: CJNE A,MODE1,DIS1
LJMP DIS22
DIS22: MOV R7,MIN
LJMP DIS2
DIS1: MOV R7,HOUR ;DISPLAY12显示高位
DIS2: LCALL BCTD ;判断完毕,调用显示
;将秒、分 分别转码,放到R4,R3
MOV A,R4
MOV R3,A
LCALL DIVIDE
MOV DPTR,#NUMTAB
MOV P2,#0FH
MOV P2,LED0
MOV A,45H ;从拆字的出口获取值
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
MOV P2,LED1
MOV A,46H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
RET
DISPLAY34: MOV A,MODE_RG ;判断模式,决定是显示闹钟时间还是显示当前时间
CJNE A,MODE4,DIS31
LJMP DIS32
DIS31: CJNE A,MODE5,DIS35
DIS32: MOV R7,M_ALARM
LJMP DIS34
DIS35: CJNE A,MODE6,DIS41
MOV R7,S_SEC ;秒表模式,显示秒表低位
LJMP DIS34
DIS41: CJNE A,MODE1,DIS33
MOV R7,SEC
LJMP DIS34
DIS33: MOV R7,MIN ;DISPLAY34显示低位
DIS34: LCALL BCTD
MOV A,R4
MOV R3,A
LCALL DIVIDE
MOV P2,LED2
MOV A,47H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
MOV P2,LED3
MOV A,48H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
SETB P23
RET
;--------------------二翻十:入口:R6R7 出口:R2R3R4----------------------
BCTD: MOV R5,#16
CLR A
MOV R2,A
MOV R3,A
MOV R4,A
LOOP: CLR C
MOV A,R7
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
MOV A,R3
ADDC A,R3
DA A
MOV R3,A
MOV A,R2
ADDC A,R2
DA A
MOV R2,A
DJNZ R5,LOOP
RET
;-----------------------拆字:入口:R3R4 出口:45H46H47H48H------------------
DIVIDE: MOV A,R3
ANL A,#0FH
MOV 46H,A
MOV A,R3
ANL A,#0F0H
SWAP A
MOV 45H,A ;时拆字 45H放时高位,46H放十低位
MOV A,R4
ANL A,#0FH
MOV 48H,A
MOV A,R4
ANL A,#0F0H
SWAP A
MOV 47H,A ;分拆字 47H放分高位,48H放分低位
RET
;------------------------------------延时----------------------------------
DELY10MS: MOV R6,#10
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
DELAY: MOV 74H,#2 ;延时子程序,12M晶振延时1002秒
L3: MOV 72H ,#10
L1: MOV 73H ,#249
L2: DJNZ 73H ,L2
LCALL DISPLAY12
LCALL DISPLAY34
JNB DOWN_KEY,OFFALARM1
LJMP S3
OFFALARM1: LCALL DELY10MS
JB DOWN_KEY,S3
S4: JNB DOWN_KEY,S4
MOV F_ALARM,#0
SETB P36
LJMP MAIN1
S3: DJNZ 72H ,L1
DJNZ 74H ,L3
RET
NUMTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH ;码表
END
ORG 00H ;程序初始地址
SJMP STAR ;跳转到STAR
ORG 1BH ;定时器T1的中断向量地址
SJMP T1S ;跳转到T1S
ORG 30H ;程序地址30H,即STAR标号地址
STAR: MOV R2,#99 ;将十进制数99送入R2中
MOV R4,#20 ;将十进制数20送入R4中
MOV IE,#88H ;开启EA和ET1
MOV TMOD,#10H ;使用T1的工作方式1
MOV TH1,#3CH ;给T1赋初值,这里是定时50ms
MOV TL1,#0B0H
SETB TR1 ;开启T1
MOV A,R2 ;将R2中的值送入A中
MOV B,#10 ;将十进制数10送入B中
DIV AB ;将A中的数除以B中的数,商在A中,余数在B中
ACALL SEG7 ;调用SEG7
MOV P1,A ;将A中值送入P1
MOV A,B ;将B中值送入A
ACALL SEG7 ;调用SEG7
MOV P2,A ;将A中值送入P2
SJMP $ ;死循环,等待中断
SJMP STAR
T1S: MOV TH1,#3CH ;中断程序,重新赋初值T1 50ms
MOV TL1,#0B0H
DJNZ R4,T1S0 ;R4中值先减1再看是否为0,若不为0则跳转到T1S0,若为0则顺序往下执行
MOV R4,#20 ;给R4重新赋值十进制数20,因此定时时间应该为1秒
DJNZ R2,T1S1 ;R2中值先减1再看是否为0,若不为0则跳转到T1S1,若为0则顺序往下执行
/CLR TR1/
SJMP T1S1 ;跳转到T1S1
T1S0: RETI ;中断返回
T1S1: MOV A,R2 ;将R2中的值送入A中
MOV B,#10 ;将十进制数10送入B中
DIV AB ;将A中的数除以B中的数,商在A中,余数在B中
ACALL SEG7 ;调用SEG7
MOV P1,A ;将A中值送入P1
MOV A,B ;将B中值送入A
ACALL SEG7 ;调用SEG7
MOV P2,A ;将A中值送入P2
CJNE R2,#0,T1S2 ;将R2中的值与十进制数0比较,若为0则跳转到T1S2,否则顺序执行
MOV R2,#100 ;给R2赋十进制数100
T1S2: RETI ;中断返回
SEG7: INC A ;A中的值加1
MOVC A,@A+PC ;先将PC中的值加1,然后与A相加,然后以此值为地址,将该地址中的数据送入A中
RET ;返回
DB 0C0H,0F9H,0A4H,0B0H;数据
DB 99H,92H,82H,0F8H
DB 80H,90H,88H,83H
DB 0C6H,0A1H,86H,8EH
END ;程序结束
=========================================================
我就是逐句解释了一下,至于程序要实现什么功能,我就不清楚了,要跟硬件相关
MOV TMOD,#00000001B 设定定时器0工作方式为1
如果设为工作方式2,则MOV TMOD,#00000010B
如果设为工作方式0,则MOV TMOD,#00000000B
TMOD的M1M0位确定定时器工作方式:
M1M0 工作方式 功能说明00 方式0 13位定时器/计数器
01 方式1 16位定时器/计数器
10 方式2 自动重载8位定时器/计数器
11 方式3 T0分为2个8位独立计数器,T1无方式3
以上就是关于51单片机,求用汇编语言编写延时1小时的子程序,要精确到秒级别全部的内容,包括:51单片机,求用汇编语言编写延时1小时的子程序,要精确到秒级别、51单片机,用定时器中断,在P1口实现1S移动一次的流水灯,用汇编语言编写的程序、51单片机用定时器T1编写延时10ms汇编程序 谁给写一个 急啊等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)