登录 注册
当前位置:主页 > 资源下载 > 50 > 电子钟程序设计的单片机实现

电子钟程序设计的单片机实现

  • 更新:2024-11-03 09:18:26
  • 大小:37KB
  • 推荐:★★★★★
  • 来源:网友上传分享
  • 类别:单片机 - 硬件开发
  • 格式:TXT

资源介绍

关于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