⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.asm

📁 电子钟完整版
💻 ASM
字号:
	 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  P3.4
	 UP_KEY		EQU  P3.3
	 DOWN_KEY	EQU  P3.5
	 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 P1.4		   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 P1.2
			CJNE A,HOUR,EXIT3
			
			MOV A,M_ALARM
			CJNE A,MIN,EXIT3
			LJMP STARTALARM

EXIT3:		SETB P3.6
			LJMP MAIN1


STARTALARM: CPL P3.6
			JNB DOWN_KEY,OFFALARM
			LJMP S1
OFFALARM:	LCALL DELY10MS
			JB DOWN_KEY,MAIN1
S2:			JNB DOWN_KEY,S2
			MOV F_ALARM,#0
			SETB P3.6
			LJMP MAIN1
S1:			LCALL DELAY
			LJMP MAIN1

;-----------------------------------键盘扫描程序---------------------------

KEY_SCAN:	LCALL DELY10MS
			JB MODE_KEY,MAIN1
			INC MODE_RG
			;SETB P1.4	   测试
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 P1.0
			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 P1.4
			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 P1.7			   
			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 P1.3
			LJMP ONALARM2

E8:			LJMP G2

KK:			LCALL DELY10MS		 ;去抖
			JB MODE_KEY,M_GLINT
W1:			JNB MODE_KEY,W1
			INC MODE_RG
			CPL P1.4
			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 P2.3
			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晶振延时1.002秒
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 P3.6
			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






				

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -