资源介绍
关于8255单片机的程序设计
;变量声明区
SECOND EQU 30H ;秒
MINUTE EQU 31H ;分
HOUR EQU 32H ;时
DAY EQU 33H ;日
MONTH EQU 34H ;月
YEAR_L EQU 35H ;年低位
YEAR_H EQU 36H ;年高位
DISPBUF EQU 37H ;显示缓冲区(6字节)
DISPBIT EQU 3DH ;位选偏移量
FLAG EQU 3EH ;标记(0表示在主界面,1-6分别代表显示时、分、秒、年、月、日,0为一般显示(当前位置为主界面),7为显示日期,8为显示闹铃开关,9、10显示闹铃时和分,11表示不做缓冲处理)
KEY EQU 3FH ;按键值
CLOSE_BIT EQU 40H ;显示屏蔽(和位选相与后送P2)
A1_MINUTE EQU 41H ;闹铃1 分钟
A1_HOUR EQU 42H ;闹铃1 小时
A1_SWITCH EQU 43H ;闹铃1 开关
A2_MINUTE EQU 44H ;闹铃2 分钟
A2_HOUR EQU 45H ;闹铃2 小时
A2_SWITCH EQU 46H ;闹铃2 开关
A3_MINUTE EQU 47H ;闹铃3 分钟
A3_HOUR EQU 48H ;闹铃3 小时
A3_SWITCH EQU 49H ;闹铃3 开关
FLAG_KEEP EQU 4AH ;闹钟持续鸣叫标志(1开启,0关闭)
FLAG_ALARM EQU 4BH ;闹钟响标志(为1蜂鸣器响,为0蜂鸣器不响)
FLAG_NUM EQU 4CH ;当前闹钟标志(1-3个闹钟)
FLAG_MOVING EQU 4DH ;流水显示初始化标志(0未初始化 1已经初始化)
COUNT EQU 4EH ;T0中断次数(T0内部使用)
COUNT_1S EQU 4FH ;计数1S(满N秒后执行程序)
FLAG_1S EQU 50H ;满1秒取反标志(1秒执行程序1,另一秒执行程序2)
FLAG_ADD EQU 51H ;时间设置标记(1代表FLAG对应的时段加1)
FLAG_CLOSE EQU 52H ;闪烁显示标记(为0不闪烁)
DATE_STYLE EQU 53H ;日期显示模式标志(为1跳变切换显示,为2流水显示,为3下滑切换显示)
CLOSE_BIT_TEMP EQU 54H ;屏蔽位暂存(流水显示模式)
CLOSE_BIT_CODE EQU 55H ;段选屏蔽位(和段选相与后送P0)
KEY_TEMP EQU 56H ;临时按键值(串口发送内容)
COUNT_50MS EQU 57H ;50毫秒计数
TEMP_R0 EQU 58H ;保护R0
TEMP_R1 EQU 59H ;保护R1
TEMP_R2 EQU 5AH ;保护R2
FLAG_DOWN_S EQU 5BH ;下移显示阶段标志(每0.2s加1;0无显示,1、2移入显示,3-17正常,18、19移出显示)
MOVING_DISPBUF EQU 5CH ;临时缓冲区(流水显示模式)
;----------------------------------------------------------------------------------------------
;主程序
ORG 00H
SJMP START
ORG 0BH
LJMP INT_T0
ORG 13H
AJMP INT_1
ORG 30H
START: ;初始化
MOV SECOND,#00
MOV MINUTE,#42
MOV HOUR,#02
MOV DAY,#09
MOV MONTH,#12
MOV YEAR_L,#09
MOV YEAR_H,#20
MOV A1_SWITCH,#00H
MOV A1_MINUTE,#22
MOV A1_HOUR,#12
MOV A2_SWITCH,#00H
MOV A2_MINUTE,#00H
MOV A2_HOUR,#00H
MOV A3_SWITCH,#00H
MOV A3_MINUTE,#00H
MOV A3_HOUR,#00H
MOV DISPBIT,#00H
MOV FLAG_KEEP,00H
MOV P3,#0FH ;键盘进入监控输入状态
MOV R7,#00H ;整点报时鸣铃次数清0
SETB P2.0 ;关蜂鸣器
MOV FLAG_CLOSE,#00H
MOV FLAG,#0BH
MOV FLAG_ADD,#00H
MOV FLAG_1S,#01H
MOV COUNT,#00H
MOV KEY,#00H
SETB PT0 ;计数器中断优先级高
CLR PX1 ;外部中断1优先级低
MOV TMOD,#21H ;T0为定时器方式1,T1为方式2
SETB TR0 ;T0开始计数
MOV TL1,#0F3H ;T1初始化
MOV TH1,#0F3H ;T1重置初值
SETB TR1 ;T1开始计数
MOV SCON,#50H ;串口工作方式1,允许接收
MOV PCON,#80H ;SMOD=1
MOV IE,#10000110B ;开总中断,开T0,外部中断1
CLR IT1 ;外部中断1触发方式为电平触发
;---------------------------------------------------------------------------------------------
;基本功能模块,按1显示012345,按2显示ABCDEF,按4进入电子时钟界面
MOV CLOSE_BIT_CODE,#00H
MOV FLAG_1S,#01H
MAIN0:
ACALL DISPLAY
MOV A,KEY ;取键值
CJNE A,#01H,MAIN0_J0 ;判断键值
MOV KEY,#00H ;主菜单下KEY=1,显示012345
SHOW_012345_START: ;显示初始化
MOV CLOSE_BIT_CODE,#0FFH ;无段选屏蔽
MOV CLOSE_BIT,#81H ;屏蔽所有位选
ACALL BUF_012345 ;显示缓冲区缓存012345
SHOW_012345:
MOV A,FLAG_1S ;取1S取反标志
CJNE A,#01H,SHOW_012345_J0
CPL A ;1S已经到(FLAG_1S=1)
INC A
MOV FLAG_1S,A ;1S取反标志取反,等待下一秒
SETB C
MOV A,CLOSE_BIT
RLC A
MOV CLOSE_BIT,A ;已到1S,依次开位选
SHOW_012345_J0: ;1S未到(FLAG_1S=0),继续显示
ACALL DISPLAY
MOV A,KEY ;取键值
CJNE A,#02H,SHOW_012345_J1
MOV KEY,#00H
SJMP SHOW_ABCDEF_START ;子功能1下KEY=2,转至显示ABCDEF
SHOW_012345_J1:
CJNE A,#04H,SHOW_012345 ;子功能1下KEY不为2和4,循环
MOV KEY,#00H
SJMP MAIN1_START ;子功能1下KEY=4,转入时钟模块
MAIN0_J0:
CJNE A,#02H,MAIN0_J1
MOV KEY,#00H ;主菜单下KEY=2,显示ABCDEF
SHOW_ABCDEF_START: ;显示初始化
MOV CLOSE_BIT_CODE,#00H ;屏蔽所有段选
MOV CLOSE_BIT,#0FFH ;无位选屏蔽
ACALL BUF_ABCDEF ;显示缓冲区缓存ABCDEF
SHOW_ABCDEF:
MOV A,FLAG_1S ;取1S取反标志
CJNE A,#01H,SHOW_ABCDEF_J0
CPL A ;1S已经到(FLAG_1S=1)
INC A
MOV FLAG_1S,A ;1S取反标志取反,等待下一秒
SETB C
MOV A,CLOSE_BIT_CODE
RLC A
MOV CLOSE_BIT_CODE,A ;已到1S,依次开段选
SHOW_ABCDEF_J0: ;1S未到(FLAG_1S=0),继续显示
ACALL DISPLAY
MOV A,KEY ;取键值
CJNE A,#01H,SHOW_ABCDEF_J1
MOV KEY,#00H
SJMP SHOW_012345_START ;子功能2下KEY=1,转至显示012345
SHOW_ABCDEF_J1:
CJNE A,#04H,SHOW_ABCDEF ;子功能2下KEY不为1和4,循环
MOV KEY,#00H
SJMP MAIN1_START ;子功能2下KEY=4,转入时钟模块
MAIN0_J1:
CJNE A,#04H,MAIN0
MOV KEY,#00H ;主菜单下KEY=4,转入时钟模块
SJMP MAIN1_START
;----------------------------------------------------------------------------------------------
;缓存012345
BUF_012345:
MOV A,#DISPBUF
ADD A,#5
MOV R0,A
MOV R1,#6
MOV A,#0
BUF_012345_LOOP:
MOV @R0,A
DEC R0
INC A
DJNZ R1,BUF_012345_LOOP
RET
;----------------------------------------------------------------------------------------------
;缓存ABCDEF
BUF_ABCDEF:
MOV A,#DISPBUF
ADD A,#5
MOV R0,A
MOV R1,#6
MOV A,#0AH
BUF_ABCDEF_LOOP:
MOV @R0,A
DEC R0
INC A
DJNZ R1,BUF_ABCDEF_LOOP
RET
;----------------------------------------------------------------------------------------------
;功能模块2,电子时钟
MAIN1_START:
MOV FLAG,#00H
MOV CLOSE_BIT_CODE,#0FFH
MOV CLOSE_BIT,#0FFH
MOV FLAG_CLOSE,#00H
MOV FLAG_DOWN_S,#0FFH
MAIN1:
LCALL ALARM
LCALL ALARM_TIME
LCALL BUF_TIME
LCALL DISPLAY
MOV A,KEY ;读键值
CJNE A,#01H,MAIN1_NOT_KEY1 ;KEY=1,转入功能1,否则继续判断
MOV KEY,#00H
SJMP FUN1_START
MAIN1_NOT_KEY1:
MOV A,KEY
CJNE A,#02H,MAIN1_NOT_KEY2 ;KEY=2,转入功能2,否则继续判断
MOV KEY,#00H
SJMP FUN2_START
MAIN1_NOT_KEY2:
MOV A,KEY
CJNE A,#03H,MAIN1_NOT_KEY3 ;KEY=3,转入功能3,否则继续判断
MOV KEY,#00H
AJMP FUN3_START
MAIN1_NOT_KEY3:
MOV A,KEY
CJNE A,#04H,MAIN1_NOT_KEY4 ;KEY=4,转入功能4,否则停留在当前界面
MOV KEY,#00H
AJMP FUN4_START
MAIN1_NOT_KEY4:
SJMP MAIN1
;----------------------------------------------------------------------------------------------
;功能1界面:显示日期(YYMMDD),按1键退出
FUN1_START:
MOV FLAG,#07H ;FLAG=7,显示YYMMDD
FUN1:
LCALL BUF_TIME ;缓冲处理
LCALL DISPLAY ;执行显示
MOV A,KEY ;读键值
CJNE A,#01H,FUN1_EXIT ;KEY=1,返回主菜单,否则停留在当前界面
MOV KEY,#00H
MOV FLAG,#00H
SJMP MAIN1_START
FUN1_EXIT:
SJMP FUN1
;----------------------------------------------------------------------------------------------
;功能2界面:时间、日期动态切换,按1键切换模式(模式1显示时间->年->月日;模式2流水显示),按2键退出
FUN2_START: ;初始化,默认进入模式1
MOV FLAG,#00H
MOV FLAG_ADD,#00H
MOV FLAG_CLOSE,#00H
MOV DATE_STYLE,#01H
MOV FLAG_MOVING,#00H
MOV COUNT_1S,#06H
MOV COUNT_50MS,#00H
MOV FLAG_DOWN_S,#0FFH
MOV FLAG_1S,#01H
FUN2:
MOV A,DATE_STYLE ;读显示模式标志
CJNE A,#01H,FUN2_STYLE2 ;DATE_STYLE=01H,模式1处理,否则继续判断
MOV FLAG_MOVING,#00H ;流水显示初始化标志置0
LCALL FUN2_DATE_STYLE1 ;调用模式1显示函数
SJMP FUN2_KEY
FUN2_STYLE2:
CJNE A,#02H,FUN2_STYLE3 ;DATE_STYLE=02H,模式2处理,进入模式3处理
LCALL FUN2_DATE_STYLE2
SJMP FUN2_KEY
FUN2_STYLE3:
MOV FLAG_MOVING,#00H ;流水显示初始化标志置0
LCALL FUN2_DATE_STYLE3 ;调用模式3处理
FUN2_KEY:
MOV A,KEY ;取键值
CJNE A,#02H,FUN2_J0 ;KEY=2,返回主菜单,否则继续判断
MOV KEY,#00H
AJMP MAIN1_START
FUN2_J0:
CJNE A,#01H,FUN2_J1 ;KEY=1切换显示模式,否则停留在主界面
MOV KEY,#00H ;切换显示模式后标志初始化处理
WAIT_TIME:
MOV P0,#00H
MOV A,COUNT
CJNE A,#00H,WAIT_TIME ;切换显示后等待COUNT类标志同步计时开始
MOV FLAG_1S,#01H
MOV COUNT_1S,#06H
MOV COUNT_50MS,#00H
MOV FLAG,#02H
MOV FLAG_DOWN_S,#0FFH
INC DATE_STYLE
MOV A,DATE_STYLE
CJNE A,#04H,FUN2_J1
MOV DATE_STYLE,#01H ;DATE_STYLE复位
FUN2_J1:
SJMP FUN2
;----------------------------------------------------------------------------------------------
;界面子函数1:日期显示动态显示模式1处理
FUN2_DATE_STYLE1:
MOV A,COUNT_1S
CLR C
SUBB A,#06H
JC FUN2_DATE_STYLE1_J0 ;COUNT_1S>=6,刚进入模式1显示,默认显示时分秒,否则跳过
MOV COUNT_1S,#00H
FUN2_DATE_STYLE1_J0:
MOV A,COUNT_1S ;取COUNT_1S
CJNE A,#00H,FUN2_DATE_STYLE1_J1 ;COUNT_1S=00H,时间显示(4秒),否则继续判断
MOV FLAG,#01H ;FLAG为1或者2、3,显示时分秒
SJMP FUN2_DATE_STYLE1_EXIT
FUN2_DATE_STYLE1_J1:
CJNE A,#04H,FUN2_DATE_STYLE1_J2 ;COUNT_1S=04H,年显示(1秒),否则继续判断
MOV FLAG,#04H ;标志为4,显示年份
SJMP FUN2_DATE_STYLE1_EXIT
FUN2_DATE_STYLE1_J2:
CJNE A,#05H,FUN2_DATE_STYLE1_EXIT ;COUNT_1S=5,月份天数显示(1秒),否则返回
MOV FLAG,#05H ;标志为5或6,显示月份天数
FUN2_DATE_STYLE1_EXIT:
LCALL BUF_TIME ;显示缓冲区准备
LCALL DISPLAY ;显示缓冲区内容
RET
;----------------------------------------------------------------------------------------------
;界面子函数2:日期显示动态显示模式2处理
FUN2_DATE_STYLE2:
MOV A,COUNT_1S
CLR C
SUBB A,#6
JNC FUN2_DATE_STYLE2_MOVING ;COUNT_1S<6,正常模式显示(持续6秒)
MOV FLAG,#00H ;正常显示模式
MOV FLAG_1S,#01H ;重置1秒反转标志
LCALL BUF_TIME ;正常显示时间,调用时钟缓冲区处理函数
SJMP FUN2_DATE_STYLE2_J0
FUN2_DATE_STYLE2_MOVING: ;COUNT_1S>=6,流水显示
MOV A,FLAG_1S
CJNE A,#01H,FUN2_DATE_STYLE2_J0;FLAG_1s=1,1S到,更新缓冲区,否则跳过
CPL A ;每隔1秒更新缓冲区(FLAG_1S=01H执行)
INC A
MOV FLAG_1S,A ;反转FLAG_1S,等待下一秒再调用
MOV FLAG,#0BH ;按键中断程序无需处理缓冲区
ACALL BUF_TEMPBUF ;临时缓冲区处理
ACALL BUF_TEMPBUF_TO_DISPBUF ;流水显示缓冲区处理
FUN2_DATE_STYLE2_J0:
ACALL DISPLAY ;执行显示
RET
;----------------------------------------------------------------------------------------------
;界面子函数3:日期显示动态显示模式3处理
FUN2_DATE_STYLE3:
MOV A,COUNT_1S
CLR C
SUBB A,#4
JC FUN2_DATE_STYLE3_NEXT ;COUNT_1S>=4秒复位
MOV COUNT_1S,#00H ;COUNT_1S复位,等待下一个4s
MOV FLAG_DOWN_S,#00H ;准备进入下滑显示第一阶段
MOV COUNT_50MS,#00H
INC FLAG
INC FLAG ;每4s切换显示信息(年->月日->时间)
MOV A,FLAG
CJNE A,#8,FUN2_DATE_STYLE3_NEXT ;FLAG复位处理
MOV FLAG,#02H
FUN2_DATE_STYLE3_NEXT:
MOV A,COUNT_50MS
CJNE A,#04H,FUN2_DATE_STYLE3_EXIT ;每0.2s下移状态标志+1,否则跳过
MOV COUNT_50MS,#00H ;COUNT_50MS=0,等待下一0.2s
INC FLAG_DOWN_S
FUN2_DATE_STYLE3_EXIT:
LCALL BUF_TIME ;缓冲
LCALL DISPLAY ;显示
RET
;----------------------------------------------------------------------------------------------
;功能3界面:设置时间、日期,按1所选时段加1,按2切换时段(时->分->秒->年->月->日),按3返回主界面
FUN3_START: ;初始化
MOV FLAG,#01H ;默认显示时间(小时段闪烁)
MOV FLAG_CLOSE,#01H ;开闪烁
MOV FLAG_ADD,#00H
MOV KEY,#00H
MOV COUNT_50MS,#00H
FUN3:
LCALL BUF_TIME
LCALL DISPLAY
MOV A,KEY ;取键值
CJNE A,#02H,FUN3_NOT_KEY1 ;KEY=2,切换时段,否则继续判断
MOV KEY,#00H
INC FLAG ;标志+1
MOV A,FLAG
CJNE A,#07H,FUN3_J0 ;时段标志过6后赋1
MOV FLAG,#01H
FUN3_J0:
SJMP FUN3
FUN3_NOT_KEY1:
CJNE A,#01H,FUN3_NOT_KEY2 ;KEY=1,调时间(加1方式),否则继续判断
MOV KEY,#00H
MOV FLAG_ADD,#01H ;时段进位标志=1
ACALL FORMAT_TIME ;调用格式调整函数,更新数据
SJMP FUN3
FUN3_NOT_KEY2:
CJNE A,#03H,FUN3_NOT_KEY3 ;KEY=3,返回主界面,否则继续判断
MOV KEY,#00H
MOV FLAG,#00H
AJMP MAIN1_START
FUN3_NOT_KEY3:
CJNE A,#04H,FUN3 ;KEY=4,调时间(减1方式),否则停留在当前界面
MOV KEY,#00H
MOV FLAG_ADD,#0FFH ;时段进位标志=-1的补码
ACALL FORMAT_TIME ;调用格式调整函数,更新数据
SJMP FUN3
;----------------------------------------------------------------------------------------------
;功能4界面:设置闹铃,按1设置,按2切换指向开关状态、小时、分钟,按3切换闹铃,按4返回主菜单
FUN4_START: ;初始化
MOV FLAG,#08H ;默认显示开关状态
MOV FLAG_NUM,#01H ;默认显示第一个闹钟
MOV FLAG_CLOSE,#01H ;开闪烁
MOV KEY,#00H
FUN4:
ACALL BUF_ALARM ;缓存闹铃数据
ACALL DISPLAY ;执行显示
FUN4_J0:
MOV A,KEY ;读键值
CJNE A,#02H,FUN4_J1 ;KEY=2,切换闹铃开关、小时、分钟,否则继续判断
MOV KEY,#00H
INC FLAG ;时段标志+1
MOV A,FLAG
CJNE A,#0BH,FUN4_J0_J0 ;时段标志过10后赋8(8为闹铃开关,9为闹铃小时,10为分钟)
MOV FLAG,#08H
FUN4_J0_J0:
SJMP FUN4
FUN4_J1:
CJNE A,#01H,FUN4_J2 ;KEY=1,调闹铃,否则继续判断
MOV KEY,#00H
INC FLAG_ADD ;调整标志+1
ACALL FORMAT_ALARM ;调用处理程序
SJMP FUN4
FUN4_J2:
CJNE A,#03H,FUN4_J3 ;KEY=3,切换闹钟,否则继续判断
MOV KEY,#00H
INC FLAG_NUM ;闹铃号+1
MOV A,FLAG_NUM
CJNE A,#04H,FUN4_J2_J0 ;闹铃号满4后置1
MOV FLAG_NUM,#01H
FUN4_J2_J0:
MOV FLAG,#08H ;切换闹铃后FLAG=8,显示当前闹钟状态
SJMP FUN4
FUN4_J3:
CJNE A,#04H,FUN4_CONTINUE ;KEY=4,返回主菜单,否则停留当前界面
MOV KEY,#00H
MOV FLAG,#00H
AJMP MAIN1_START
FUN4_CONTINUE:
SJMP FUN4
;----------------------------------------------------------------------------------------------
;数据处理函数1:时间数据处理,FLAG_ADD为1时为自增调整时间,0FFH时为自减调整时间,0时为自动计时
FORMAT_TIME:
MOV A,FLAG_ADD ;取时间设置标志
CJNE A,#00H,FORMAT_TIME_ADD_REFORM ;FLAG_ADD=0,否则进入时钟模式格式调整,否则进入设置模式格式调整(无进位)
AJMP FORMAT_TIME_SECOND_REFORM
FORMAT_TIME_ADD_REFORM:
MOV A,FLAG ;取时段标志
CJNE A,#01H,FORMAT_TIME_NOT_HOUR ;FLAG=1,当前时段为小时,否则继续判断
MOV A,FLAG_ADD
ADD A,HOUR
CJNE A,#0FFH,FORMAT_TIME_NO_RESET_J0 ;小时减时复位处理
MOV A,#23
FORMAT_TIME_NO_RESET_J0:
MOV HOUR,A ;小时设置
CLR C
SUBB A,#24
JC FORMAT_TIME_J0 ;小时增时复位处理
MOV HOUR,#00H
FORMAT_TIME_J0:
AJMP FORMAT_TIME_DONE ;调整完毕,返回
FORMAT_TIME_NOT_HOUR:
CJNE A,#02H,FORMAT_TIME_NOT_MINUTE ;FLAG=2当前时段为分钟,否则继续判断
MOV A,FLAG_ADD
ADD A,MINUTE ;分钟设置
CJNE A,#0FFH,FORMAT_TIME_NO_RESET_J1 ;分钟减时复位处理
MOV A,#59
FORMAT_TIME_NO_RESET_J1:
MOV MINUTE,A
CLR C
SUBB A,#60
JC FORMAT_TIME_J1 ;分钟增时复位处理
MOV MINUTE,#00H
FORMAT_TIME_J1:
AJMP FORMAT_TIME_DONE ;调整完毕,返回
FORMAT_TIME_NOT_MINUTE:
CJNE A,#03H,FORMAT_TIME_NOT_SECOND ;FLAG=3,当前时段为秒,否则继续判断
MOV A,FLAG_ADD
ADD A,SECOND ;秒设置
CJNE A,#0FFH,FORMAT_TIME_NO_RESET_J2 ;分钟减时复位处理
MOV A,#59
FORMAT_TIME_NO_RESET_J2:
MOV SECOND,A
CLR ET0 ;关计数器中断
MOV TL0,#0B8H
MOV TH0,#3CH ;重置计数值
MOV COUNT,#00H
SETB ET0 ;开计数器中断,设置秒后重新计秒
CLR C
SUBB A,#60
JC FORMAT_TIME_J2 ;秒增时复位处理
MOV SECOND,#00H
FORMAT_TIME_J2:
AJMP FORMAT_TIME_DONE
FORMAT_TIME_NOT_SECOND:
CJNE A,#04H,FORMAT_TIME_NOT_YEAR ;FLAG=4,当前时段为年,否则继续判断
MOV A,FLAG_ADD
ADD A,YEAR_L
CJNE A,#0FFH,FORMAT_TIME_NO_RESET_J3 ;年份减时复位设置
MOV A,#99
DEC YEAR_H ;年高位借1
FORMAT_TIME_NO_RESET_J3:
MOV YEAR_L,A
MOV A,YEAR_H
CJNE A,#0FFH,FORMAT_TIME_YEAR_REFORM ;年高位减时复位设置
MOV YEAR_H,#99
SJMP FORMAT_TIME_YEAR_REFORM ;跳至时钟模式下的年复位调整
FORMAT_TIME_NOT_YEAR:
CJNE A,#05H,FORMAT_TIME_NOT_MONTH ;FLAG=5,当前时段为月,否则继续判断
MOV A,FLAG_ADD
ADD A,MONTH ;月份设置
CJNE A,#00H,FORMAT_TIME_NO_RESET_J4 ;月份减时复位设置
MOV A,#12
FORMAT_TIME_NO_RESET_J4:
MOV MONTH,A
ACALL FORMAT_YEAR ;调用闰年判断函数,月份改变后天数的复位处理
MOV A,MONTH
CLR C
SUBB A,#13
JC FORMAT_TIME_DONE ;月份增时复位处理
MOV MONTH,#01H
SJMP FORMAT_TIME_DONE
FORMAT_TIME_NOT_MONTH: ;FLAG=6,当前时段为天数
MOV A,FLAG_ADD
ADD A,DAY
MOV DAY,A
ACALL FORMAT_YEAR ;调用闰年判断函数,处理了天数调整
SJMP FORMAT_TIME_DONE
FORMAT_TIME_SECOND_REFORM:
MOV A,SECOND ;由最小位秒位开始调整
CJNE A,#60,FORMAT_TIME_DONE ;分无进位,调整结束
MOV SECOND,#00H ;秒复位
INC MINUTE ;分进位
MOV FLAG_KEEP,#00H ;每过1分钟关蜂鸣器(闹铃响1分钟)
SETB P2.0
MOV A,MINUTE
CJNE A,#60,FORMAT_TIME_DONE ;时无进位,调整结束
MOV MINUTE,#00H ;分复位
INC HOUR ;时进位
MOV A,FLAG_ADD
CJNE A,#00H,FORMAT_NO_ALARM_HOUR ;设置时间状态下跳过整点报时检测
ACALL ALARM_HOUR
FORMAT_NO_ALARM_HOUR:
MOV A,HOUR
CJNE A,#24,FORMAT_TIME_DONE ;天数无进位,调整结束
MOV HOUR,#00H ;时复位
INC DAY ;天数进位
ACALL FORMAT_YEAR ;调用闰年判断函数,处理了天数调整
MOV A,MONTH
CJNE A,#13,FORMAT_TIME_DONE ;年低位无进位,调整结束
MOV MONTH,#01H ;月复位
INC YEAR_L
FORMAT_TIME_YEAR_REFORM:
MOV A,YEAR_L
CJNE A,#100,FORMAT_TIME_DONE ;年高位无进位,调整结束
MOV YEAR_L,#00H ;年低位满100复位,向高位进1
INC YEAR_H ;高位进1
MOV A,YEAR_H
CJNE A,#100,FORMAT_TIME_DONE ;高位
MOV YEAR_H,#00H ;年高位满100复位
FORMAT_TIME_DONE:
MOV A,FLAG_ADD ;取时间设置标志
CJNE A,#00H,FORMAT_TIME_ADJUST ;FLAG=0,直接返回,否则执行设置后显示参数处理
SJMP FORMAT_TIME_EXIT
FORMAT_TIME_ADJUST:
MOV FLAG_ADD,#00H ;执行设置后,设置标志归0
MOV COUNT_50MS,#00H ;闪烁重新计秒
MOV FLAG_CLOSE,#01H ;调时间后处于相关位处于显示状态
FORMAT_TIME_EXIT:
RET
;----------------------------------------------------------------------------------------------
;数据处理1子函数:闰年判断以及月份、天数调整处理
FORMAT_YEAR:
MOV A,MONTH
CJNE A,#02H,DAY30_OR_DAY31 ;MONTH不为2,判断是30天还是31天
MOV A,YEAR_L ;取年低位
CJNE A,#00H,DIV4 ;不能被100整除的话判断是否能被4整除
MOV A,YEAR_H ;能被100整除判断能否被400整除
MOV B,#4
DIV AB
MOV A,B ;年高位除4
CJNE A,#00H,NOT_LEAP_YEAR
SJMP LEAP_YEAR ;能被400整除,为闰年
DIV4:
MOV A,YEAR_L
MOV B,#4
DIV AB
MOV A,B
CJNE A,#00H,NOT_LEAP_YEAR ;被4整除?
LEAP_YEAR: ;能被4整除,为闰年
MOV A,DAY
CJNE A,#00H,FORMAT_YEAR_NO_RESET_J0
MOV DAY,#29 ;天数减时复位设置
FORMAT_YEAR_NO_RESET_J0:
CLR C
SUBB A,#30 ;闰年下,满30天天数复位
JC FORMAT_YEAR_EXIT
SJMP FORMAT_YEAR_ADD_MONTH
NOT_LEAP_YEAR:
MOV A,DAY
CJNE A,#00H,FORMAT_YEAR_NO_RESET_J1
MOV DAY,#28 ;天数减时复位设置
FORMAT_YEAR_NO_RESET_J1: CLR C
SUBB A,#29 ;平年下,满29天天数复位
JC FORMAT_YEAR_EXIT
SJMP FORMAT_YEAR_ADD_MONTH
DAY30_OR_DAY31:
MOV A,MONTH
CJNE A,#4,NOT_M4
SJMP DAY30 ;为4月,有30天
NOT_M4:
CJNE A,#6,NOT_M6
SJMP DAY30 ;为6月,有30天
NOT_M6:
CJNE A,#9,NOT_M9
SJMP DAY30 ;为9月,有30天
NOT_M9:
CJNE A,#11,DAY31
SJMP DAY30 ;为11月,有30天
DAY31: ;余下可能为31天
MOV A,DAY
CJNE A,#00H,FORMAT_YEAR_NO_RESET_J2
MOV DAY,#31 ;天数减时复位设置
FORMAT_YEAR_NO_RESET_J2:
CLR C
SUBB A,#32
JC FORMAT_YEAR_EXIT ;大于31天,需要进位处理,否则返回
SJMP FORMAT_YEAR_ADD_MONTH
DAY30:
MOV A,DAY
CJNE A,#00H,FORMAT_YEAR_NO_RESET_J3
MOV DAY,#30 ;天数减时复位设置
FORMAT_YEAR_NO_RESET_J3:
CLR C
SUBB A,#31
JC FORMAT_YEAR_EXIT ;大于30天,需要进位处理,否则返回
FORMAT_YEAR_ADD_MONTH:
MOV DAY,#01H ;天数复位1
INC MONTH ;月进位
MOV A,FLAG_ADD ;取FLAG_ADD
CJNE A,#00H,FORMAT_YEAR_ADJUST ;FLAG_ADD=0,返回,否则在设置日期时候产生的天数归位不应产生月份进位,MONTH减1
SJMP FORMAT_YEAR_EXIT
FORMAT_YEAR_ADJUST:
DEC MONTH
FORMAT_YEAR_EXIT:
RET
;----------------------------------------------------------------------------------------------
;数据处理函数2:闹铃数据处理
FORMAT_ALARM:
MOV A,FLAG_ADD ;取设置标志
CJNE A,#00H,FORMAT_ALARM_NEXT ;FLAG_ADD=0,无修改,跳出,否则进入闹铃设置处理
SJMP FORMAT_ALARM_EXIT
FORMAT_ALARM_NEXT:
MOV R0,#A1_SWITCH
MOV A,FLAG_NUM ;取当前闹钟标志
DEC A
MOV B,#03H
MUL AB
MOV B,R0
ADD A,B
MOV R0,A ;R0指向当前闹钟开关地址
MOV A,FLAG ;取FLAG
CJNE A,#08H,FORMAT_ALARM_NOT_SWITCH
MOV A,@R0 ;FLAG=8,修改开关状态
CPL ACC.0 ;开关状态取反
MOV @R0,A ;修改开关状态
SJMP FORMAT_ALARM_EXIT
FORMAT_ALARM_NOT_SWITCH:
CJNE A,#09H,FORMAT_ALARM_NOT_HOUR
DEC R0 ;FLAG=9,修改小时,R0减1,指向小时地址
INC @R0 ;小时+1
MOV A,@R0
CJNE A,#24,FORMAT_ALARM_EXIT ;满24归0判断
MOV @R0,#00H
SJMP FORMAT_ALARM_EXIT
FORMAT_ALARM_NOT_HOUR:
DEC R0
DEC R0 ;FLAG=10,修改分钟,R0减2,指向分钟地址
INC @R0 ;分钟+1
MOV A,@R0
CJNE A,#60,FORMAT_ALARM_EXIT ;满60归0判断
MOV @R0,#00H
FORMAT_ALARM_EXIT:
MOV A,FLAG_ADD ;取FLAG_ADD
CJNE A,#01H,FORMAT_ALARM_J0
DEC FLAG_ADD ;FLAG_ADD=1,有修改,修改完成FLAG_ADD减1
MOV COUNT_50MS,#00H
MOV FLAG_CLOSE,#01H ;修改后相应位处于显示状态
FORMAT_ALARM_J0:
RET
;----------------------------------------------------------------------------------------------
;缓冲区处理函数1:显示缓冲区存时间信息,0=4,显示月份、天数
MOV CLOSE_BIT,#0BFH ;10111111,屏蔽第6位
MOV A,#MONTH
MOV R0,A ;R0指向日期
MOV R4,#01H ;R4=1
MOV R2,#02H ;存4位
BUF_TIME_START: ;数据处理,每次循环处理2位
MOV A,R4 ;取R4值
CJNE A,#01H,BUF_TIME_NO_ADD ;R4=1,月份和天数间加"-",否则不用加
MOV A,R2 ;取R2
CJNE A,#01H,BUF_TIME_NO_ADD ;R2=1,存完月份后加"-"
MOV @R1,#11H
DEC R1
BUF_TIME_NO_ADD:
MOV A,@R0
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
DEC R0
DJNZ R2,BUF_TIME_START ;R2=0,处理完毕,返回
RET
;----------------------------------------------------------------------------------------------
;缓冲区处理函数2:显示缓冲区存闹铃信息
BUF_ALARM:
MOV A,#DISPBUF
ADD A,#05H
MOV R1,A ;R1指向缓冲区高地址
MOV R0,#A1_SWITCH
MOV A,FLAG_NUM ;FLAG_NUM为偏移量
DEC A
MOV B,#03H ;每个闹铃长度为3
MUL AB
MOV B,R0
ADD A,B
MOV R0,A ;R0指向新闹铃开关地址
MOV A,FLAG_NUM
MOV @R1,#00H
MOV @R1,A ;先存闹铃号
DEC R1
DEC R1 ;R1指向缓冲区第3位
MOV A,FLAG ;取标志
CJNE A,#08H,BUF_ALARM_NOT_SWITCH ;FLAG=8,存开关状态,否则存闹铃时间
MOV @R1,#00H ;FLAG=8,存开关状态
DEC R1 ;第3位存0
MOV A,@R0 ;取状态
CJNE A,#00H,BUF_ALARM_SWITCH_ON ;A=0,开关为关,否则开关为开
MOV CLOSE_BIT,#0BBH ;10111011,开关为关时应屏蔽的位
SJMP BUF_ALARM_J0
BUF_ALARM_SWITCH_ON:
MOV CLOSE_BIT,#9BH ;10011011,开关为开时应屏蔽的位
BUF_ALARM_J0:
MOV DPTR,#SWITCH_TAB ;取开关显示状态表,存字符
MOV B,#02H
MUL AB
MOV R0,A
MOVC A,@A+DPTR
MOV @R1,A
DEC R1
INC R0
MOV A,R0
MOVC A,@A+DPTR
MOV @R1,A
SJMP BUF_ALARM_EXIT
BUF_ALARM_NOT_SWITCH:
MOV CLOSE_BIT,#0FBH ;FLAG=9和10,屏蔽第2位
MOV R2,#02H ;循环2次,存小时和分钟
INC R1 ;R1指向缓冲区第2位
BUF_ALARM_LOOP:
DEC R0
DEC R1
MOV A,@R0
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV @R1,B
DJNZ R2,BUF_ALARM_LOOP
BUF_ALARM_EXIT:
RET
;----------------------------------------------------------------------------------------------
;缓冲区处理函数3:显示缓冲区内容左移,最高位内容丢弃,最低位内容存在R6
BUF_DISPBUF_LEFT:
MOV A,#DISPBUF
ADD A,#5
MOV R1,A ;R1指向显示缓冲区高位地址
MOV R0,A
DEC R0 ;R2指向上一位地址
MOV R3,#5
BUF_DISPBUF_LEFT_LOOP:
MOV A,@R0
MOV @R1,A
DEC R1
DEC R0
DJNZ R3,BUF_DISPBUF_LEFT_LOOP ;循环,将低位内容移向高位
MOV A,R6
MOV R0,A
MOV A,@R0
MOV @R1,A ;R6内容存于最低位
RET
;----------------------------------------------------------------------------------------------
;缓冲区处理函数4:临时缓冲区存时间信息(YYYY-MM-DD HHMMSS)
BUF_TEMPBUF:
MOV A,#MOVING_DISPBUF
ADD A,#12H
MOV R1,A ;R1指向临时缓冲区高地址
MOV @R1,#12H ;第一位无内容
DEC R1
MOV R0,#YEAR_H ;R0指向年高位地址
MOV R2,#2
BUF_TEMPBUF_L1:
MOV A,@R0 ;L1循环存年
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV @R1,B
DEC R1
DEC R0
DJNZ R2,BUF_TEMPBUF_L1
MOV R2,#2
BUF_TEMPBUF_L2:
MOV @R1,#11H ;存横杆-,L2循环存月份,天数
DEC R1
MOV A,@R0
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV @R1,B
DEC R1
DEC R0
DJNZ R2,BUF_TEMPBUF_L2
MOV @R1,#12H
DEC R1
MOV @R1,#12H
DEC R1
MOV R2,#3
BUF_TEMPBUF_L3:
MOV A,@R0 ;L3循环存时分秒
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV @R1,B
DEC R1
DEC R0
DJNZ R2,BUF_TEMPBUF_L3
RET
;----------------------------------------------------------------------------------------------
;缓冲区处理函数5:临时缓冲区内容转至显示缓冲区(日期流水显示模式)
BUF_TEMPBUF_TO_DISPBUF:
MOV A,FLAG_MOVING ;读初始化标志
CJNE A,#00H,BUF_TEMPBUF_TO_DISPBUF_START;判断初始化标志,FLAG_MOVING=00H进行初始化
MOV FLAG,#00H
MOV A,#MOVING_DISPBUF
ADD A,#12H
MOV R6,A ;R6存缓冲区1高地址
MOV CLOSE_BIT_TEMP,#00H
MOV R5,#00H
MOV FLAG_MOVING,#01H ;初始化完成,FLAG_MOVING置1
BUF_TEMPBUF_TO_DISPBUF_START:
ACALL BUF_DISPBUF_LEFT ;临时缓冲区内容左移入显示缓冲区
DEC R6
INC R5
MOV A,R5
SETB C
MOV A,CLOSE_BIT_TEMP
RRC A
MOV CLOSE_BIT_TEMP,A ;屏蔽位处理(由左至右逐渐开显示)
RRC A
ORL A,#10000001B
MOV CLOSE_BIT,A ;规范化处理,赋给CLOSE_BIT
MOV A,R5 ;取流水移动位数
CJNE A,#19,BUF_TEMPBUF_TO_DISPBUF_EXIT
MOV FLAG_MOVING,#00H ;流水显示完毕,秒计数置0
MOV COUNT_1S,#00H ;流水显示完毕,秒计数复位
MOV CLOSE_BIT,#81H ;流水显示完毕,屏蔽位复位
BUF_TEMPBUF_TO_DISPBUF_EXIT:
RET
;----------------------------------------------------------------------------------------------
;显示处理函数:显示显示缓冲区内容,根据FLAG判断是否闪烁以及屏蔽位显示,DISPBIT存当前显示的位,先取段码后取位码
DISPLAY:
MOV A,P2
ANL A,#81H
MOV P2,A ;防残影
MOV A,#DISPBUF
ADD A,#05H ;指向缓冲区高位地址
CLR C
SUBB A,DISPBIT ;位偏移量
MOV R0,A ;段偏移存储
MOV A,FLAG_DOWN_S ;取下滑显示标志FLAG_DOWN_S,FLAG_DOWN_S>=20无下滑处理
CJNE A,#0,DISPLAY_NEXT0
SJMP DISPLAY_NEXT1
DISPLAY_NEXT0:
CJNE A,#1,DISPLAY_NOT_STATE1
MOV DPTR,#TABLE_STATE1
SJMP DISPLAY_CODE
DISPLAY_NOT_STATE1:
CJNE A,#2,DISPLAY_NOT_STATE2
MOV DPTR,#TABLE_STATE2
SJMP DISPLAY_CODE
DISPLAY_NOT_STATE2:
CJNE A,#18,DISPLAY_NOT_STATE3
MOV DPTR,#TABLE_STATE3
SJMP DISPLAY_CODE
DISPLAY_NOT_STATE3:
CJNE A,#19,DISPLAY_NORMAL_STATE
MOV DPTR,#TABLE_STATE4
SJMP DISPLAY_CODE
DISPLAY_NORMAL_STATE:
MOV DPTR,#TABLE ;指向字形表
DISPLAY_CODE:
MOV A,@R0 ;段偏移量
MOVC A,@A+DPTR ;取字形
ANL A,CLOSE_BIT_CODE ;屏蔽处理
DISPLAY_NEXT1:
MOV P0,A ;字形选P1口显示
MOV A,DISPBIT ;位移偏量
MOV DPTR,#TAB ;指向位选
MOVC A,@A+DPTR ;取位选通
MOV R0,A
MOV A,FLAG ;取标志FLAG
CJNE A,#00H,DISPLAY_J0 ;FLAG=0,无需闪烁和屏蔽位,否则继续判断
SJMP DISPLAY_NO_FLASH ;跳过闪烁处理
DISPLAY_J0:
CJNE A,#07H,DISPLAY_J1 ;FLAG=7,无需闪烁和屏蔽位,否则进入闪烁模式判断
SJMP DISPLAY_NO_FLASH ;跳过闪烁处理
DISPLAY_J1:
MOV A,FLAG_CLOSE ;取FLAG_CLOSE(每1秒取反,非闪烁模式置0)
CJNE A,#00H,DISPLAY_FLASH ;FLAG_CLOSE=0,不闪烁,否则进入闪烁处理
SJMP DISPLAY_NO_FLASH ;跳过闪烁处理
DISPLAY_FLASH:
CJNE A,#01H,DISPLAY_CLOSE ;FLAG_CLOSE=1,正常显示,否则屏蔽相应位,实现闪烁
SJMP DISPLAY_NO_FLASH ;为1,跳过屏蔽输出处理
DISPLAY_CLOSE:
MOV A,FLAG
CJNE A,#01,DISPLAY_NOT_HOUR ;FLAG=1,指示小时,关闭12位,否则继续判断
SJMP CLOSE12
DISPLAY_NOT_HOUR:
CJNE A,#02,DISPLAY_NOT_MINUTE ;FLAG=2,指示分钟,关闭34位,否则继续判断
SJMP CLOSE34
DISPLAY_NOT_MINUTE:
CJNE A,#03,DISPLAY_NOT_SECOND ;FLAG=3,指示分钟,关闭56位,否则继续判断
SJMP CLOSE56
DISPLAY_NOT_SECOND:
CJNE A,#04,DISPLAY_NOT_YEAR ;FLAG=4,指示年份,关闭1234位,否则继续判断
SJMP CLOSE1234
DISPLAY_NOT_YEAR:
CJNE A,#05,DISPLAY_NOT_MONTH ;FLAG=5,指示月份,关闭12位,否则继续判断
SJMP CLOSE12
DISPLAY_NOT_MONTH:
CJNE A,#06,DISPLAY_ALARM ;FLAG=6,指示天数,关闭45位,否则继续判断
SJMP CLOSE45
DISPLAY_ALARM:
CJNE A,#08,DISPLAY_ALARM_HOUR ;FLAG=8,指示闹钟开关,关345位,否则继续判断
SJMP CLOSE345
DISPLAY_ALARM_HOUR:
CJNE A,#09,DISPLAY_ALARM_MINUTE;FLAG=9,指示闹钟小时,关34位,否则继续判断
SJMP CLOSE34
DISPLAY_ALARM_MINUTE:
SJMP CLOSE56 ;FLAG=10,指示闹钟分钟,关56位
CLOSE12:
ANL CLOSE_BIT,#0F9H ;CLOSE_BIT&11111001,P2.1=P2.2=0
SJMP DISPLAY_NO_FLASH
CLOSE34:
ANL CLOSE_BIT,#0E7H ;CLOSE_BIT&11100111,P2.3=P2.4=0
SJMP DISPLAY_NO_FLASH
CLOSE45:
ANL CLOSE_BIT,#0CFH ;CLOSE_BIT&11001111,P2.4=P2.5=0
SJMP DISPLAY_NO_FLASH
CLOSE56:
ANL CLOSE_BIT,#9FH ;CLOSE_BIT&10011111,P2.5=P2.6=0
SJMP DISPLAY_NO_FLASH
CLOSE1234:
ANL CLOSE_BIT,#0E1H ;CLOSE_BIT&11100001,P2.1=P2.2=P2.3=P2.4=P2.5=P2.6=0
SJMP DISPLAY_NO_FLASH
CLOSE345:
ANL CLOSE_BIT,#0C7H ;11000111
SJMP DISPLAY_NO_FLASH
CLOSE3456:
ANL CLOSE_BIT,#87H ;10000111
DISPLAY_NO_FLASH:
MOV A,P2 ;取P2口状态
ORL A,R0 ;输出位相与,输出不影响原P2.0状态
ANL A,CLOSE_BIT ;位屏蔽处理
MOV P2,A ;位选通送P2输出
INC DISPBIT ;位偏移量+1
MOV A,DISPBIT ;取位偏移量
CJNE A,#06H,DISPLAY_EXIT ;DISPBIT=6,复位,否则返回
MOV DISPBIT,#00H
DISPLAY_EXIT:
RET
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H,0B7H,40H,00H
TAB: DB 02H,04H,08H,10H,20H,40H ;选通输出表
SWITCH_TAB: DB 0FH,0FH,10H,10H
TABLE_STATE1:DB 81H,80H,81H,81H,80H,81H,81H,80H,81H,81H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,80H
TABLE_STATE2:DB 0E2H,82H,0E0H,0C3H,82H,0C3H,0E3H,82H,0E3H,0C3H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,81H
TABLE_STATE3:DB 0D4H,84H,0CCH,0CCH,9CH,0D8H,0D8H,0C4H,0DCH,0DCH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,88H
TABLE_STATE4:DB 88H,80H,88H,88H,80H,88H,88H,88H,88H,88H,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,0FFH,80H
;----------------------------------------------------------------------------------------------
;闹铃处理函数:闹铃、整点报时,响1秒,停1秒,R7存鸣报次数
ALARM:
MOV A,FLAG_KEEP ;取闹钟持续鸣叫标志
CJNE A,#01,ALARM_NO_KEEP ;FLAG_KEEP=1,响铃处理,否则跳至整点报时
MOV A,COUNT
MOV B,#10
DIV AB
CJNE A,#01H,ALARM_L ;每0.5s改变P2.0电位,实现间断闹铃声
CLR P2.0
SJMP ALARM_EXIT
ALARM_L:
SETB P2.0
SJMP ALARM_EXIT ;返回,响闹铃时不处理整点报时
ALARM_NO_KEEP:
MOV A,R7 ;取整点报时时间
CJNE A,#00,ALARM_J0 ;R7=0,无整点报时,返回,否则进入整点报时处理
SJMP ALARM_EXIT
ALARM_J0:
MOV A,FLAG_1S ;取1S取反标志
CJNE A,#01H,ALARM_J1
MOV FLAG_ALARM,#01H ;FLAG_1S=1,FLAG_ALARM置1
CLR P2.0 ;响蜂鸣器
SJMP ALARM_EXIT ;结束
ALARM_J1:
SETB P2.0 ;FLAG_1S=0,关蜂鸣器
MOV A,FLAG_ALARM ;取FLAG_ALARM
CJNE A,#01H,ALARM_EXIT
DEC R7 ;FLAG_ALARM=1,为蜂鸣器开到蜂鸣器关转换时刻,已响1次,鸣报次数减1
MOV FLAG_ALARM,#00H ;FLAG_ALARM=0,蜂鸣器关状态
ALARM_EXIT:
RET
;----------------------------------------------------------------------------------------------;闹铃处理子函数1:整点报时检测
ALARM_HOUR:
MOV A,FLAG_ADD ;判断时间设置标志
CJNE A,#00H,ALARM_HOUR_EXIT ;FLAG_ADD=0,非设置时间模式,检测整点报时,否则返回
MOV FLAG_1S,#01H ;开1秒取反标志
MOV A,HOUR ;鸣铃次数处理(小时数转为12进制处理)
MOV B,#12
DIV AB
MOV R7,B
MOV A,R7 ;鸣铃次数存于R6
CJNE A,#00H,ALARM_HOUR_EXIT
MOV R7,#12 ;HOUR能被12整除,应鸣12次
ALARM_HOUR_EXIT:
RET
;----------------------------------------------------------------------------------------------
;闹铃处理子函数2:闹铃检测
ALARM_TIME:
MOV R2,#03H ;循环条件,检测3个闹钟
MOV R1,#A1_SWITCH ;指向第一个闹钟开关状态地址
ALARM_TIME_LOOP:
MOV A,R2
DEC A
MOV B,#03
MUL AB
ADD A,R1
MOV R0,A ;偏移量处理,指向下一个开关状态地址
MOV A,@R0
CJNE A,#01H,ALARM_TIME_NO_MATCH;开关状态判断,为0当前闹铃可跳过判断
DEC R0
MOV A,@R0 ;去闹铃小时
CLR C
SUBB A,HOUR
CJNE A,#00H,ALARM_TIME_NO_MATCH;判断小时是否符合
DEC R0
MOV A,@R0
CLR C
SUBB A,MINUTE
CJNE A,#00H,ALARM_TIME_NO_MATCH;判断分钟是否符合
MOV A,SECOND
CJNE A,#00H,ALARM_TIME_NO_MATCH;判断秒是否为0,为0说明时间刚到,响蜂鸣器
MOV FLAG_KEEP,#01H ;FLAG_KEEP=1,一直响蜂鸣器
; CLR P2.0 ;P2.0输出低电平,蜂鸣器发声
SJMP ALARM_TIME_EXIT
ALARM_TIME_NO_MATCH:
DJNZ R2,ALARM_TIME_LOOP
ALARM_TIME_EXIT:
RET
;----------------------------------------------------------------------------------------------
;子功能函数:延时10ms
DELAY10MS:
MOV R1,#10
DELAY10MS_LOOP:
MOV R2,#248
DJNZ R2,$
DJNZ R1,DELAY10MS_LOOP
RET
;----------------------------------------------------------------------------------------------
;INT_1中断处理函数:按键判断以及功能1显示处理,串口发送键值,KEY收取键值
INT_1:
PUSH ACC ;保护现场
PUSH PSW
MOV TEMP_R0,R0
MOV TEMP_R1,R1
MOV TEMP_R2,R2 ;保护
CLR EX1 ;关INT1中断
; CLR P2.0 ;按下按键有响声
CLR P1.0 ;按键按下时LED灯亮
LCALL DISPLAY ;进入中断执行一次显示函数,优化显示效果
MOV KEY_TEMP,#00H ;默认键值为#00H
ACALL DELAY10MS ;延时10ms,去抖动
JB P3.3,NOT_KEY ;P3.3若为高电平,无输入,跳出
SETB P3.4 ;P3.4置高电平
JNB P3.3,NOT_KEY1 ;P3.3电平判断
MOV KEY_TEMP,#01H ;P3.3电平被拉高,按键在P3.4上,KEY=1
MOV P3,#0FH
SJMP WAIT
NOT_KEY1: ;按键2判断,判断方式同上
SETB P3.5
JNB P3.3,NOT_KEY2
MOV KEY_TEMP,#02H
MOV P3,#0FH
SJMP WAIT
NOT_KEY2: ;按键3判断,判断方式同上
SETB P3.6
JNB P3.3,NOT_KEY3
MOV KEY_TEMP,#03H
MOV P3,#0FH
SJMP WAIT
NOT_KEY3: ;按键4
MOV KEY_TEMP,#04H
MOV P3,#0FH
WAIT: ;等待按键松开时继续调用显示函数
MOV A,FLAG ;判断FLAG,缓存闹铃还是时间信息
CJNE A,#0BH,INT_1_BUF
SJMP INT_1_DISPLAY ;FLAG=11,不做缓冲处理
INT_1_BUF:
CLR C
SUBB A,#08H
JC INT_1_TIME
LCALL BUF_ALARM ;FLAG>7,缓存闹铃信息
SJMP INT_1_DISPLAY
INT_1_TIME:
LCALL BUF_TIME ;FLAG<7,缓冲时间信息
INT_1_DISPLAY:
LCALL DISPLAY ;执行显示
JNB P3.3,WAIT ;等待按键松开(P3.3恢复高电平)
NOT_KEY:
MOV P3,#0FFH ;P3口复位,发送准备
MOV SBUF,KEY_TEMP ;发送键值KEY_TEMP
JNB TI,$ ;等待发送完成
CLR TI ;TI清0
CLR RI ;RI清0,丢弃第一次结果,准备重新接收
MOV SBUF,KEY_TEMP ;重发键值KEY_TEMP
JNB TI,$ ;等待发送完成
CLR TI ;TI清0
JNB RI,NO_RECEIVE
MOV KEY,SBUF ;接收完成,接受缓冲区内容送KEY
CLR RI ;RI清0
MOV A,KEY_TEMP
CJNE A,KEY,NO_RECEIVE ;KEY与发送KEY_TEMP对比,不等的话舍弃
SJMP NEXT
NO_RECEIVE:
MOV KEY,#00H ;接收不完成,KEY=0
NEXT:
MOV P3,#0FH ;P3口恢复键盘监控状态
MOV FLAG_KEEP,#00H ;有按键按下,关闹铃
MOV R7,#00H ;有按键按下,关整点报时
SETB P2.0 ;关蜂鸣器
SETB P1.0 ;按键松开后关LED灯
LCALL DISPLAY ;中断返回前调用一次显示函数,优化显示效果
MOV R0,TEMP_R0
MOV R1,TEMP_R1
MOV R2,TEMP_R2
POP PSW
POP ACC ;恢复现场
SETB EX1 ;开INT1中断
RETI
;----------------------------------------------------------------------------------------------
;计数器T0中断处理函数:50ms调用一次,修正量取5(响应中断)+3(2个PUSH命令、1个MOV命令)=8机器周期,8us
INT_T0:
PUSH ACC
PUSH PSW
MOV TL0,#0B8H
MOV TH0,#3CH ;重置计数值
INC COUNT ;记录调用次数
INC COUNT_50MS
MOV A,COUNT_50MS ;取调用次数COUNT_50MS,COUNT_50MS可由其他函数复位,实现相对定时
CJNE A,#10,INT_T0_NEXT ;COUNT_50MS=10,满10次,0.5秒到,否则跳过
MOV A,FLAG_CLOSE ;满0.5秒FLAG_CLOSE取反操作
CPL A
INC A
MOV FLAG_CLOSE,A
MOV COUNT_50MS,#00H
INT_T0_NEXT:
MOV A,COUNT ;取调用次数COUNT,COUNT为计数器内部使用
CJNE A,#20,INT_T0_EXIT ;COUNT=20,1秒到,COUNT清0,否则返回
MOV COUNT,#00H
INC SECOND ;秒+1
INC COUNT_1S ;1S统计标志+1,由其他函数复位,实现相对定时
MOV A,FLAG_1S ;1S取反标志取反
CPL A
INC A
MOV FLAG_1S,A
PUSH FLAG_ADD ;保护FLAG_ADD
MOV FLAG_ADD,#00H ;FLAG_ADD=00H
LCALL FORMAT_TIME ;时钟模式下调用数据处理
POP FLAG_ADD
INT_T0_EXIT:
POP PSW
POP ACC ;恢复现场
RETI
END
- 上一篇: ajax4jsf中文教程
- 下一篇: STC-MCU-SPI演示