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

📄 clock.asm

📁 数字钟的单片机实现
💻 ASM
字号:
SCL   EQU P1.2
SDA   EQU P1.3

ORG   0000H
AJMP  MAIN

ORG   000BH
AJMP  TIME

ORG 0300H
MAIN:
MOV  20H,#00H	  ;25ms定时计数器
MOV	 21H,#50H	  ;秒
MOV  22H,#30H     ;分
MOV  23H,#12H     ;时
MOV  24H,#08H	  ;日
MOV  25H,#06H	  ;月
MOV  26H,#07H	  ;
MOV  27H,#20H	  ;年

MOV  30H,#00H     ;当30H里的值为00H时,数码管显示时间;
				  ;当30H里的值为0FFH时,数码管显示日期;
				  ;默认显示时间
MOV  31H,#00H     ;但31H里的值为00H时,闹钟关闭
				  ;但31H里的值为0FFH时,闹钟打开
				  ;默认为关闭,通过按键P3.7打开

MOV  32H,#00H	  ;若32H为0FFH,则启动闹钟计数器,使闹钟响5秒

MOV  33H,#00H     ;闹钟计数器

MOV  34H,#00H	  ;闹钟调整:若为0FFH则进入调整,使数码管显示闹钟时刻

MOV  40H,#00H	  ;闹钟,分
MOV  41H,#00H	  ;闹钟,时

MOV   A,#00H      ;24c02的读地址,读到数据为分
LCALL RD24
MOV   40H,A
NOP
MOV   A,#01H	  ;读地址,读到数据为时
LCALL RD24
MOV   41H,A

MOV  IP,#02H	  ;设置中断优先级
MOV  IE,#82H	  ;设置中断允许
MOV  TMOD,#01H	  ;设置定时器T0的工作方式,16位计数器
MOV  TL0,#00H	  ;定时器的间隔为25ms,初值为A600H,晶振频率为11.0592MHz
MOV  TH0,#0A6H
SETB TR0		  ;启动定时器T0

MOV  SP,#50H      ;重新设置堆栈指针

CLR  P1.0

NEXT:

MOV    A,31H		;判断是否允许闹钟
CJNE   A,#0FFH,NOSPEAKER
LCALL  NAOZHONG
MOV    A,32H		;判断是否到了闹钟时刻
CJNE   A,#0FFH,NOSPEAKER
LCALL  SPEAKER
NOSPEAKER:

MOV    A,31H		;闹钟开,LED灯点亮
CJNE   A,#0FFH,N_LED
CLR    P1.1
AJMP   LED_END
N_LED:
SETB   P1.1
LED_END:


;检测是否有按键按下
LCALL  KEY
;MOV    A,R6
JNZ	   ANSKEY	   ;P3口有按键按下
MOV    A,B
JZ     DISP		   ;P1口没有按键按下
MOV    A,#00H
ANSKEY:
LCALL  ANKEY

DISP:
MOV    A,34H
JNZ    G2

MOV    A,30H
JNZ    G0		  ;显示年、月、日
		
LCALL  DISP2   ;调用时、分、秒显示子程序
SJMP   G1

G0:
LCALL  DISP1   ;调用年、月、日显示子程序
SJMP   G1

G2:
LCALL  DISP3   ;显示闹钟时刻

G1:
SJMP   NEXT    ;循环显示

;主程序结束

;定时器处理子程序
TIME:
PUSH  ACC
PUSH  PSW

MOV   TL0,#00H		      ;重置定时器初值
MOV   TH0,#0A6H

INC   20H
MOV   A,20H
CJNE  A,#40,RETITIME	 ;如果25ms计数器的值为40时,即1秒到
MOV   20H,#00H

;--------------------------------------------
;闹钟计数器处理模块
MOV   A,32H
CJNE  A,#0FFH,N_NAOZHONG
MOV   A,33H
INC   A
MOV   33H,A
CJNE  A,#05H,N_NAOZHONG
MOV   31H,#00H
MOV   32H,#00H
MOV   33H,#00H

N_NAOZHONG:
;--------------------------------------------


MOV   A,21H			     ;秒处理
ADD   A,#01H
DA    A
MOV   21H,A
CJNE  A,#60H,RETITIME	 ;1分到
MOV   21H,#00H


MOV   A,22H				 ;分处理
ADD   A,#01H
DA    A
MOV   22H,A
CJNE  A,#60H,RETITIME    ;1时到
MOV   22H,#00H

MOV   A,23H	    		 ;时处理
ADD   A,#01H
DA    A
MOV   23H,A
CJNE  A,#24H,RETITIME	 ;1天到
MOV   23H,#00H

MOV   A,24H				 ;天处理
ADD   A,#01H
DA    A
MOV   24H,A
ACALL MONTH
CJNE  A,24H,RETITIME	 ;1月到
MOV   24H,#01H

MOV   A,25H			     ;月处理
ADD   A,#01H
DA	  A
MOV   25H,A
CJNE  A,#13H,RETITIME    ;1年到
MOV   25H,#01H

MOV   A,26H				 ;年处理
CJNE  A,#99H,NO_OH_YEAR	 ;
MOV   26H,#00H			 ;100年到
AJMP  OH_YEAR
NO_OH_YEAR:
ADD   A,#01H
DA    A
MOV   26H,A
AJMP  RETITIME

OH_YEAR:
MOV	  A,27H
ADD   A,#01H
DA    A
MOV   27H,A

RETITIME:
POP   PSW
POP   ACC
RETI                ;时间处理子程序结束

;月份处理子程序,返回值为当前月份数,存在A中
MONTH:
MOV  A,25H
XRL  A,#01H
JZ	 LAB1	       ;一月
MOV  A,25H
XRL  A,#02H
JZ	 LAB2
MOV  A,25H
XRL  A,#03H
JZ	 LAB1
MOV  A,25H
XRL  A,#04H
JZ	 LAB3
MOV  A,25H
XRL  A,#05H
JZ	 LAB1
MOV  A,25H
XRL  A,#06H
JZ	 LAB3
MOV  A,25H
XRL  A,#07H
JZ	 LAB1
MOV  A,25H
XRL  A,#08H
JZ	 LAB1
MOV  A,25H
XRL  A,#09H
JZ	 LAB3
MOV  A,25H
XRL  A,#10H
JZ	 LAB1
MOV  A,25H
XRL  A,#11H
JZ	 LAB3
MOV  A,25H
XRL  A,#12H
LAB1:     
MOV	 A,#32H
AJMP RETMONTH
LAB2:	
MOV	 A,#29H
AJMP RETMONTH
LAB3:	
MOV	 A,#31H
RETMONTH:	
RET		;月份处理子程序结束

;年、月、日显示子程序
DISP1:
MOV  A,24H      ;处理日数
ANL  A,#0FH
MOV  2FH,A		;2FH里为日的低4位译码
MOV  A,24H
ANL  A,#0F0H
SWAP A
MOV  2EH,A		;2EH里为日的高4位译码

MOV	 A,25H		;处理月数
ANL	 A,#0FH
MOV	 2DH,A
MOV  A,25H
ANL	 A,#0F0H
SWAP A
MOV  2CH,A

MOV	 A,26H		;处理年数
ANL  A,#0FH
MOV	 2BH,A
MOV	 A,26H
ANL	 A,#0F0H
SWAP A
MOV	 2AH,A

MOV	 A,27H
ANL	 A,#0FH
MOV	 29H,A
MOV  A,27H
ANL	 A,#0F0H
SWAP A
MOV	 28H,A

;对显示数据译码
MOV  R0,#2FH    	;显示数据的地址为:2FH--28H
MOV  R3,#08H    	;显示在8个数码管上
MOV  DPTR,#TABLE
MOV  A,#80H	   		;显示数码管地址
LOOP1:
MOV  B,A
MOV  P2,A      		;送出数码管地址
MOV  A,@R0
MOVC A,@A+DPTR
MOV  P0,A
MOV  R2,#40H     	;延时
DJNZ R2,$        	;在当前位置循环
DEC  R0 		 	;指向下一个显示数据地址
MOV  A,B
RR   A 				;改变数码管显示地址
DJNZ R3,LOOP1
RET					;年、月、日显示子程序结束

;时、分、秒显示子程序
DISP2:
MOV  A,21H			;秒处理
ANL  A,#0FH
MOV  2FH,A			;低4位存在2FH里
MOV  A,21H
ANL  A,#0F0H
SWAP A
MOV  2EH,A

MOV  2DH,#0AH	   	;显示一个“-”

MOV  A,22H			;分处理
ANL  A,#0FH
MOV  2CH,A
MOV  A,22H
ANL  A,#0F0H
SWAP A
MOV  2BH,A

MOV  2AH,#0AH	   	;显示一个“-”

MOV  A,23H			;时处理
ANL  A,#0FH
MOV  29H,A
MOV  A,23H
ANL  A,#0F0H
SWAP A
MOV  28H,A

;对显示数据译码
MOV  R0,#2FH
MOV  R3,#08H
MOV  DPTR,#TABLE
MOV  A,#80H
LOOP2:
MOV  B,A
MOV  P2,A
MOV  A,@R0
MOVC A,@A+DPTR
MOV  P0,A
MOV  R2,#40H
DJNZ R2,$
DEC  R0
MOV  A,B
RR   A
DJNZ R3,LOOP2
RET	              ;时、分、秒显示子程序结束

;闹钟时刻显示子程序
DISP3:
MOV  2FH,#0BH		;秒位置的数码管灭
MOV  2EH,#0BH
MOV  2DH,#0BH	   	

MOV  A,40H			;分处理
ANL  A,#0FH
MOV  2CH,A
MOV  A,40H
ANL  A,#0F0H
SWAP A
MOV  2BH,A

MOV  2AH,#0AH	   	;显示一个“-”

MOV  A,41H			;时处理
ANL  A,#0FH
MOV  29H,A
MOV  A,41H
ANL  A,#0F0H
SWAP A
MOV  28H,A

;对显示数据译码
MOV  R0,#2FH
MOV  R3,#08H
MOV  DPTR,#TABLE
MOV  A,#80H
LOOP3:
MOV  B,A
MOV  P2,A
MOV  A,@R0
MOVC A,@A+DPTR
MOV  P0,A
MOV  R2,#40H
DJNZ R2,$
DEC  R0
MOV  A,B
RR   A
DJNZ R3,LOOP3
RET	              ;时、分、秒显示子程序结束

TABLE:  DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0BFH,0FFH   ;0,1,2,3,4,5,6,7,8,9,-, ;

;清除数码管显示子程序
CLEAR:
MOV  R3,#08H
MOV  A,#80H
LOOP4:
MOV  B,A
MOV  P2,A
MOV  P0,#0FFH
MOV  A,B
RR   A
DJNZ R3,LOOP4
RET    ;清除数码管显示子程序结束

;按键扫描子程序(思路:连续两次读入按键值,判断是否为按键抖动,然后等待释放按键)
KEY:	
ACALL CLEAR		   ;按下按键时,数码管不显示

MOV	 P3,#0FFH	   ;第一次读入按键值
MOV  A,P3
CPL  A
JZ   KEYTIAO	   ;P3口无按键按下

MOV  P3,#0FFH	   ;第二次读入按键值
MOV  A,P3
CPL  A
JZ   KEYTIAO	    ;按键抖动,非期望

MOV  R6,A			;保存键值
LOOPKEY:
MOV  P3,#0FFH	    ;等待释放按键
MOV  A,P3
CPL  A
JNZ  LOOPKEY
MOV  A,R6		    ;按键值存在A中
MOV  B,#00H
SJMP RETKEY

KEYTIAO:
;MOV	 P1,#0FFH	   ;第一次读入按键值
MOV  A,P1
CPL  A
ANL  A,#0C0H
MOV  B,A
JZ   RETKEY 	   ;P1口无按键按下

;MOV  P1,#0FFH	   ;第二次读入按键值
MOV  A,P1
CPL  A
ANL  A,#0C0H
MOV  B,A
JZ   RETKEY 	    ;按键抖动,非期望

MOV  R5,B			;保存键值
LOOPKEYTIAO:
;MOV  P1,#0FFH	    ;等待释放按键
MOV  A,P1
CPL  A
ANL  A,#0C0H
MOV  B,A
JNZ  LOOPKEYTIAO
MOV  B,R5		    ;按键值存在B中
MOV  A,#00H
RETKEY:
RET 	;按键扫描子程序结束

;按键处理子程序(按键值从A中读入)
ANKEY:

;MOV  A,R6
JB   ACC.0,K0
JB   ACC.1,K1
JB   ACC.2,K2
JB   ACC.3,K3
JB   ACC.4,K4
JB   ACC.5,K5
JB   ACC.6,K6
JB   ACC.7,K7

MOV  A,B
JB   ACC.6,KT
JB   ACC.7,KQ
AJMP  RETANKEY

K0:
LCALL KEY0
AJMP  RETANKEY

K1:
LCALL KEY1
AJMP  RETANKEY

K2:
LCALL KEY2
AJMP  RETANKEY

K3:
LCALL KEY3
AJMP  RETANKEY

K4:
LCALL KEY4
AJMP  RETANKEY

K5:
LCALL KEY5
AJMP  RETANKEY

K6:
LCALL KEY6
AJMP  RETANKEY

K7:
LCALL KEY7
AJMP  RETANKEY

KT:
LCALL KEYTIAOZHENG
AJMP  RETANKEY

KQ:
LCALL KEYQUEREN

RETANKEY:
RET		   		;按键处理子程序结束


;按键P3.0执行的内容:改变30H里的数值,使数码管显示年、月、日或者时、分、秒
KEY0:
MOV  A,30H
CPL  A
MOV  30H,A
RET 	  ;按键P3.0子程序结束

;按键P3.1执行的内容:年或者时+1
KEY1:
MOV   A,30H
CJNE  A,#0FFH,TA_HOUR
;进行年+1
MOV   A,26H				 
CJNE  A,#99H,TA_NO_OH_YEAR
MOV   26H,#00H			 
AJMP  TA_OH_YEAR
TA_NO_OH_YEAR:
ADD   A,#01H
DA    A
MOV   26H,A
AJMP  RETKEY1
TA_OH_YEAR:
MOV	  A,27H
ADD   A,#01H
DA    A
MOV   27H,A 
AJMP  RETKEY1

;进行时+1
TA_HOUR:
MOV   A,34H
JNZ   TA_HOUR_NAOZH
;时钟时+1
MOV   A,23H	 
ADD   A,#01H
DA    A
MOV   23H,A
CJNE  A,#24H,RETKEY1
MOV   23H,#00H
AJMP  RETKEY1
;闹钟时+1
TA_HOUR_NAOZH:
MOV   A,41H	 
ADD   A,#01H
DA    A
MOV   41H,A
CJNE  A,#24H,RETKEY1
MOV   41H,#00H
RETKEY1:
RET		   ;按键P3.1子程序结束

;按键P3.2执行的内容::年或者时-1
KEY2:
MOV   A,30H
CJNE  A,#0FFH,TD_HOUR
;进行年-1
MOV   A,26H				 
CJNE  A,#00H,TD_NO_OH_YEAR
MOV   26H,#99H			 
AJMP  TD_OH_YEAR
TD_NO_OH_YEAR:
CLR   C
LCALL BCDBIN
SUBB  A,#01H
LCALL BINBCD
MOV   26H,A
AJMP  RETKEY2
TD_OH_YEAR:
MOV	  A,27H
LCALL BCDBIN
CLR   C
SUBB  A,#01H
LCALL BINBCD
MOV   27H,A 
AJMP  RETKEY2

;进行时-1
TD_HOUR:
MOV   A,34H
JNZ   TD_HOUR_NAOZH
;时钟时-1
MOV   A,23H
CJNE  A,#00H,TD_NO_OD
MOV   23H,#23H
AJMP  RETKEY2
TD_NO_OD:
LCALL BCDBIN
CLR   C	 
SUBB  A,#01H
LCALL BINBCD
MOV   23H,A
AJMP  RETKEY2
;闹钟时-1
TD_HOUR_NAOZH:
MOV   A,41H
CJNE  A,#00H,TD_NO_OD_NAOZH
MOV   41H,#23H
AJMP  RETKEY2
TD_NO_OD_NAOZH:
LCALL BCDBIN
CLR   C	 
SUBB  A,#01H
LCALL BINBCD
MOV   41H,A
RETKEY2:
RET		  ;按键P3.2子程序结束

;按键P3.3执行的内容:月或者分+1
KEY3:
MOV   A,30H
CJNE  A,#0FFH,TA_MIN
;进行月+1
MOV   A,25H			    
ADD   A,#01H
DA	  A
MOV   25H,A
CJNE  A,#13H,RETKEY3 
MOV   25H,#01H
AJMP  RETKEY3

;进行分+1
TA_MIN:
MOV   A,34H
JNZ   TA_MIN_NAOZH
;时钟分+1
MOV   A,22H	 
ADD   A,#01H
DA    A
MOV   22H,A
CJNE  A,#60H,RETKEY3
MOV   22H,#00H
AJMP  RETKEY3

TA_MIN_NAOZH:
;闹钟分+1
MOV   A,40H	 
ADD   A,#01H
DA    A
MOV   40H,A
CJNE  A,#60H,RETKEY3
MOV   40H,#00H

RETKEY3:
RET 		 ;按键P3.3子程序结束
 
;按键P3.4执行的内容:月或者分-1
KEY4:
MOV   A,30H
CJNE  A,#0FFH,TD_MIN
;进行月-1
MOV   A,25H				 
CJNE  A,#01H,TD_NO_OM
MOV   25H,#12H			 
AJMP  RETKEY4
TD_NO_OM:
CLR   C
LCALL BCDBIN
SUBB  A,#01H
LCALL BINBCD
MOV   25H,A
AJMP  RETKEY4

;进行分-1
TD_MIN:
MOV   A,34H
JNZ   TD_MIN_NAOZH
;时钟的分-1
MOV   A,22H
CJNE  A,#00H,TD_NO_OH
MOV   22H,#59H
AJMP  RETKEY4
TD_NO_OH:
LCALL BCDBIN
CLR   C	 
SUBB  A,#01H
LCALL BINBCD
MOV   22H,A
AJMP  RETKEY4

TD_MIN_NAOZH:
;闹钟的分-1
MOV   A,40H
CJNE  A,#00H,TD_NO_OH_NAOZH
MOV   40H,#59H
AJMP  RETKEY4
TD_NO_OH_NAOZH:
LCALL BCDBIN
CLR   C	 
SUBB  A,#01H
LCALL BINBCD
MOV   40H,A
RETKEY4:
RET		   ;按键P3.4子程序结束

;按键P3.5执行的内容:日或者秒+1
KEY5:
MOV   A,30H
CJNE  A,#0FFH,TA_SEC
;进行日+1
MOV   A,24H			
ADD   A,#01H
DA    A
MOV   24H,A
ACALL MONTH
CJNE  A,24H,RETKEY5	 
MOV   24H,#01H
AJMP  RETKEY5

;进行秒+1
TA_SEC:
MOV   A,21H	 
ADD   A,#01H
DA    A
MOV   21H,A
CJNE  A,#60H,RETKEY3
MOV   21H,#00H

RETKEY5:
RET 	 ;按键P3.5子程序结束

;按键P3.6执行的内容:日或者秒-1
KEY6:
MOV   A,30H
CJNE  A,#0FFH,TD_SEC
;进行日-1
MOV   A,24H				 
CJNE  A,#01H,TD_NO_ODAY
LCALL MONTH
DEC   A
MOV   24H,A			 
AJMP  RETKEY6
TD_NO_ODAY:
CLR   C
LCALL BCDBIN
SUBB  A,#01H
LCALL BINBCD
MOV   24H,A
AJMP  RETKEY4

;进行秒-1
TD_SEC:
MOV   A,21H
CJNE  A,#00H,TD_NO_OMS
MOV   21H,#59H
AJMP  RETKEY6
TD_NO_OMS:
LCALL BCDBIN
CLR   C	 
SUBB  A,#01H
LCALL BINBCD
MOV   21H,A
RETKEY6: 
RET		   ;按键P3.6子程序结束

;按键P3.7子程序
KEY7:
MOV  A,31H
CPL  A
MOV  31H,A
MOV  32H,#00H
MOV  33H,#00H
RET         ;按键P3.7子程序结束

;按键P1.6,进入闹钟调整
KEYTIAOZHENG:
MOV  34H,#0FFH
RET

;按键P1.7,确认闹钟调整
KEYQUEREN:
MOV  34H,#00H
;---------------------------
;把闹钟设置写入24c02
;写分
MOV   A,40H
MOV   B,A
MOV   A,#00H
LCALL WT24
;写时
MOV   B,41H
MOV   A,#01H
LCALL WT24
RET

;BCD码转换成BIN码
BCDBIN: 
PUSH   B
PUSH   PSW
PUSH   ACC
ANL	   A,#0F0H
SWAP   A
MOV	   B,#0AH
MUL	   AB
MOV	   B,A
POP	   ACC
ANL	   A,#0FH
ADD	   A,B
POP	   PSW
POP    B
RET

;BIN码转换成BCD码
BINBCD:	
PUSH   PSW
PUSH   B
MOV    B,#10
DIV    AB
SWAP   A
ADD    A,B
POP    B
POP	   PSW
RET

;蜂鸣器子程序
SPEAKER:
MOV   R0,#0FFH
DJNZ  R0,$
SETB  P1.0
MOV   R0,#0FFH
DJNZ  R0,$
CLR   P1.0
RET	   ;蜂鸣器子程序结束


;闹钟子程序
NAOZHONG:
MOV   A,40H
CJNE  A,22H,RETNAOZHONG
MOV   A,41H
CJNE  A,23H,RETNAOZHONG
MOV   32H,#0FFH
RETNAOZHONG:
RET

;-------------------------------------------------------------
;24c02读写相关子程序
RD24: 
PUSH  ACC ;读24C02子程序。 
SETB  SDA 
CLR   SCL 
CALL  START24 
MOV   A,#0A0H 
CALL  SHIFT8 
CALL  ACK 
POP   ACC 
CALL  SHIFT8 
CALL  ACK 
CALL  START24 
MOV   A,#0A1H 
CALL  SHIFT8 
CALL  ACK 
SETB  SDA 
MOV   R7,#8 
CLR   A 
SETB  SDA 
RD000: 
RL    A 
SETB  SCL 
MOV   C,SDA 
MOV   ACC.0,C 
CLR   SCL 
DJNZ  R7,RD000 
RET 
;-------------------------------
;写入24C02程序: 
WT24: 
PUSH  ACC 
SETB  SDA 
CLR   SCL 
CALL  START24 
MOV   A,#0A0H 
CALL  SHIFT8 
CALL  ACK 
POP   ACC 
CALL  SHIFT8 
CALL  ACK 
MOV   A,B 
CALL  SHIFT8 
CALL  ACK 
CALL  STOP 
CALL  DELAY2
MOV   46H,#0FFH
DELAY:
CALL  DELAY1
DJNZ  46H,DELAY 
RET
; -------------------------------
;开始条件
START24:
CLR   SDA 
SETB  SDA
SETB  SCL
CLR   SDA 
CLR   SCL
RET

;停止条件
STOP: 
CLR   SDA 
SETB  SCL
SETB  SDA
RET

;应答信号
ACK: 
SETB  SCL 
CLR   SCL
RET

;读、写数据
SHIFT8: 
MOV   R7,#8 
SH01: 
RLC   A
MOV   SDA,C
SETB  SCL
CLR   SCL
DJNZ  R7,SH01
RET

DELAY2:
NOP
NOP
NOP
NOP
RET

DELAY1:
MOV   45H,#01H
C_DELAY:
MOV   44H,#0FFH
DJNZ  44H,$
DJNZ  45H,C_DELAY
RET

END                 ;程序结束

⌨️ 快捷键说明

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