单片机学习小组
直播中

而无返还

8年用户 1239经验值
擅长:光电显示
私信 关注

如何利用C51汇编去实现一种时间控制器呢

如何利用C51汇编去实现一种时间控制器呢?如何对时间控制器进行proteus仿真呢?

回帖(1)

陈连香

2022-1-26 10:48:50
电路图:

汇编代码:

                ORG 0000H
                LJMP MAIN       
                ORG 000BH                       
                LJMP TIME       
                ORG 0100H
                                       
;宏定义
        ;键位
                K0        BIT 20H.0
                K1        BIT 20H.1
                K2        BIT 20H.2
                K3  BIT 20H.3
                K4        BIT 20H.4
                ;暂存区
                ST  DATA 68H
                MT         DATA 69H
                HT        DATA 6AH
                DT         DATA 6BH
                MOUT DATA 6CH
                YLT        DATA 6DH
                YHT DATA 6EH       
                SPT DATA 21H        ;移位指针
        ;时钟时间寄存区                       
                S         DATA 60H
                M         DATA 61H
                H         DATA 62H
                D         DATA 63H
                MOU DATA 64H
                YL         DATA 65H
                YH  DATA 66H
                FLAG DATA 67H
        ;闹钟时间寄存区                       
                SC                DATA 50H
                MC                DATA 51H
                HC                DATA 52H
                DC                DATA 53H
                MOUC        DATA 54H
                YLC                DATA 55H
                YHC                DATA 56H
                       
                ;时间显示缓冲区
                //存放数码管显示16位的数据
                SDL                DATA 70H
                SDH         DATA 71H
                POINT1         DATA 72H
                MDL         DATA 73H
                MDH         DATA 74H
                POINT2         DATA 75H
                HDL         DATA 76H
                HDH         DATA 77H
                DDL         DATA 78H
                DDH         DATA 79H
                MOUDL         DATA 7AH
                MOUDH         DATA 7BH
                YD0           DATA 7CH
                YD1                DATA 7DH
                YD2                DATA 7EH
                YD3                DATA 7FH
                       
//主程序
MAIN:       
                MOV TMOD,#01H                ;T0工作方式1
                MOV TL0,#0B0H
                MOV TH0,#3CH                ;50ms
                MOV R7,#20                        ;20*50ms = 1s
                MOV S,#50
                MOV M,#59
                MOV H,#11
                MOV D,#11
                MOV MOU,#12
                MOV YL,#20
                MOV YH,#20
                MOV POINT1,#10                ;在TABLE中第10个对应“-”
                MOV POINT2,#10               
                MOV SPT,#1                        ;移位指针初始最低位为1
                SETB K0                               
                CLR         K1                                ;K1置1 (非暂停状态)
                CLR  K2                                ;K2置1  默认修改模式
                CLR  P3.5           ;默认蜂鸣器非工作状态
                CLR  P3.6           ;默认LED非工作状态
                SETB ET0                       
                SETB EA
                SETB TR0                        ;开启定时器
               
;不断循环
GO_ON:
                LCALL CHECK_KEY
                LCALL DISPLAY
                LCALL CHECK_CLOCK         ;闹铃
                LCALL LIGHT_ON       ;开灯
            LCALL LIGHT_OFF      ;关灯
                SJMP GO_ON           ;跳转循环
               
;定时子程序
TIME:       
                MOV TL0,#0B0H
                MOV TH0,#3CH               
                DJNZ R7,TIME_END       
                MOV R7,#20          ;循环20次 定时1s
                LCALL TIME_INC                ;跳转到计时
                LCALL SAVE0                        ;跳转到数据转移
                LCALL SEND_TO_DIS        ;储存时间寄存器中的BCD
TIME_END:
                RETI                               










;数码管显示子程序
DISPLAY:
                MOV R0,#SDL                        ;数据缓存区指针
                MOV DPTR,#TABLE                ;七段共阴数码管0-9显示
                MOV R1,#0                ;R1存放表示第几位的数字
               
//P0口实现片选               
NEXT:        MOV P0,R1                        ;显示位连接P0
                MOV A,R1
                CLR C                               
                SUBB A,#8           //实现前8个向HMS跳转,后8个向YMD跳转               
                JC        HMS                               


//P2口实现年月日
DIAN1:        //先判断是否位第10位,第10位需要有小数点
                CJNE R1,#10,DIAN2    ;跳转判断DIAN2
                MOV DPTR,#TABLE1
                MOV A,@R0                        ;取显示数字
                MOVC A,@A+DPTR               
                MOV P2,A                        ;显示年月日
                LCALL DELAY                        ;调用延时
                MOV DPTR,#TABLE
                SJMP GO


DIAN2:        //再判断是否位第12位,第12位也需要有小数点
                CJNE R1,#12,YMD     ;若不是第10,12位,跳转YMD
                MOV DPTR,#TABLE1
                MOV A,@R0                        ;取显示数字
                MOVC A,@A+DPTR               
                MOV P2,A                        ;显示年月日
                LCALL DELAY                        ;调用延时
                MOV DPTR,#TABLE
                SJMP GO
               
YMD:    //正常输出没小数点的数字
                MOV A,@R0                        ;取显示数字
                MOVC A,@A+DPTR               
                MOV P2,A                        ;显示年月日
                LCALL DELAY                        ;调用延时
                SJMP GO


//P1口实现时分秒
HMS:        MOV A,@R0                        ;取显示数字
                MOVC A,@A+DPTR               
                MOV P1,A                        ;显示时分秒
                LCALL DELAY                        ;调用延时
                SJMP GO
               
GO:                INC R1                                ;显示位左移
                INC R0                       
                CJNE R1,#16,NEXT
                RET
//共阳极,0亮1灭,共阴极,1亮0灭
TABLE:        DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H        ;七段共阴数码管0-9
TABLE1:        DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0EFH,40H        ;带小数点的七段共阴数码管0-9










;计时程序
TIME_INC:       
SEC:        INC S                                ;+1S
                MOV R6,S
                CJNE R6,#60,INC_END ;满60秒进位
                MOV R6,#0
                MOV S,R6
                SJMP MIN
MIN:        INC M                                ;+1M
                MOV R6,M
                CJNE R6,#60,INC_END ;满60分钟进位
                MOV R6,#0
                MOV M,R6
                SJMP HOUR
HOUR:        INC H                                ;+1H
                MOV R6,H
                CJNE R6,#24,INC_END ;满24小时进位
                MOV R6,#0
                MOV H,R6
DAY:        LCALL CHECK_Y       ;检查平闰年
                MOV R6,FLAG
                CJNE R6,#1,PING
                MOV DPTR,#R_YEAR    ;调用闰年月份表
                SJMP YGO
PING:        MOV DPTR,#P_YEAR        ;调用平年月份表
YGO:         MOV A,MOU
                MOVC A,@A+DPTR               
                INC A
                INC D                                ;+1D                               
                CJNE A,D,INC_END
                MOV R6,#1
                MOV D,R6
                SJMP MOUN
MOUN:        INC MOU                                ;+1M
                MOV R6,MOU
                CJNE R6,#13,INC_END ;第13个月进位
                MOV R6,#0
                MOV MOU,R6
                SJMP YEAR
YEAR:       
                INC YL               ;+1Y低位
                MOV R6,YL
                CJNE R6,#100,INC_END
                MOV R6,#0
                MOV YL,R6
                INC YH               ;+1Y高位
                MOV R6,YH
                CJNE R6,#100,INC_END
                MOV R6,#0
                MOV YH,R6
INC_END:
    RET  


;检查平闰年子程序
CHECK_Y:
                MOV A,YL
                MOV B,#4
                DIV AB
                MOV A,B
                JNZ SET_FLAG
                MOV FLAG,#1
                SJMP CHECK_END
SET_FLAG:
                MOV FLAG,#0
CHECK_END:       
                RET


P_YEAR:        DB 0,31,28,31,30,31,30,31,31,30,31,30,31                ;平年月份表
R_YEAR:        DB 0,31,29,31,30,31,30,31,31,30,31,30,31                ;闰年月份表
       
;将暂存区中的数据转为BCD码存入显示缓冲区
SEND_TO_DIS:                                               
                MOV A,ST
                LCALL H2B
                MOV SDL,R4
                MOV SDH,R5                                        ;存秒
               
                MOV A,MT
                LCALL H2B
                MOV MDL,R4
                MOV MDH,R5                                        ;存分
               
                MOV A,HT
                LCALL H2B
                MOV HDL,R4
                MOV HDH,R5                                        ;存时
               
                MOV A,DT
                LCALL H2B
                MOV DDL,R4
                MOV DDH,R5                                        ;存天
               
                MOV A,MOUT
                LCALL H2B
                MOV MOUDL,R4
                MOV MOUDH,R5                                ;存月
               
                MOV A,YLT
                LCALL H2B
                MOV YD0,R4
                MOV YD1,R5                                        ;存年(低位)
               
                MOV A,YHT
                LCALL H2B
                MOV YD2,R4
                MOV YD3,R5                                        ;存年(高位)
                RET
               
;1ms延时子程序
DELAY:       
                MOV R3,#4
DEL:        MOV R2,#250
                DJNZ R2,$
                DJNZ R3,DEL
                RET


;
H2B:        MOV B,#10
                DIV AB
                MOV R5,A                        ;个位存到R5
                MOV R4,B                        ;十位存到R4
                RET
               
;查询按键子程序
CHECK_KEY:
                MOV A,P3                        ;读取P3按键状态
                CPL A;
                JZ CHECK_EXIT
                ACALL KEY_DELAY
                MOV A,P3                        ;读取P3按键状态 确认是否有键按下
                CPL A
                JZ CHECK_EXIT
                JB ACC.0,ACT0                ;暂停/恢复键
                JB ACC.1,ACT1                ;闹钟键
                JB ACC.2,ACT2                ;换位键
                JB ACC.3,ACT3                ;+
                JB ACC.4,ACT4                ;-
CHECK_EXIT:       
                RET
               
;按键子程序               
ACT:
ACT0:        MOV A,P3                        ;检测按键是否释放
                JNB ACC.0,ACT0                ;键未释放,则继续等待
                CPL K0                                ;K0取反,在暂停/继续中转换
                JB        K0,START
                CLR TR0                                ;TR0=0,停止计时
                LJMP EXIT
START:        SETB TR0                        ;TRO=1,开始计时
                CLR  K1                                ;默认回修改功能
                RET
               
;定时/修改按钮
ACT1:        MOV A,P3                        ;检测按键是否释放
                JNB ACC.1,ACT1                ;键未释放,则继续等待
                CPL K2                                ;取反闹铃使能开关
                JB        K0,EXIT                        ;若K0未在暂停状态,则返回
                CPL K1                                ;K1取反,0为修改,1为闹钟定时
                RET
               
;移位按钮
ACT2:       
                MOV A,P3                        ;检测按键是否释放
                JNB ACC.2,ACT2                ;键未释放,则继续等待
                JB        K0,EXIT                        ;若K0未在暂停状态,则返回
                MOV A,SPT                       
                RL         A                                ;SPT移动(RL循环左移,RLC带进位左移,RL不带进位)
                MOV SPT,A       
                JNB ACC.7,EXIT                ;最多移到01000000
                MOV SPT,#1                       
                RET
               
;加
ACT3:        MOV A,P3                        ;检测按键是否释放
                JNB ACC.3,ACT3                ;键未释放,则继续等待
                JB        K0,EXIT                        ;若K0未在暂停状态,则返回
                JB         K1,CL_INC
                SJMP UP_INC
                RET
               
CL_INC:                             ;闹钟
                LCALL KEY_INC
                LCALL SEND_TO_DIS
                LCALL SEND1
                RET       
               
UP_INC:        LCALL SAVE0
                LCALL KEY_INC
                LCALL SEND_TO_DIS
                LCALL SEND0
                RET
               
;减       
ACT4:        MOV A,P3                        ;检测按键是否释放
                JNB ACC.4,ACT4                ;键未释放,则继续等待
                JB        K0,EXIT                        ;若K0未在暂停状态,则返回
                JB         K1,CL_DEC
                SJMP UP_DEC
                RET
               
CL_DEC:                            ;闹钟
                LCALL KEY_DEC
                LCALL SEND_TO_DIS
                LCALL SEND1
                RET       
               
UP_DEC:        LCALL SAVE0
                LCALL KEY_DEC
                LCALL SEND_TO_DIS
                LCALL SEND0
                RET               
       
EXIT:        RET


KEY_DELAY:
                MOV R3,#24
KEY_DEL:MOV R2,#0FAH
                DJNZ R2,$
                DJNZ R3,KEY_DEL
                RET




;数据转移子程序
SAVE0:        MOV ST,S
                MOV        MT,M       
                MOV        HT,H
                MOV        DT,D
                MOV        MOUT,MOU
                MOV        YLT,YL
                MOV        YHT,YH
                RET               
;将数据传给计时数据寄存器
SEND0:  MOV S,ST
                MOV        M,MT       
                MOV        H,HT
                MOV        D,DT
                MOV        MOU,MOUT
                MOV        YL,YLT
                MOV        YH,YHT
                RET
;将数据传给闹钟数据寄存器
SEND1:        MOV SC,ST
                MOV        MC,MT       
                MOV        HC,HT
                MOV        DC,DT
                MOV        MOUC,MOUT
                MOV        YLC,YLT
                MOV        YHC,YHT
                RET
               
//按下按键年月日时分秒的加减处理               
;+按键子程序
KEY_INC:
                JB         SPT.0,S_INC     ;未按换位键 默认更改秒
                JB        SPT.1,M_INC     ;按一次更改分
                JB  SPT.2,H_INC     ;按两次更改小时
                JB        SPT.3,D_INC     ;按三次更改日
                JB        SPT.4,MOU_INC   ;按四次更改月
                JB        SPT.5,YL_INC    ;按五次更改年的个十位
                JB        SPT.6,YH_INC    ;按六次更改年的百千位
               
S_INC:        INC ST                                ;+1S
                MOV R6,ST
                CJNE R6,#60,EXIT_INC
                MOV R6,#0
                MOV ST,R6
                RET
               
M_INC:        INC MT                                ;+1M
                MOV R6,MT
                CJNE R6,#60,EXIT_INC
                MOV R6,#0
                MOV MT,R6
                RET
               
H_INC:        INC HT                                ;+1H
                MOV R6,HT
                CJNE R6,#24,EXIT_INC
                MOV R6,#0
                MOV HT,R6
                RET
               
D_INC:        LCALL CHECK_Y
                MOV R6,FLAG
                CJNE R6,#1,PING1
                MOV DPTR,#R_YEAR
                SJMP YGO1
PING1:        MOV DPTR,#P_YEAR        ;暂存本月天数上限
YGO1:         MOV A,MOUT
                MOVC A,@A+DPTR               
                INC A
                INC DT                                ;+1D                               
                CJNE A,DT,EXIT_INC
                MOV R6,#1
                MOV DT,R6
                RET
               
MOU_INC:       
                INC MOUT                        ;+1M
                MOV R6,MOUT
                CJNE R6,#13,EXIT_INC
                MOV R6,#1
                MOV MOUT,R6
                RET
               
YL_INC:        INC YLT              ;+1Y低位
                MOV R6,YLT
                CJNE R6,#100,EXIT_INC
                MOV R6,#0
                MOV YLT,R6
                RET
               
YH_INC:        INC YHT               ;+1Y高位
                MOV R6,YHT
                CJNE R6,#100,EXIT_INC
                MOV R6,#0
                MOV YHT,R6
                RET
               
EXIT_INC:
                RET
               
;-按键子程序
KEY_DEC:
                //根据移位指针SPT哪一位是1
                JB         SPT.0,S_DEC       ;未按换位键 默认更改秒
                JB        SPT.1,M_DEC       ;按一次更改分
                JB  SPT.2,H_DEC       ;按两次更改小时
                JB        SPT.3,D_DEC       ;按三次更改日
                JB        SPT.4,MOU_DEC     ;按四次更改月
                JB        SPT.5,YL_DEC      ;按五次更改年的个十位
                JB        SPT.6,YH_DEC      ;按六次更改年的百千位


S_DEC:
                DEC ST                ;-1s
                MOV R6,ST
                CJNE R6,#0FFH,EXIT_DEC
                MOV R6,#59
                MOV ST,R6
                RET
M_DEC:
                DEC MT                ;-1m
                MOV R6,MT
                CJNE R6,#0FFH,EXIT_DEC
                MOV R6,#59
                MOV MT,R6
                RET
H_DEC:               
                DEC HT                ;-1h
                MOV R6,HT
                CJNE R6,#0FFH,EXIT_DEC
                MOV R6,#23
                MOV HT,R6
                RET
               
D_DEC:        LCALL CHECK_Y
                MOV R6,FLAG
                CJNE R6,#1,PING2
                MOV DPTR,#R_YEAR
                SJMP YGO2
PING2:        MOV DPTR,#P_YEAR       
YGO2:         MOV A,MOUT
                MOVC A,@A+DPTR                ;暂存本月天数上限
                DEC         DT                                ;-1D
                MOV R6,DT
                CJNE R6,#0,EXIT_INC
                MOV R6,A
                MOV DT,R6
                RET
               
MOU_DEC:
                DEC MOUT             ;-1MO
                MOV R6,MOUT
                CJNE R6,#0,EXIT_DEC
                MOV R6,#12
                MOV MOUT,R6
                RET
YL_DEC:                            
                DEC YLT              ;-1Y(低位)
                MOV R6,YLT
                CJNE R6,#0FFH,EXIT_DEC
                MOV R6,#99
                MOV YLT,R6
                RET
YH_DEC:       
                DEC YHT               ;-1Y(低位)
                MOV R6,YHT
                CJNE R6,#0FFH,EXIT_DEC
                MOV R6,#99
                MOV YHT,R6
                RET


EXIT_DEC:
                RET
               
;闹钟响铃子程序
CHECK_CLOCK:                   ;判断是否响铃
                MOV R0,#M                       
                MOV R1,#MC
                MOV R2,#5
CHECK_NEXT:                        ;
                MOV        A,@R0
                SUBB A,@R1                           ;判断当前时刻是否是闹铃时刻
                CLR C
                JNZ        CLOC_EXIT
                INC R0
                INC R1
                DJNZ R2,CHECK_NEXT
                LCALL TIMEOUT                        ;分 时 日 月 年均满足则调用响铃程序
                RET
               
CLOC_EXIT:                  
                CLR P3.5
                RET
;响铃程序               
TIMEOUT:                                       
                JNB K2,BUZ_END          ;按下按键停止响铃
BUZ:        SETB P3.5           
                LCALL BUZ_DELAY
               
BUZ_DELAY:                      ;延时
                MOV R3,#250
BUZ_T:        MOV R2,#40
                DJNZ R2,$
                DJNZ R3,BUZ_T
                RET
BUZ_END:       
                CLR P3.5
                RET
               
;亮灯子程序
LIGHT_ON:
    MOV A,#12
        CJNE A,H,TTE3
        MOV A,#00
        CJNE A,M,TTE3
        MOV A,#00
        CJNE A,S,TTE3
        SETB P3.6                   ;从12:00:00开始亮
TTE3:       
   RET
LIGHT_OFF:
    MOV A,#23;CMP_LED_START
        CJNE A,H,TTE4
        MOV A,#00
        CJNE A,M,TTE4
        MOV A,#00
        CJNE A,S,TTE4
        CLR P3.6                    ;到21:00:00关灯
TTE4:
RET




       
                END
R_YEAR:        DB 0,31,29,31,30,31,30,31,31,30,31,30,31                ;


TABLE:        DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H        ;
       
                END
举报

更多回帖

发帖
×
20
完善资料,
赚取积分