求单片机课程设计实验 用汇编语言,基于51单片机的定时闹钟

任务:
设计一个简易的定时闹钟时钟。
功能要求:
(1)可手动利用键盘设置当前时间和目标提醒时间;
(2)显示格式为“时时:分分”,且在数码管上显示;
(3)提醒时间到达,则用LED灯闪烁提醒,且蜂鸣器报警;
(4)有暂停和继续功能。
最好有原理图

MODE_RG EQU  40H ;模式选择

 MODE2 EQU  60H ;MODE值

 MODE3 EQU  61H

 MODE4 EQU  62H

 MODE5 EQU  63H

 MODE6 EQU  64H

 MODE1 EQU  65H

     HOUR    EQU  41H ;小时缓冲区

 MIN     EQU  42H ;分钟缓冲区

 SEC     EQU  43H ;秒缓冲区

 TEMP EQU  4AH

 ;*********闹钟缓冲区********************

 H_ALARM EQU  6AH ;闹钟缓冲区

 M_ALARM EQU  6BH

 S_ALARM EQU  6CH

 F_ALARM EQU  6DH

 ;***********秒表缓冲区******************

 M_SEC EQU  76H

 S_SEC EQU  77H

 ;*********LED送显示临时变量*************

 LED0 EQU  51H

 LED1 EQU  52H

 LED2       EQU  53H

 LED3 EQU  54H

 MODE_KEY   EQU  P3.4

 UP_KEY EQU  P3.3

 DOWN_KEY EQU  P3.5

 BUF EQU  49H

ORG 0000H

LJMP MAIN

ORG 000BH

LJMP INT_0

ORG 001BH

LJMP INT_1

ORG 0080H

MAIN: MOV SP,#2FH  ;堆栈初始化

MOV MODE_RG,#0  ;MODE_RG寄存器值初始化

MOV LED0,#0FEH  ;初始化LED

MOV LED1,#0FDH

MOV LED2,#0FBH

MOV LED3,#0F7H

MOV MODE1,#1

MOV MODE2,#2

MOV MODE3,#3

MOV MODE4,#4

MOV MODE5,#5

MOV MODE6,#6

MOV F_ALARM,#0  ;错误2:一开始用 CLR F_ALARM,这导致在后面的时候JZ F_ALARM 运行错误,

MOV BUF,#0 ;在于 JZ 指令是对累加器A全为0或者全为1进行判断,CLR只能对一位操作

MOV TMOD,#11H  ;定时器初始化:定时器0,方式1,定时器1,方式1

MOV IP,#00001000B  ;定时器1优先级高

MOV TH0,#3CH  ;定时50MS

MOV TL0,#0B1H

MOV TH1,#0D8H  ;定时10MS

MOV TL1,#0F0H

SETB EA

SETB ET0

SETB ET1

SETB TR0             ;启动定时器

        MOV HOUR,#0      ;for test

MOV MIN,#0

MOV SEC,#0  ;定时器计数器,50MS中断一次,200次则刚好1S

MOV M_SEC,#0

MOV S_SEC,#0

MOV H_ALARM,#0

MOV M_ALARM,#0

MAIN1: LCALL DISPLAY12

LCALL DISPLAY34

;CLR P1.4    TEST

JNB MODE_KEY,KEY_SCAN

MOV A,MODE_RG

CJNE A,MODE6,Y1   ;MODE6  秒表

JNB DOWN_KEY,DEALDOWN    ;判断秒表开关

JNB UP_KEY,DEALUP

Y1: MOV A,F_ALARM   ;判断闹钟

JNZ ALARM

LJMP MAIN1

;-----------------------------------秒表开关程序---------------------------

DEALDOWN: LCALL DELY10MS

JB DOWN_KEY,MAIN1

H1: JNB DOWN_KEY,H1

CPL TR1

LJMP MAIN1

DEALUP: LCALL DELY10MS

JB UP_KEY,MAIN1

H2: JNB UP_KEY,H2

MOV M_SEC,#0

MOV S_SEC,#0

CLR TR1

LJMP MAIN1

;-----------------------------------闹钟扫描程序---------------------------

ALARM: MOV A,H_ALARM

CPL P1.2

CJNE A,HOUR,EXIT3

MOV A,M_ALARM

CJNE A,MIN,EXIT3

LJMP STARTALARM

EXIT3: SETB P3.6

LJMP MAIN1

STARTALARM: CPL P3.6

JNB DOWN_KEY,OFFALARM

LJMP S1

OFFALARM: LCALL DELY10MS

JB DOWN_KEY,MAIN1

S2: JNB DOWN_KEY,S2

MOV F_ALARM,#0

SETB P3.6

LJMP MAIN1

S1: LCALL DELAY

LJMP MAIN1

;-----------------------------------键盘扫描程序---------------------------

KEY_SCAN: LCALL DELY10MS

JB MODE_KEY,MAIN1

INC MODE_RG

;SETB P1.4    测试

K1: JNB MODE_KEY,K1  ;按键直到用户松开按键

K2: MOV A,MODE_RG

CJNE A,#0,DEALMODE  ;不是在正常显示模式下则跳转到模式处理程序

LJMP MAIN1  ;返回主程序

;*******************模式处理程序部分

DEALMODE: MOV TEMP,#0  ;凡转入MODE处理,则首先清除TEMP

MOV A,MODE_RG  ;有MODE_RG值不为5、0

CJNE A,MODE2,M0  ;判断MODE_RG值,不为1跳转

LJMP H_GLINT  ;模式1,小时位闪烁

M0: CJNE A,MODE3,M1  ;不是模式2,跳转

LJMP M_GLINT  ;模式2,分钟位闪烁

M1: CJNE A,MODE4,M2  ;不是模式3,跳转

LJMP H_GLINT

M2:   CJNE A,MODE5,M3

LJMP M_GLINT

M3: CJNE A,MODE6,M4

MOV M_SEC,#0

MOV S_SEC,#0

LJMP MAIN1

M4: CJNE A,MODE1,M5

;CLR TR1

LJMP MAIN1

M5: MOV MODE_RG,#0

LJMP MAIN1

;*****************************MODE为1,3,小时位闪烁

//MOV TEMP,HOUR  ;将TEMP赋值,防止在加的时候是在随机值的基础上增加

H_GLINT: ;CPL P1.0

MOV R0,#28

MOV R1,#28

K4: LCALL DISPLAY12  ;分开显示

LCALL DISPLAY34

E1: JNB MODE_KEY,K21  ;检测是否有按键按下,有按下则跳转到分钟位闪烁

JB UP_KEY,E9  ;判断加位有无按键按下

LJMP UP

E9: DJNZ R0,K4

K6: LCALL DISPLAY34

JNB MODE_KEY,K21  ;检测是否有按键按下,有按下则跳转延时后进行模式判断

LJMP G1

K21: LCALL DELY10MS  ;延时后确定有MODE按键按下,将

JB MODE_KEY,H_GLINT

W: JNB MODE_KEY,W

INC MODE_RG

CPL P1.4

LJMP DEALMODE  ;确定有按下,MODE+1后返回MODE处理程序

JNB UP_KEY,UP  ;判断加位有无按键按下

G1: DJNZ R1,K6

LJMP H_GLINT  ;调用完毕返回,实现闪烁

K3: LJMP MAIN1  ;可省略

;******************************MODE为2,4,分钟位闪烁

M_GLINT: MOV R0,#28

MOV R1,#28

K23: CPL P1.7    

LCALL DISPLAY12

LCALL DISPLAY34

JNB MODE_KEY,KK  ;跳转,确定是否有按键按下

JNB UP_KEY,UP  ;判断加位有无按键按下

MOV A,MODE_RG

CJNE A,MODE3,E2  ;在MODE5的情况下要判断闹钟确认键有没按下

LJMP E5

E2: JNB DOWN_KEY,F2

LJMP E5

F2: LJMP ONALARM2

E5: DJNZ R0,K23

K24: LCALL DISPLAY12

JNB MODE_KEY,KK  ;检测是否有按键按下,有按下则跳转

JNB UP_KEY,UP  ;判断加位有无按键按下

MOV A,MODE_RG  ;扫描闹钟确认键

CJNE A,MODE3,E7  ;在MODE5的情况下要判断闹钟确认键有没按下

LJMP G2

E7: JB DOWN_KEY,E8

CPL P1.3

LJMP ONALARM2

E8: LJMP G2

KK: LCALL DELY10MS  ;去抖

JB MODE_KEY,M_GLINT

W1: JNB MODE_KEY,W1

INC MODE_RG

CPL P1.4

LJMP DEALMODE  ;确定有按下,MODE+1后返回MODE处理程序

G2: DJNZ R1,K24

LJMP M_GLINT

;*************************位加,处理程序

;***************小时调整

UP: MOV R1,#20

UP11: INC TEMP

UP12: MOV A,MODE_RG  ;判断此时的MODE,根据MODE将临时变量给对应的赋值

CJNE A,MODE2,AA0  ;不是在MODE2的情况下跳转

MOV A,TEMP

CJNE A,#24,A_UP1

MOV TEMP,#0

A_UP1: MOV HOUR,TEMP  ;为MODE2,将临时变量赋给小时位

LJMP UP15

AA0: CJNE A,MODE4,UP13    //UP13为分钟调整入口

MOV A,TEMP

CJNE A,#24,A_UP

MOV TEMP,#0

A_UP: MOV H_ALARM,TEMP   ;模式3,将临时变量赋给闹钟的小时位

LJMP UP15   ;UP15为显示入口

;****************分钟调整入口

UP13: MOV A,MODE_RG

CJNE A,MODE3,UP14  ;不是模式2,跳转

MOV A,TEMP

CJNE A,#60,DISOVER2

MOV TEMP,#0

DISOVER2: MOV MIN,TEMP

LJMP UP15

UP14: MOV A,TEMP  ;上面判断不是模式2,则必然是模式4

CJNE A,#60,DISOVER3

MOV TEMP,#0

DISOVER3: MOV M_ALARM,TEMP

LJMP UP15

UP15: LCALL DISPLAY12

LCALL DISPLAY34

DJNZ R1,UP01

MOV R1,#1   ;

JNB UP_KEY,UP11

UP01: JNB UP_KEY,UP12

UP16: MOV A,MODE_RG   ;松开键以后按照模式判断该返回哪种状态,不能返回DEALMODE函数

CJNE A,MODE2,UP17

LJMP H_GLINT

UP17: CJNE A,MODE3,UP18

MOV SEC,#0   ;每次设置完时间后将秒钟位置零保证时间准确

LJMP M_GLINT

UP18: CJNE A,MODE4,UP19

LJMP H_GLINT

UP19: CJNE A,MODE5,UP20

LJMP M_GLINT

UP20: LJMP MAIN1

ONALARM2: LCALL DELY10MS  ;延时10MS,去抖

JB DOWN_KEY,B2  ;抖动所致,返回分钟位闪烁

LJMP K42

B2: LJMP M_GLINT

K42: JNB DOWN_KEY,K42

MOV F_ALARM,#0FFH

MOV MODE_RG,#0

LJMP MAIN1

;---------------------------------------中断程序入口---------------------

;*******************时间中断0*********************

;错误1:中断程序EXIT处用了MAIN1,导致一直处于中断状态   

INT_0: PUSH ACC

PUSH PSW

MOV TH0,#3CH

MOV TL0,#0B1H

INC BUF

MOV A,BUF

CJNE A,#20,EXIT

TIME: MOV BUF,#0

INC SEC

MOV A,SEC

CJNE A,#60,EXIT

MOV SEC,#00H

INC MIN

MOV A,MIN

CJNE A,#60,EXIT

MOV MIN,#00H

INC HOUR

MOV A,HOUR

CJNE A,#24,EXIT

MOV HOUR,#0

RETI    

EXIT:  POP PSW

   POP ACC

  RETI

;******************时间中断1***********************

INT_1:  MOV TH1,#0D8H  ;定时10MS

MOV TL1,#0F0H

INC S_SEC

MOV A,S_SEC

CJNE A,#100,EXIT4

MOV S_SEC,#0

INC M_SEC

MOV A,M_SEC

CJNE A,#100,EXIT4

MOV M_SEC,#0

EXIT4: RETI

;---------------------------------------显示-----------------------------

DISPLAY12: MOV A,MODE_RG   ;判断模式,决定是显示闹钟时间还是显示当前时间

CJNE A,MODE4,DIS0   ;模式四,显示闹钟

LJMP DIS01   ;MODE4

DIS0: CJNE A,MODE5,DIS20

DIS01: MOV R7,H_ALARM   ;闹钟模式

LJMP DIS2

DIS20: CJNE A,MODE6,DIS21

MOV R7,M_SEC   ;秒表模式,显示秒表高位

LJMP DIS2

DIS21: CJNE A,MODE1,DIS1

LJMP DIS22

DIS22: MOV R7,MIN

LJMP DIS2

DIS1: MOV R7,HOUR   ;DISPLAY12显示高位

DIS2: LCALL BCTD   ;判断完毕,调用显示

;将秒、分 分别转码,放到R4,R3

MOV A,R4

MOV R3,A

LCALL DIVIDE

MOV DPTR,#NUMTAB

MOV P2,#0FH

MOV P2,LED0

MOV A,45H  ;从拆字的出口获取值

MOVC A,@A+DPTR

MOV P0,A

LCALL DELY10MS

MOV P2,LED1

MOV A,46H

MOVC A,@A+DPTR

MOV P0,A

LCALL DELY10MS

RET

DISPLAY34: MOV A,MODE_RG   ;判断模式,决定是显示闹钟时间还是显示当前时间

CJNE A,MODE4,DIS31

LJMP DIS32

DIS31: CJNE A,MODE5,DIS35

DIS32: MOV R7,M_ALARM

LJMP DIS34

DIS35: CJNE A,MODE6,DIS41

MOV R7,S_SEC   ;秒表模式,显示秒表低位

LJMP DIS34

DIS41: CJNE A,MODE1,DIS33

MOV R7,SEC

LJMP DIS34

DIS33: MOV R7,MIN  ;DISPLAY34显示低位

DIS34: LCALL BCTD

MOV A,R4

MOV R3,A

LCALL DIVIDE

MOV P2,LED2

MOV A,47H

MOVC A,@A+DPTR

MOV P0,A

LCALL DELY10MS

MOV P2,LED3

MOV A,48H

MOVC A,@A+DPTR

MOV P0,A

LCALL DELY10MS

SETB P2.3

RET

;--------------------二翻十:入口:R6R7 出口:R2R3R4----------------------

BCTD: MOV R5,#16

CLR A

MOV R2,A

MOV R3,A

MOV R4,A

LOOP: CLR C

MOV A,R7

RLC A

MOV R7,A

MOV A,R6

RLC A

MOV R6,A

MOV A,R4

ADDC A,R4

DA A

MOV R4,A

MOV A,R3

ADDC A,R3

DA A

MOV R3,A

MOV A,R2

ADDC A,R2

DA A

MOV R2,A

DJNZ R5,LOOP

RET

;-----------------------拆字:入口:R3R4 出口:45H46H47H48H------------------

DIVIDE: MOV A,R3

ANL A,#0FH

MOV 46H,A

MOV A,R3

ANL A,#0F0H

SWAP A

MOV 45H,A      ;时拆字 45H放时高位,46H放十低位

MOV A,R4

ANL A,#0FH

MOV 48H,A

MOV A,R4

ANL A,#0F0H

SWAP A

MOV 47H,A      ;分拆字 47H放分高位,48H放分低位

            RET

;------------------------------------延时----------------------------------

DELY10MS:   MOV R6,#10  

D1:         MOV R7,#248

            DJNZ R7,$

            DJNZ R6,D1

            RET

DELAY: MOV 74H,#2 ;延时子程序,12M晶振延时1.002秒

L3:  MOV 72H ,#10

L1:  MOV 73H ,#249

L2:  DJNZ 73H ,L2

LCALL DISPLAY12

LCALL DISPLAY34

JNB DOWN_KEY,OFFALARM1

LJMP S3

OFFALARM1: LCALL DELY10MS

JB DOWN_KEY,S3

S4: JNB DOWN_KEY,S4

MOV F_ALARM,#0

SETB P3.6

LJMP MAIN1

S3: DJNZ 72H ,L1

DJNZ 74H ,L3

RET

NUMTAB:     DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH  ;码表

END

温馨提示:答案为网友推荐,仅供参考
第1个回答  2012-01-02
MOV AL,0FFH
MOV DX,300H
OUT DX,AL
CALL CLEAR ;LCD 清除
LEA BX,HZ_TAB
MOV CH,2 ;显示第2行信息
CALL LCD_DISP
LEA BX, HZ_TAB
MOV CH,3 ;显示第3行信息
CALL LCD_DISP
l1: JMP L1
CLEAR PROC
MOV AL,0CH
MOV DX,IO_ADDRESS
OUT DX,AL ;设置CLEAR命令
CALL CMD_SETUP ;启动LCD执行命令
RET本回答被提问者采纳
第2个回答  2011-12-19
..
第3个回答  2011-12-19
瓦尔特瓦尔特