51单片机,求用汇编语言编写延时1小时的子程序,要精确到秒级别

51单片机,求用汇编语言编写延时1小时的子程序,要精确到秒级别,第1张

这个可以做到,如果晶振是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汇编程序 谁给写一个 急啊等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10096689.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存