📄 clock.txt
字号:
MOV R6, A
MOV A, R2 ;补加(年-1925)中闰年补偿(一年366天)的天数
MOV B, #4
DIV AB
ADD A, R7
MOV R7, A
MOV A, #0
ADDC A, R6
MOV R6, A
MOV A, R3 ;假设每月有28天,计算(月-1)个月的总天数
DEC A
MOV B, #28 ;设每月有28天
MUL AB
ADD A, R7
MOV R7, A
MOV A, B
ADDC A, R6
MOV R6, A
MOV DPTR, #0F70H ;平年月天数补偿表起始地址(大月31天、小月30天、闰年2月29天)
MOV A, R2
INC A
MOV B, #4
DIV AB
MOV A, B
JNZ SETDPTREND
MOV DPTR, #0F80H ;闰年月天数补偿表起始地址
SETDPTREND:
MOV A, R3 ;补加月补偿天数
DEC A
MOVC A, @A+DPTR
ADD A, R7
MOV R7, A
MOV A, #0
ADDC A, R6
MOV R6, A
MOV A, R4 ;日
DEC A
ADD A, R7
MOV R7, A
MOV A, #0
ADDC A, R6
MOV R6, A
RET
;*****************************************************************************************
ORG 0580H
;计算当前是星期几,使用第0组寄存器
;入口:R6、R7,为当天距离1925年1月1日的总天数
;出口:R5,计算结果0表示星期天,1~6分别为星期一至星期六
SETWEEKDAYS:
MOV A, R7 ;取出总天数,加4(1925年1月1日为星期四)
ADD A, #4
MOV R7, A
MOV A, #0
ADDC A, R6
MOV R6, A ;计算总天数除以7的余数
MOV B, #7
DIV AB
MOV R6, B
MOV A, R7
MOV B, #7
DIV AB
MOV A, B
RL A
RL A
RL A
MOV R7, A
MOV A, R6
RL A
RL A
RL A
MOV B, #7
DIV AB
MOV R6, B
MOV R0, #3
WEEKDAYSLOOP:
MOV A, R6
CLR CY
RRC A
MOV R6, A
MOV A, R7
RRC A
MOV R7, A
DEC R0
CJNE R0, #0, WEEKDAYSLOOP
;MOV A, R7
MOV B, #7
DIV AB
MOV R5, B
RET
;*****************************************************************************************
ORG 0700H
;计算农历日期(年月日),第0组、第1组(00H~0FH)寄存器存储计算中间值
;子程序段
LUNARYEARDAYS:
;计算农历Y年的总天数
;入口,R2, Y年-1925
;出口,R4、R5,Y年的总天数
MOV R5, #5CH ;设一年29x12=348(15CH)天
MOV R4, #1
MOV DPTR, #0E00H ;资料起始地址
MOV A, R2 ;设置DPTR,原因:资料单位为字(双字节)
ADD A, DPL
MOV DPL, A
MOV A, #0
ADDC A, DPH ;在程序设计时确定该计算不会溢出
MOV DPH, A
MOV A, R2 ;取Y年月份资料高字节(1~8月份)
MOVC A, @A+DPTR
MOV R0, #0 ;累加农历Y年应补加的天数
MOV R1, #8 ;移位计数器
LOOPLUNARYEARDAYS1:
RLC A
JNC LUNARYEARDAY291
INC R0
LUNARYEARDAY291:
DJNZ R1, LOOPLUNARYEARDAYS1
MOV A, R2 ;取低字节资料的高四位
INC A
MOVC A, @A+DPTR
MOV R1, #4
LOOPLUNARYEARDAYS2:
RLC A
JNC LUNARYEARDAY292
INC R0
LUNARYEARDAY292:
DJNZ R1, LOOPLUNARYEARDAYS2
MOV A, R0
ADD A, R5
MOV R5, A
MOV A, #0
ADDC A, R4
MOV R4, A
LCALL LUNARLEAPDAYS ;补加Y年闰月的天数(R3)
MOV A, R3
ADD A, R5
MOV R5, A
MOV A, #0
ADDC A, R4
MOV R4, A
RET
LUNARLEAPDAYS:
;计算农历Y年的闰月的天数
;入口:R2 Y年-1925
;出口:R3,Y年闰月的天数
LCALL LUNARLEAPMONTH ;Y年有无闰月,润几月。结果存在R3
CJNE R3, #0, LUNARLEAPDAYS29
MOV R3, #0
LJMP LUNARLEAPDAYSRET
LUNARLEAPDAYS29:
MOV A, R2 ;取月份资料低字节低四位(闰月天数资料)
INC A
ADD A, #2 ;取(Y年-1924),低四位表示前一年闰月天数
MOVC A, @A+DPTR
ANL A, #0FH ;取低四位
XRL A, #0FH ;如果低四位为F,则前一年闰月30天
JZ LUNARLEAPDAYS30
MOV R3, #29
LJMP LUNARLEAPDAYSRET
LUNARLEAPDAYS30:
MOV R3, #30
LUNARLEAPDAYSRET:
RET
LUNARLEAPMONTH:
;计算农历Y年的闰月的月份
;入口:R2 Y年-1925
;出口:R3,Y年闰月的月份, 0表示Y年无闰月
MOV A, R2
INC A
MOVC A, @A+DPTR
ANL A, #0FH ;取低四位
MOV R3, A
XRL A, #0FH ;如果是F,返回0,Y年无闰月
JNZ LUNARLEAPMONTHRET
MOV R3, #0
LUNARLEAPMONTHRET:
RET
LUNARMONTHDAYS:
;计算农历Y年的M月的天数
;入口:R2 Y年-1925, R4 M月
;出口:RX,Y年M月的天数
;MOV A, R2
;MOV DPTR, #2000H ;资料起始地址
;MOV A, R2 ;设置DPTR,原因:资料单位为字(双字节)
;ADD A, DPL
;MOV DPL, A
;MOV A, #0
;ADDC A, DPH ;在程序设计时确定该计算不会溢出
;MOV DPH, A
MOV A, R2 ;取Y年月份资料高字节(1~8月份)
MOVC A, @A+DPTR
MOV 25H, A
MOV A, R4 ;循环计数器
MOV R0, A
MOV R1, #8
MOV A, 25H
LOOPMONTHDAYS1:
RLC A
MOV 01H, C
DEC R0
DEC R1
MOV 25H, A ;保存A寄存器的内容
MOV A, R0
JZ EXITLOOPMONTHDAYS2
MOV A, R1
JZ EXITLOOPMONTHDAYS1
MOV A, 25H ;恢复A寄存器的内容
LJMP LOOPMONTHDAYS1
EXITLOOPMONTHDAYS1:
MOV A, R2 ;取低字节资料
INC A
MOVC A, @A+DPTR
LOOPMONTHDAYS2:
RLC A
MOV 01H, C
DJNZ R0, LOOPMONTHDAYS2
EXITLOOPMONTHDAYS2:
JB 01H, LUNARMONTHDAYS30
MOV R3, #29
LJMP LUNARMONTHDAYSRET
LUNARMONTHDAYS30:
MOV R3, #30
LUNARMONTHDAYSRET:
RET
;计算农历日期的主程序
LUNARDATECALULATE:
;计算农历日期,使用第0组或第1组寄存器
;入口:R4、R5总天数
;出口:R2=年-1925;R4=月;R7=日
;分三段计算1925.1.24~1968.1.30、~2011.2.3、~2045.2.8、~2099.12.31
MOV A, R5
CLR C
SUBB A, #033H
MOV R7, A
MOV A, R4
SUBB A, #0B8H
MOV R6, A
MOV R2, #129
JNC EXITFENDUAN
MOV A, R5
CLR C
SUBB A, #0D4H
MOV R7, A
MOV A, R4
SUBB A, #07AH
MOV R6, A
MOV R2, #86
JNC EXITFENDUAN
MOV A, R5
CLR C
SUBB A, #076H
MOV R7, A
MOV A, R4
SUBB A, #03DH
MOV R6, A
MOV R2, #43
JNC EXITFENDUAN
MOV A, R5
CLR C
SUBB A, #017H
MOV R7, A
MOV A, R4
SUBB A, #0
MOV R6, A
MOV R2, #0
JNC EXITFENDUAN
LJMP ERRCALCULATE ;计算出错,超出日期范围
EXITFENDUAN: ;分段计算有效总天数R6、R7,年份R2,R4、R5失效后面的程序可以使用
LOOPCALCULATEYEAR:
LCALL LUNARYEARDAYS
MOV A, R7
CLR C
SUBB A, R5
MOV R7, A
MOV A, R6
SUBB A, R4
MOV R6, A
JC EXITLOOPCALCULATEYEAR
INC R2
MOV A, R2
XRL A, #176 ;大于175(2100年)退出循环
JNZ PASSERRCALCULATE2
LJMP ERRCALCULATE
PASSERRCALCULATE2:
LJMP LOOPCALCULATEYEAR
EXITLOOPCALCULATEYEAR:
MOV A, R7 ;加上最后一年减掉的天数,当年已经过去的天数,用于计算月份和日期
ADD A, R5
MOV R7, A
MOV A, R6
ADDC A, R4
MOV R6, A
;DEC R2 ;如果是零,为1926年
LCALL LUNARLEAPMONTH ;判断是否有闰月,月份存在R3
MOV A, R3
MOV R5, A
CLR 00H ;是否闰月标识
MOV R4, #1 ;计算月数
LOOPCALCULATEMONTH:
MOV A, R5
JZ CALCULATEMONTH1 ;转无闰月处理
MOV A, #1
ADD A, R5
XRL A, R4
JNZ CALCULATEMONTH1 ;转非闰月处理
JB 00H, CALCULATEMONTH1
DEC R4
SETB 00H ;设置闰年标识
LCALL LUNARLEAPDAYS ;读取当年闰月的天数R3
LJMP CALCULATEMONTH2 ;
CALCULATEMONTH1:
LCALL LUNARMONTHDAYS ;结果存放在R3中
CALCULATEMONTH2:
JNB 00H, CALCULATEMONTH3
MOV A, #1
ADD A, R5
XRL A, R4
JNZ CALCULATEMONTH3
CLR 00H ;解除闰月标识
CALCULATEMONTH3:
MOV A, R7
CLR C
SUBB A, R3
MOV R7, A
MOV A, R6
SUBB A, #0
MOV R6, A
JC EXITLOOPCALCULATEMONTH
INC R4
MOV A, R4 ;如果大于十二退出,提示错误
XRL A, #13
JZ ERRCALCULATE
LJMP LOOPCALCULATEMONTH
EXITLOOPCALCULATEMONTH:
MOV A, R5 ;判断是否闰月
JZ CALCULATEMONTH5
MOV A, #1
ADD A, R5
XRL A, R4
JNZ CALCULATEMONTH5
JNB 00H, CALCULATEMONTH4
CLR 00H
LJMP CALCULATEMONTH5
CALCULATEMONTH4:
SETB 00H
DEC R4
CALCULATEMONTH5:
MOV A, R7 ;加最后一次减的天数,当月已经过完的天数
ADD A, R3
MOV R7, A
MOV A, #0
ADDC A, R6
MOV R6, A
;DEC R4
INC R7 ;计算日期
LJMP CALCULATERET
;计算结果:R2=年-1925;R4=月;R7=日
ERRCALCULATE: ;错误显示
;错误处理程序
NOP
CALCULATERET:
RET
;****************************************************************************************
ORG 0900H
THEKEYDOWNSERVER:
;27H单元的位地址高位到低位:37、36、35、34、33、32、31、30(H)
;有键按下的位为0,本程序为按键处理分派
CLR TR1 ;关闭延时计数器
CLR EX0 ;关闭INT0中断
PUSH P0
MOV P0, #0
MOV 04H, #10 ;延时单元
KEYDELAY:
MOV 05H, #200
DJNZ 05H, $
DJNZ 04H, KEYDELAY
PUSH PSW ;保护现场
PUSH A
PUSH B
MOV PSW, #00001000B
MOV A, P1
ORL A, #0FH
MOV P1, A ;读键盘口,结果存储26H第四位
MOV A, P1
CPL A
ANL A, #0FH
JZ KEYALLOT5 ;如果无键按下,推出
ANL 26H, #0F0H
ORL 26H, A
KEYALLOT1:
MOV A, 27H
JNZ KEYALLOT2
ACALL KEYSTATE0
AJMP KEYALLOT5
KEYALLOT2:
JNB 3CH, KEYALLOT3
ACALL KEYSTATE1
AJMP KEYALLOT5
KEYALLOT3:
JNB 3DH, KEYALLOT4
ACALL KEYSTATE2
AJMP KEYALLOT5
KEYALLOT4:
JNB 3EH, KEYALLOT8
ACALL KEYSTATE3
AJMP KEYALLOT5
KEYALLOT8:
JNB 3FH, KEYALLOT5
ACALL KEYSTATE4
;AJMP KEYALLOT5
KEYALLOT5:
POP B ;恢复现场
POP A
POP PSW
POP P0
;设置延时计数器,如果在5秒钟内没有按键动作自动转到时间显示状态
MOV TH1, #0
MOV TF0, #0
MOV 03H, #255
CLR IE0
SETB EX0
SETB TR1 ;计时开始
RETI
KEYSTATE0:
;状态0按键处理,时间显示状态
STATE0KEY0:
JNB 30H, STATE0KEY1
MOV 27H, #10H
ACALL PRESETALARMTIME
AJMP KEYSTATE0RET
STATE0KEY1:
JNB 31H, STATE0KEY2
AJMP STATE0KEY12
STATE0KEY2:
JNB 32H, STATE0KEY3
STATE0KEY12:
MOV 27H, #24H
MOV R0, 18H
MOV R1, 19H
MOV R2, 1AH
MOV R3, 1BH
MOV R6, 36H
MOV R7, 37H
MOV A, 32H
ANL A, #0F0H
ANL 26H, #0FH
ORL 26H, A
AJMP KEYSTATE0RET
STATE0KEY3:
JNB 33H, KEYSTATE0RET
MOV 27H, #48H
;AJMP KEYSTATE0RET
KEYSTATE0RET:
RET
KEYSTATE1:
;状态1按键处理,闹钟设置状态
STATE1KEY0:
JNB 30H, STATE1KEY1
ACALL SETALARMTIME ;SET
MOV 27H, #21H ;初始化万年历状态
MOV R0, 18H
MOV R1, 19H
MOV R2, 1AH
MOV R3, 1BH
MOV R6, 36H
MOV R7, 37H
MOV A, 32H
ANL A, #0F0H
ANL 26H, #0FH
ORL 26H, A
AJMP KEYSTATE1RET
STATE1KEY1:
JNB 31H, STATE1KEY2
JB 3BH, STATE1KEY1MIN ;UP
INC R4
CJNE R4, #25, STATE1KEY1HOUR
MOV R4, #0
STATE1KEY1HOUR:
AJMP KEYSTATE1RET
STATE1KEY1MIN:
ACALL MINUTEADJUST
AJMP KEYSTATE1RET
STATE1KEY2:
JNB 32H, STATE1KEY3
JB 3BH, STATE1KEY2MIN ;DOWN
DEC R4
CJNE R4, #0FFH, STATE1KEY2HOUR
MOV R4, #24
STATE1KEY2HOUR:
AJMP KEYSTATE1RET
STATE1KEY2MIN:
ACALL MINUTEADJUST
AJMP KEYSTATE1RET
STATE1KEY3:
JNB 33H, KEYSTATE1RET
JNB 3BH, STATE1KEY3CHANGE ;RIGHT
ACALL SETALARMTIME
MOV A, 27H
ANL A, #03H
INC A
MOV B, #4
DIV AB
MOV A, B
ANL 27H, #0F0H
ORL 27H, A
ACALL PRESETALARMTIME
AJMP KEYSTATE1RET
STATE1KEY3CHANGE:
SETB 3BH ;切换到分钟调整
;AJMP KEYSTATE1RET
KEYSTATE1RET:
RET
KEYSTATE2:
;状态2按键处理,万年历查看状态
STATE2KEYO:
JNB 30H, STATE2KEY1
MOV 27H, #41H ;按键0,SET
AJMP KEYSTATE2RET
STATE2KEY1:
JNB 31H, STATE2KEY2
JNB 38H, STATE2KEY1YEAR ;按键1, UP
MOV B, #10
ACALL YEARADJUST
AJMP KEYSTATE2RET
STATE2KEY1YEAR:
JNB 39H, STATE2KEY1MONTH
MOV B, #1
ACALL YEARADJUST
AJMP KEYSTATE2RET
STATE2KEY1MONTH:
JNB 3AH, STATE2KEY1DATE
ACALL MONTHADJUST
AJMP KEYSTATE2RET
STATE2KEY1DATE:
JNB 3BH, KEYSTATE2RET
ACALL DATEADJUST
AJMP KEYSTATE2RET
STATE2KEY2:
JNB 32H, STATE2KEY3
JNB 38H, STATE2KEY2YEAR ;按键2, DOWN
MOV B, #10
ACALL YEARADJUST
AJMP KEYSTATE2RET
STATE2KEY2YEAR:
JNB 39H, STATE2KEY2MONTH
MOV B, #1
ACALL YEARADJUST
AJMP KEYSTATE2RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -