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

📄 电子闹钟.asm

📁 具有电子时钟、秒表、闹钟(可设定10组)功能
💻 ASM
字号:
;**********************电子闹钟*******************
;本电子闹钟最多可设定10个闹铃时间,还具有秒表功能.
;编程环境:WAVE6000  
;MCU: AT89S51
;*************************************************
  STATEH    EQU    2AH ;状态码高8位
  STATEL    EQU    2BH ;状态码低8位
  B_ON      BIT   STATEH.5;蜂鸣器软开关
  FLAG      EQU    2CH ;辅助标志字节
  DISP_P    EQU    30H ;显示扫描指针
  KEYC      EQU    2DH ;键码
  KEYT      EQU    33H ;键龄
  KEYOK      BIT    FLAG.0 ;按键已响应标志位
  DHEAD     EQU    3AH ;显存首地址(3AH-3FH为显存)
  HOUR      EQU    40H ;时
  MINUTE    EQU    41H ;分
  SEC       EQU    42H ;秒
  SECD      EQU    43H ;0.01秒
  SECD2     EQU    44H ;2ms
  MMIN      EQU    45H ;秒表分
  MSEC      EQU    46H ;秒表秒
  MSECD     EQU    47H ;秒表0.01秒
  MSTA      BIT   STATEH.3;秒表启动标志位
  ALARM     EQU    48H ;闹铃时间表首地址(48H-5BH为闹铃时间表)
  M_1S      BIT    FLAG.1 ;秒时钟
  BUZZER    BIT    P1.5   ;蜂鸣器控制端
;注:
;STATEH的高2位=00,01,10时分别表示当前显示的数据为时钟,秒表,闹钟.
;STATEH.5为蜂鸣器响标志位.STATEH.4为修改标志位.STATEH.3为秒表
;启动标志位.在修改状态时,STATEH的低3位=0,1,2分别表示修改时,分,秒.
;在显示闹钟表状态时STATEL表示当前显示的闹铃时间在闹钟表中的序号.
;在闹铃时间表中,每一个时间用2个字节表示,地址小的字节的最高为表示
;该时间是否已打开,低7为表示时,还有一个字节表示分.
;--------------------------------------------------
        ORG    0000H
        AJMP   START
        ORG    000BH
        AJMP   TIME
        ORG    0030H
;--------------------初始化------------------
START:  MOV    SP,#60H
        MOV    R0,#30H
        MOV    @R0,#0
        INC    R0
        CJNE   R0,#61H,$-3
        MOV    TMOD,#01H
        MOV    TL0,#30H        ;2ms中断(12M晶振)
        MOV    TH0,#0E8H
        MOV    HOUR,#12H
        MOV    MINUTE,#00H
        MOV    SEC,#00H
        MOV    STATEH,#0
        MOV    STATEL,#0
        MOV    DISP_P,#0
        SETB   TR0
        SETB   ET0
        SETB   EA
        ACALL  DISP
;-----------------------------------------
MAIN:   SJMP MAIN   ;等待中断
;--------------T0 中断服务子程序--------------
TIME:   ORL     TL0,#30H        ;用ORL可提高计时精度
        MOV     TH0,#0F8H
        INC     SECD2
        NOP
        MOV     A,SECD2
        CJNE    A,#5,TIME1
        MOV     SECD2,#0      ;10ms到
;--------------------------------------------
;运行时钟
        CLR     F0             ;时间改变标志
        CLR     F1             ;秒为0标志位
        MOV     A,SECD          ;加0.01秒
        ADD     A,#1
        DA      A
        MOV     SECD,A
        CJNE    A,#50H,$+3
        MOV     M_1S,C        ;产生秒方波
        JNZ     TIME0
        MOV     A,SEC             ;秒加1
        ADD     A,#1
        DA      A
        MOV     SEC,A
        SETB    F0              ;标志时间改变
        CJNE    A,#60H,TIME0
        MOV     SEC,#0
        SETB    F1              ;标志秒为0
        MOV     A,MINUTE        ;分加1
        ADD     A,#1
        DA      A
        MOV     MINUTE,A
        CJNE    A,#60H,TIME0
        MOV     MINUTE,#0
        MOV     A,HOUR            ;时加1
        ADD     A,#1
        DA      A
        MOV     HOUR,A
        CJNE    A,#24H,TIME0
        MOV     HOUR,#0
TIME0:  JNB     F0,TMB          ;时间未改变,转
        JNB     F1,$+5
        ACALL   BJIAO           ;秒为0,比较
        MOV     A,STATEH
        ANL     A,#0C0H
        JNZ     TMB             ;不是显示时间,转
        ACALL   DISP            ;刷新显示
;运行秒表
TMB:    JNB     MSTA,FMQI      ;秒表未开,转
        CLR     F0
        MOV     A,MSECD
        ADD     A,#1            ;加0.01秒
        DA      A
        SETB    F0
        MOV     MSECD,A
        JNZ     TIME1
        MOV     A,MSEC            ;加1秒
        ADD     A,#1
        DA      A
        MOV     MSEC,A
        CJNE    A,#60H,TIME1
        MOV     MSEC,#0
        MOV     A,MMIN
        ADD     A,#1
        DA      A
        MOV     MMIN,A
TIME1:  JNB     F0,FMQI
        MOV     A,STATEH
        ANL     A,#0C0H
        CJNE    A,#40H,FMQI
        ACALL   DISP
;----------------------------------------
;蜂鸣器控制
FMQI:   MOV     C,B_ON
        ANL     C,M_1S
        CPL     C
        MOV     BUZZER,C
;--------------------
        ACALL   SCAN
        RETI
;--------------------动态扫描---------------------
SCAN:   MOV     P2,#0FFH      ;关显示器
        INC     DISP_P        ;指向下一位
        MOV     A,DISP_P
        CJNE    A,#6,SCAN0
        MOV     DISP_P,#0FFH
        AJMP    SCNKEY        ;每扫完一遍显示器就扫描一次按键
SCAN0:  MOV     A,DISP_P
        ADD     A,#DHEAD         ;加上显存首地址,得到实际地址
        MOV     R0,A
        MOV     A,@R0
        ADD     A,#2
        MOVC    A,@A+PC       ;查段码
        SJMP    SCAN1
   DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H   ;0-9
   DB 0BFH,0FFH                                     ;-,"灭"
SCAN1:  MOV     P0,A
        MOV     A,DISP_P
        ADD     A,#2
        MOVC    A,@A+PC        ;查位码
        SJMP    SCAN2
   DB  0DFH,0EFH,0F7H,0FBH,0FDH,0FEH ;位码
;闪亮控制
SCAN2:  JNB     STATEH.4,SCAN3  ;非修改状态,不用控制
        JB      M_1S,SCAN3      ;全亮,转
        JNB     KEYOK,SCAN3
        MOV     R7,A            ;保存位码
        MOV     A,STATEH
        ANL     A,#07H
        ADD     A,#3
        MOVC    A,@A+PC
        ORL     A,R7
        SJMP    SCAN3
    DB  30H,0CH,03H
;-----------
SCAN3:  MOV     P2,A
        RET
;-----------------扫描键盘-------------------
SCNKEY: MOV     A,P1
        CPL     A
        ANL     A,#5FH
        JZ      NOKEY             ;无按键,转
        MOV     KEYC,A
        DEC     KEYT              ;键龄减1
        MOV     A,KEYT
        JNZ     SKEND
        MOV     KEYT,#70          ;连击延时的时间
        JBC     KEYOK,SKEY1        ;未响应则标志已响应,并转移
        MOV     KEYT,#5          ;连击的速度
        JB      KEYC.0,SKEY1
        JB      KEYC.1,SKEY1
        SJMP    SKEND             ;不允许连击,转
SKEY1:  SJMP    KEYJX             ;解释按键
NOKEY:  SETB    KEYOK              ;清响应标志位
        MOV     KEYT,#2		  ;消抖时间
        MOV     KEYC,#00H
SKEND:  RET
;----------------------解释按键------------------
KEYJX:  JNB     B_ON,KEYJX1
        CLR     B_ON              ;若蜂鸣器开
        RET
KEYJX1: MOV     A,STATEH	  ;判断当前状态
        RL      A
        RL      A
        ANL     A,#03H
        CJNE    A,#1,$+5
        AJMP    MBIAO             ;显示秒表状态
        CJNE    A,#2,SZHONG
        AJMP    NZHONG            ;显示闹钟表状态
;---------------显示时钟状态-----------------
SZHONG: JNB     STATEH.4,SZ
        AJMP    SZ_XIU            ;修改时钟状态
;-------正常运行-----
SZ:     JNB     KEYC.2,$+5
        AJMP    SZK2
        JNB     KEYC.6,$+5
        AJMP    SZK5
        RET
;"修改/确定"键
SZK2:   SETB    STATEH.4          ;进入修改状态
        ANL     STATEH,#0F8H      ;修改"时"
        RET
;"切换"键
SZK5:   ACALL   QHUAN
        ACALL   DISP              ;刷新显示
        RET
;----切换显示状态子程序-----
QHUAN:  MOV     A,STATEH
        ANL     A,#0C0H
        ADD     A,#40H
        CJNE    A,#0C0H,$+4
        CLR     A
        ANL     STATEH,#3FH
        ORL     A,STATEH
        MOV     STATEH,A
        RET
;--------修改时钟-------
SZ_XIU: JNB     KEYC.0,$+5
        AJMP    SXK0
        JNB     KEYC.1,$+5
        AJMP    SXK1
        JNB     KEYC.2,$+5
        AJMP    SXK2           ;修改/确定
        RET
;"加"键
SXK0:   CLR     C              ;设立加1标志
        ACALL   S_ADD          ;修改
        ACALL   DISP
        RET
;"减"键
SXK1:   SETB    C             ;设立减1标志
        ACALL   S_ADD         ;修改
        ACALL   DISP
        RET
;"修改/确定"键
SXK2:   MOV     B,#2         ;修改完"秒"后,退出修改状态
        ACALL   W_G
        RET
;-----------改变修改位置子程序-----------
;修改完第(B)位后,退出修改状态.
W_G:    MOV     A,STATEH
        ANL     A,#07H
        CJNE    A,B,W_G1
        CLR     STATEH.4        ;退出修改状态
        RET
W_G1:   INC     STATEH          ;修改下一位
        RET
;---------------显示秒表状态----------------
MBIAO:  JB      MSTA,MBRUN    ;运行状态
        AJMP    MBSTOR        ;停止状态
;------运行状态------
MBRUN:  JNB     KEYC.3,$+5
        AJMP    MBRUN1
        JNB     KEYC.6,$+5
        ACALL   QHUAN           ;切换显示状态
        ACALL   DISP
        RET
;"开/关"键
MBRUN1: CLR     MSTA            ;停秒表
        RET
;------停止状态------
MBSTOR: JNB     KEYC.3,$+5
        AJMP    MSTK3
        JNB     KEYC.4,$+5
        AJMP    MSTK4
        JNB     KEYC.6,$+5
        AJMP    MSTK5
        RET
;"开/关"键
MSTK3:  SETB    MSTA            ;开秒表
        RET
;"清0"键
MSTK4:  MOV     MMIN,#0
        MOV     MSEC,#0
        MOV     MSECD,#0
        ACALL   DISP
        RET
;"切换"键
MSTK5:  ACALL   QHUAN
        ACALL   DISP
        RET
;-----------------显示闹钟表状态--------------
NZHONG: JNB     STATEH.4,NZ
        AJMP    NZ_XIU
;---------查看闹钟表状态--------
NZ:     JNB     KEYC.0,$+5
        AJMP    NZK0
        JNB     KEYC.1,$+5
        AJMP    NZK1
        JNB     KEYC.2,$+5
        AJMP    NZK2
        JNB     KEYC.3,$+5
        AJMP    NZK3
        JNB     KEYC.6,$+5
        AJMP    NZK5
        RET
;"加"键
NZK0:   MOV     A,STATEL      ;查看上一个时间
        ADD     A,#1
        DA      A
        ANL     A,#0FH     ;只有10个时间,从0-9循环翻看
        MOV     STATEL,A
        ACALL   DISP
        RET
;"减"键
NZK1:   MOV     A,STATEL      ;查看下一个时间
        ADD     A,#99H
        DA      A
        ANL     A,#0FH
        MOV     STATEL,A
        ACALL   DISP
        RET
;"修改/确定"键
NZK2:   SETB    STATEH.4          ;进入修改状态
        ANL     STATEH,#0F8H      ;修改"时"
        RET
;"开/关"键
NZK3:   MOV     A,STATEL
        RL      A
        ADD     A,#ALARM
        MOV     R0,A
        MOV     A,@R0
        CPL     ACC.7       ;开/关当前显示的那个闹铃时间
        MOV     @R0,A
        ACALL   DISP
        RET
;"切换"键
NZK5:   ACALL   QHUAN
        ACALL   DISP
        RET
;-------修改闹钟表状态------
NZ_XIU: JNB     KEYC.0,$+5
        ACALL   NXK0
        JNB     KEYC.1,$+5
        ACALL   NXK1
        JNB     KEYC.2,$+5
        ACALL   NXK2
        RET
;"加"键
NXK0:   CLR     C          ;设立加1标志
        ACALL   S_ADD      ;修改
        ACALL   DISP
        RET
;"减"键
NXK1:   SETB    C          ;设立减1标志
        ACALL   S_ADD      ;修改
        ACALL   DISP
        RET
;"修改/确定"键
NXK2:   MOV     B,#1       ;修改完"分"后,退出修改状态
        ACALL   W_G        ;改变修改位置
        RET
;_______________________按键解释完毕_______________________
;----------------显示模块---------------
DISP:   MOV     A,STATEH
        RL      A
        RL      A
        ANL     A,#03H
        CJNE    A,#0,$+5
        AJMP    DIS0
        CJNE    A,#1,$+5
        AJMP    DIS1
        CJNE    A,#2,$+5
        AJMP    DIS2
        RET
;显示时钟状态
DIS0:   MOV     R0,#HOUR
        MOV     R2,#3
        SJMP    DIS
;显示秒表状态
DIS1:   MOV     R0,#MMIN
        MOV     R2,#3
        SJMP    DIS
;显示闹钟表状态
DIS2:   MOV     A,STATEL
        RL      A
        ADD     A,#ALARM
        MOV     R0,A
        MOV     R1,#DHEAD+4
        MOV     @R1,#0AH           ;插入闹钟开标志
        MOV     A,@R0
        JB      ACC.7,DIS2_1
        MOV     @R1,#0BH           ;插入闹钟关标志
DIS2_1: INC     R1
        MOV     A,STATEL
        MOV     @R1,A              ;插入序号
        MOV     R2,#2
;-----------------
DIS:    MOV     R1,#DHEAD
DISL:   MOV     A,@R0
        CLR     ACC.7
        SWAP    A
        ANL     A,#0FH
        MOV     @R1,A
        INC     R1
        MOV     A,@R0
        ANL     A,#0FH
        MOV     @R1,A
        INC     R0
        INC     R1
        DJNZ    R2,DISL
        RET
;-----------------比较模块---------------
BJIAO:  MOV     A,HOUR
        SETB    ACC.7
        MOV     R6,A
        MOV     R7,MINUTE
        ACALL   FIND               ;查找
        MOV     B_ON,C             ;若找到则开闹铃
        RET
;查找
FIND:   MOV     R2,#10
        MOV     R0,#ALARM
FIND0:  MOV     A,@R0
        INC     R0
        XRL     A,R6
        JNZ     FIND1
        MOV     A,@R0
        XRL     A,R7
        JNZ     FIND1
        SETB    C                  ;设立找到标志
        RET
FIND1:  INC     R0
        DJNZ    R2,FIND0
        CLR     C                  ;标志未找到
        RET
;---------------修改闪亮位子程序---------------
;入口条件:加1 C=0,减1 C=1.
S_ADD:  MOV     R7,#01H
        JNC     S_AD
        MOV     R7,#99H      ;-1的BCD码补码
;求闪亮位地址
S_AD:   MOV     A,STATEH
        RL      A
        RL      A
        ANL     A,#3
        JNZ     S_ADD0
        MOV     R0,#HOUR      ;修改时钟
        SJMP    S_ADD1
S_ADD0: CJNE    A,#2,S_ADD5
        MOV     A,STATEL      ;修改闹钟表
        RL      A
        ADD     A,#ALARM
        MOV     R0,A
S_ADD1: MOV     A,STATEH
        ANL     A,#07H
        ADD     A,R0
        MOV     R0,A
;求进制值
S_ADD2: MOV     A,STATEH
        ANL     A,#07H
        ADD     A,#2
        MOVC    A,@A+PC
        SJMP    S_ADD3
    DB  24H,60H,60H
S_ADD3: MOV     B,A      ;保存进制值
;修改闪亮位
        MOV     A,@R0
        CLR     ACC.7
        ADD     A,R7
        DA      A
        MOV     @R0,A
        CJNE    A,B,S_ADD4
        MOV     @R0,#0    ;上溢,清0?
        RET
S_ADD4: CJNE    A,#99H,S_ADD5
        ADD     A,B       ;下溢,付与最大值
        DA      A
        MOV     @R0,A
S_ADD5: RET
;**************************************************
                   END

⌨️ 快捷键说明

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