led数码管、led数码彩屏专业生产厂家,承接各种数码管显示屏的定制业务,手机(微信):15626546861 关于我们 | 联系我们 | 在线留言
国内业务热线
15626546861
当前位置: 主页 > led数码管知识 > 常识问答

led数码管电子时钟制作及程序

文章出处:-1 人气:发表时间:2020-08-10 11:33

一、 题目及功能要求

1 制作一个电子日历时钟使用汇编语言进行软件编程
2 实现功能
(1) 显示北京时间并能校准
(2) 时、分、秒之间以及年、月、日之间以小数点隔开
(3) 显示公历日期并能校准能够自动识别“闰年”以及“大月、小月”
(4) 运动秒表能够后台计时秒表精确到 0.05S
(5) 闹钟功能有闹钟开关并能显示当前闹钟是否开启
(6) 整点报时提醒

二、 硬件方案

1 AT89S52 最小系统
2 显示电路采用动态扫描驱动电路AT89S52 的 P0 口连接 74LS244 总线驱动器输
出信号利用三极管 8550 进行放大通过 P1 口对数码管进行段选扫描AT89S52 的
P1.2~P1.7 口对数码管进行位选扫描
3 两个按键开关分别接 AT89S52 的两个外部中断引脚
4 AT89S52 的 P2.0 口输出经三极管 9012 放大驱动有源蜂鸣器发声

三、 电路原理图

led数码管时钟电路原理图

四、 系统元件布局、布线图

led数码管时钟系统元件布局布线图

五、 元器件清单

led数码管时钟元器件清单

六、 软件方案

1 “时钟”基准时间由 AT89S52 定时器 0 中断提供设置为最高优先级定时器 0
设为工作方式 1即 16 进制计数器方式计数初值设为 15536即可实现 0.05s 中
断一次连续中断 20 次即可实现一秒定时。
2 由于使用较多数码管显示模块使用动态扫描方式定义全局变量保存各个数位
的 BCD 码通过查表将字模送到 P0 口进行输出为了显示闹钟的状态设置了
另一字模数据表在显示前进行判断若为闹钟开关设置状态则调用此字模数据表。
3 按键中断的时候在 2 个按键都没按下的状态2 个中断引脚都为低电平则一直
调用中断 0 的子程序每次进入中断 0 子程序中便检测中断 1 的引脚是否为高电平
即检测开关 KEY1 是否按下相反在按下 KEY0 时进入中断 1 子程序每次进
入中断 1 子程序都检测中断 0 的引脚是否为高电平为高电平则表示已按下。
4 用寄存器 R7 来记录当前切换的功能分别为0时间1日期2-闹钟3-闹钟
开关4-秒表。
5 秒表的实现采用基准时钟作为秒表时钟源,精度可以达到 0.05s。
6 闹钟的实现在主程序中循环判断闹钟设置的时分与当前时分是否相等闹钟持
续 1 分钟
7 整点报时的实现在主程序中先判断当前时间的秒若为 0 再判断分再为 0 则
使蜂鸣器嘀一声循环判断。

七、 程序框图

1. 主程序
led数码管时钟主程序
2. 定时器 0 中断子程序
led数码管时钟定时器0中断子程序
3. 外部中断 0 子程序
led数码管时钟外部中断0子程序

4. 外部中断 1 子程序
led数码管时钟外部中断1子程序

八、 系统使用说明

1 接通电源自动复位读取初始状态时钟--“00.00.00”日期—“10.06.06”闹钟
—“06.00.00”闹钟状态—“OFF”秒表—“00.00.00”。
2 按键 KEY1 为“切换功能/调节”按钮按键 KEY0 为“确定/计时开始/计时暂停/
闹钟开关按钮
3 第一功能----电子时钟按 KEY0 键进入时校准状态“时”数码管闪烁此时按
KEY1 键可以调节小时“时”调节范围为 00~24按 KEY0 可切换到“分”设置
调节范围为 00~59 再按 KEY0 可切换到“秒”设置 调节范围为 00~59。
4 第二功能----电子日历在电子时钟功能下按 KEY1 可以切换到电子日历功能。
进入电子日历功能可以对“年”.“月”.“日”进行校准校准方式同电子时钟
的校准方式一样自行摸索。
5 第三功能----闹钟设置在电子日历功能下按 KEY1 可以切换到闹钟设置功能。
闹钟的设置同电子时钟的设置一样。
6 第四功能----闹钟开关在闹钟设置功能下按 KEY1 可以切换到闹钟开关设置。
默认状态为关闭闹钟功能显示“OFF”按 KEY0 可以调节闹钟开关打开闹钟
功能则显示“ON”。闹钟设置为“ON”时最后一个数码管的小数点会亮起可
以在任何功能状态下提示闹钟功能已开启。
7 第五功能----秒表在闹钟设置功能下按 KEY1 可以切换到秒表功能。进入秒表
功能按 KEY0 开始计时再按 KEY0 则暂停计时在秒表计时的时候按 KEY1 可
以切换到其他功能而秒表则在后台计时在秒表暂停时按 KEY1 可以将秒表清零。

九、 体会

第一次使用Atmel Designer Winter 09布出一个完整的PCB制板图并用覆铜板做成实
物最大的体会是软件能画出来的图我们不一定就能把这样的 电路板做出来。布线时
要考虑的因素除整体布局、飞线数目外最重要的是线的宽度、线与线的间距、焊盘的大小。
唯有线宽合适、间距合 理才能做出符合要求的电路板。刚制成的电路板要先使用万用表检
测各导线的连接情况解决断路、短路的问题之后方能进行焊接。这样做 的好处是保证
了调试程序时不会受硬件接触不良等情况的影响。
由于第一次尝试完全使用汇编语言对AT89S52进行编程操作对汇编语言的陌生给前期
编程工作带来诸多不便。汇编语言不同于C或其它高级 语言程序间的跳转各种寄存器的
压栈出栈都需要人工考虑而这种疏漏编译器也不会给出任何提示于是往往一些大意的疏
忽程序便 无法达到预期的效果。加之没有相关条件使用在线调试也给故障排除带来一
些障碍。
对此的体会是确定是程序出现问题时优先往程序间的跳转条件、重要寄存器等的现
场保护、循环退出的条件方面考虑寻找原因。由于 此次硬件电路设计采用低电平导通的
PNP三极管和74LS244电平驱动器也没有将IO口做通用数据传输口用故不需考虑上拉电
阻的选用及 将相应管脚写入高电平以正确接收数据的问题。当然在调试的过程中合理的使
用软件仿真机熟练的设置程序断点同时观察单片机各寄存 器值的变化可以极大方便
我们查找程序漏洞解决问题。
在书写代码的过程中应该注意代码的规范化尤其是使用汇编编程时必须加上必要
的注释方便程序阅读及故障排查。对于需要使用 到的各个变量必须在程序开头集中定
义存储位置以求一目了然在新增变量的时候也不至于出现存储单元被重复使用而导致数
据丢失的 情况。
最后看着忙碌数日得来的劳动成果乖乖的工作确实蛮有成就感。希望今后有更多的
机会进行这样的实践实验。
 
十、 附录

;AT89S52CLOCK_FINAL.asm
; (Electronic Calendar and Clock)
; Reference for Grade 2008, s.c.u.t.
; Key0(for shift/adjust) connected to INT1
; Key1(for un-flash/flash) connected to INT0
; 学生姓名黄锦波黄卓佳
; 学生学号200830240380200830240434
; 分组编号007
;变量定义
TICK_CNT EQU 20H ;T0 倍乘
;------------------
SECOND_BCD EQU 21H ;时间记录
MINUTE_BCD EQU 22H
HOUR_BCD EQU 23H
;------------------
DAY_BCD EQU 24H ;日期记录
MONTH_BCD EQU 25H
YEAR_BCD EQU 26H
;------------------
FLASH_FLAG EQU 27H ;是否闪烁
DIS_FLAG EQU R7 ;当前显示内容标志 ;DIS_FLAG: 0时间1日期;2-闹钟3-闹钟开
关4-秒表
;------------------
NSECOND_BCD EQU 2BH ;闹钟时间
NMINUTE_BCD EQU 2CH
NHOUR_BCD EQU 2DH
;------------------
TCC_BCD EQU 2EH ;秒表计时器
TBB_BCD EQU 2FH
TAA_BCD EQU 30H
;------------------
TIMER_FLAG EQU 31H ;秒表模式
TIMER_START_FLAG EQU 32H ;秒表开始
;------------------
ALAM_STATE EQU 33H ;闹钟开启标志
;------------------
DI_40H EQU 34H ;提示音延时变量
DI_41H EQU 35H ;延时
;------------------
ALAM_ON1 EQU 36H ;闹钟状态显示
ALAM_ON2 EQU 37H
ALAM_ON3 EQU 38H
ALAM_OFF1 EQU 39H
ALAM_OFF2 EQU 3AH
ALAM_OFF3 EQU 3BH
;------------------
;中断向量表
ORG 0000H
LJMP MAIN
ORG 0003H
LJMP EX0_INT ; port INT0
ORG 000BH
LJMP T0_INT ; port T0
ORG 0013H
LJMP EX1_INT ; port INT1
;主程序
ORG 0030H
MAIN: NOP ; main program
;初始化堆栈
MOV SP,#60H
;初始化变量
MOV SECOND_BCD,#00H ; BCD of "second"
MOV MINUTE_BCD,#00H ; BCD of "minute"
MOV HOUR_BCD,#00H ; BCD of "hour"
MOV NSECOND_BCD,#00H ; BCD of "second"
MOV NMINUTE_BCD,#00H ; BCD of "minute"
MOV NHOUR_BCD,#06H ; BCD of "hour"
MOV TCC_BCD,#00H ; BCD of "second"
MOV TBB_BCD,#00H ; BCD of "minute"
MOV TAA_BCD,#00H ; BCD of "hour"
MOV TIMER_START_FLAG,#00H ;秒表工作标志
MOV TIMER_FLAG,#00H ;秒表模式标志
MOV DAY_BCD,#06H ; BCD of "day"
MOV MONTH_BCD,#06H ; BCD of "month"
MOV YEAR_BCD,#010H ; BCD of "year"
MOV FLASH_FLAG,#00H ; flag for un-flash/flash
MOV DIS_FLAG,#00H ; flag for shift(time/date)
MOV ALAM_ON1,#55H ; BCD OF 闹钟状态显示
MOV ALAM_ON2,#01H
MOV ALAM_ON3,#55H
MOV ALAM_OFF1,#63H
MOV ALAM_OFF2,#42H
MOV ALAM_OFF3,#33H
MOV ALAM_STATE,#00H ;初始化闹钟状态为 OFF
;------------------
MOV TL0,#0B0H ; constant for 0.05s
MOV TH0,#3CH ; 65536-15536=50,000 for 12MHz
MOV TICK_CNT,#14H ; times of overflow 0.05*20=1s
MOV TMOD,#01H ; Mode 1 for T0, Timer Mode
SETB ET0 ; open T0
SETB EX0 ; open INT0, Key1
SETB EX1 ; open INT1, Key0
SETB EA ; total open
SETB PT0 ; priority for T0高优先级
SETB TR0 ; start T0, Run
SCAN_HOUR: ;闹钟扫描
MOV A,SECOND_BCD
CJNE A,#00H,SCANALARM
MOV A,MINUTE_BCD
CJNE A,#00H,SCANALARM
HOUR:
CLR P2.0
NOP ;整点滴
SETB P2.0
SCANALARM: ;闹钟扫描
MOV A,ALAM_STATE
JZ SCAN_HOUR ;闹钟开关已打开
MOV A,NHOUR_BCD
CJNE A,HOUR_BCD,WAIT
MOV A,NMINUTE_BCD
CJNE A,MINUTE_BCD,WAIT
ALARM:
CLR P2.0 ;闹铃滴滴滴滴``````
SETB P2.0
CLR P2.0
SETB P2.0
CLR P2.0
SETB P2.0
CLR P2.0
SETB P2.0
NOP
NOP
NOP
WAIT:
SETB P2.0
SJMP SCAN_HOUR ; wait for interrupt
; -------------------------------------------------
; sub: T0 interrupt
; 定时器 0 中断
T0_INT:
PUSH ACC
MOV TL0,#0B0H ; constant for 0.05s
MOV TH0,#3CH ; Timer 0 重装载
MOV A,TIMER_START_FLAG
CJNE A,#01H,TIMER_NEXT ;秒表模式
LJMP TIMER_INC ;秒表计时
TIMER_NEXT:
DJNZ TICK_CNT,NOT_1S ; is up to 1 second ?
SJMP IS_1S
NOT_1S:
LJMP T0_RET
; 1 秒时间到
IS_1S:
MOV A,SECOND_BCD ; take BCD of "second"
CJNE A,#59H,IN3 ; is up to 59 seconds ?
SJMP IN4
IN3:LJMP SECOND_INC ; 秒加 1
IN4:MOV SECOND_BCD,#00H ; 秒进位
MOV A,MINUTE_BCD ; take BCD of "minute"
CJNE A,#59H,IN5 ; is up to 59 minutes ?
SJMP IN6
IN5: LJMP MINUTE_INC
IN6: MOV MINUTE_BCD,#00H ; 分进位
MOV A,HOUR_BCD ; take BCD of "hour"
CJNE A,#23H,HOUR_INC ; is up to 23 hours ?
MOV HOUR_BCD,#00H ; “时”进位
MOV A,MONTH_BCD ; take BCD of "month"
CJNE A,#02H,NOT_FEB ; is February ?
;2 月处理
;--------------------------
FEB: NOP
ACALL BCD_DIV4 ; BCD of "year in 26H" divided by 4
MOV A,R3 ; remainder in R3
CJNE A,#00H,NOT_LEAP_Y ; "00" means leap year
;闰年29 天
LEAP_Y: MOV A,DAY_BCD ; take BCD of "day" in Feb.
CJNE A,#29H,DAY_INC ; is up to 29 days (leap year)?
MOV DAY_BCD,#01H ; keep the first day
MOV MONTH_BCD,#03H ; increase "month"
SJMP RESET_CNT
;非闰年
NOT_LEAP_Y: MOV A,DAY_BCD ; take BCD of "day" in Feb.
CJNE A,#28H,DAY_INC ; is up to 28 days (common year)?
MOV DAY_BCD,#01H ; keep the first day
MOV MONTH_BCD,#03H ; increase "month"
SJMP RESET_CNT
;---------------------------
;非 2 月处理
;30/31 天
NOT_FEB:NOP ; other "month" except Feb.
CJNE A,#04H,Y01 ; is April ?
AJMP MON_30D
Y01: CJNE A,#06H,Y02 ; is June ?
AJMP MON_30D
Y02: CJNE A,#09H,Y03 ; is September ?
AJMP MON_30D
Y03: CJNE A,#11H,T11 ; is November ?
AJMP MON_30D
;31 天
T11: MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#31H,DAY_INC ; is up to 31 days ?
AJMP NEXT_MONTH
;30 天
MON_30D:MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#30H,DAY_INC ; is up to 30 days ?
;天进位
NEXT_MONTH: MOV DAY_BCD,#01H ; keep the first day
MOV A,MONTH_BCD ; take BCD of "month"
CJNE A,#12H,MONTH_INC; is December ?
; 月进位
MOV MONTH_BCD,#01H ; keep the first month
MOV A,YEAR_BCD ; take BCD of "year"
CJNE A,#99H,YEAR_INC ; is up to 99 years ?
MOV YEAR_BCD,#00H ; keep the first year
SJMP RESET_CNT
;年加 1
YEAR_INC: MOV A,YEAR_BCD ; take BCD of "year"
ADD A,#01H ; increase "year"
DA A ; adjust BCD
MOV YEAR_BCD,A ; keep "year"
SJMP RESET_CNT
MONTH_INC: MOV A,MONTH_BCD ; take BCD of "month"
ADD A,#01H ; increase "month"
DA A ; BCD 码调整
MOV MONTH_BCD,A ; keep "month"
SJMP RESET_CNT
DAY_INC: MOV A,DAY_BCD ; take BCD of "day"
ADD A,#01H ; increase "day"
DA A ; BCD 码调整
MOV DAY_BCD,A ; keep "day"
SJMP RESET_CNT
HOUR_INC: MOV A,HOUR_BCD ; take BCD of "hour"
ADD A,#01H ; increase "hour"
DA A ; BCD 码调整
MOV HOUR_BCD,A ; keep "hour"
SJMP RESET_CNT
MINUTE_INC: MOV A,MINUTE_BCD ; take BCD of "minute"
ADD A,#01H ; increase "minute"
DA A ; BCD 码调整
MOV MINUTE_BCD,A ; keep "minute"
SJMP RESET_CNT
SECOND_INC: MOV A,SECOND_BCD ; take BCD of "second"
ADD A,#01H ; increase "second"
DA A ; BCD 码调整
MOV SECOND_BCD,A ; save back "second"
RESET_CNT: MOV TICK_CNT,#14H ; retrieve times of overflow
T0_RET:
POP ACC
RETI
;--------------------------------------------------------------------
;秒表增
TIMER_INC:
TCC_INC:
MOV A,TCC_BCD ; take BCD of "0.05S"
CLR C
SUBB A,#95H
JZ TBB_INC
MOV A,TCC_BCD
ADD A,#05H ; increase "0.05S"
DA A ; BCD 码调整
MOV TCC_BCD,A ; keep "0.05S"
AJMP TIMER_OUT
TBB_INC:
MOV TCC_BCD,#00H
MOV A,TBB_BCD ; take BCD of "SECOND"
CLR C
SUBB A,#59H
JZ TAA_INC
MOV A,TBB_BCD
ADD A,#01H ; increase "SECOND"
DA A ; BCD 码调整
MOV TBB_BCD,A ; keep "SECOND"
AJMP TIMER_OUT
TAA_INC:
MOV TBB_BCD,#00H
MOV A,TAA_BCD ; take BCD of "MINUTE"
CLR C
SUBB A,#59H
JZ TDD_INC
MOV A,TAA_BCD
ADD A,#01H ; increase "MINUTE"
DA A ; BCD 码调整
MOV TAA_BCD,A ; save back "MINUTE"
AJMP TIMER_OUT
TDD_INC:MOV TAA_BCD,00H
TIMER_OUT: LJMP TIMER_NEXT ;返回定时器中断
;------------------------------------------------------------------
; -------------------------------------------------------------------
; sub: LED Display
;显示子程序
DISPLAY:
MOV A,DIS_FLAG
CJNE A,#03H,DISPLAY2 ;选择不同字模
MOV DPTR,#TAB2
SJMP DISPLAY3
DISPLAY2:
MOV DPTR,#TAB ; set address of code table
DISPLAY3:
MOV A,DIS_FLAG ; take flag for shift
CJNE A,#00H,DISP_DATE ; "00" 当前显示内容为时间
;R0: point to display buffer
DISP_TIME: MOV R0,#SECOND_BCD ; beginning from "second"
SJMP TSA
DISP_DATE:
CJNE A,#01H,DISP_ALAM ; "01" 当前显示内容为日期
MOV R0,#DAY_BCD ; "FF" for showing date
SJMP TSA;显示时间或日期
DISP_ALAM:
CJNE A,#02H,DISP_ALAM_SET ; "02" 当前显示内容为闹钟
MOV R0,#NSECOND_BCD ; beginning from "second"
SJMP TSA
DISP_ALAM_SET:
CJNE A,#03H,DISP_TIMER ; "03" 当前显示内容为闹钟设置
MOV A,ALAM_STATE ; 闹钟状态显示
JZ SHOWOFF
MOV R0,#ALAM_ON1 ; 显示”ON“
SJMP TSA
SHOWOFF:
MOV R0,#ALAM_OFF1 ;显示“OFF”
SJMP TSA
DISP_TIMER: ;"04"当前显示内容为秒表
MOV R0,#TCC_BCD ; beginning from "second"
TSA: MOV A,@R0 ; begin from "day"
ANL A,#0FH ; get the "low half byte"
MOVC A,@A+DPTR ; take character from code table
MOV R1,A ; keep in R1 for DS6 showing
MOV A,@R0
SWAP A
ANL A,#0FH ; get the "high half byte"
MOVC A,@A+DPTR ; take character from code table
MOV R2,A ; keep in R2 for DS5 showing
;---------------
INC R0
MOV A,@R0 ; next one from "month"
ANL A,#0FH ; get the "low half byte"
MOVC A,@A+DPTR
MOV R3,A ; keep in R3 for DS4 showing
MOV A,@R0
SWAP A
ANL A,#0FH ; get the "high half byte"
MOVC A,@A+DPTR
MOV R4,A ; keep in R4 for DS3 showing
;-------------
INC R0
MOV A,@R0 ; next one from "year"
ANL A,#0FH ; get the "low half byte"
MOVC A,@A+DPTR
MOV R5,A ; keep in R5 for DS2 showing
MOV A,@R0
SWAP A
ANL A,#0FH ; get the "high half byte"
MOVC A,@A+DPTR
MOV R6,A ; keep in R6 for DS1 showing
;---------------------
;P1位选线
;P0段选线
NOP
TDP: MOV P1,#0FFH ; close all showing///
;Display DS6
MOV A,ALAM_STATE ;是否显示闹钟状态位最末位小数点
JZ DIS_NEXT
MOV A,R1
ANL A,#7FH
MOV R1,A
DIS_NEXT:
MOV A,R1
MOV P0,A ; send character to DS6
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#03H,A02 ; "03" is flash on DS5&DS6
SJMP A03
A02: CJNE A,#03H,A04; ; "03" is flash on DS5&DS6
A03: MOV A,TICK_CNT ; take Counter of overflow
RRC A
JNC A05 ; check bit C ( 1 or 0 )
A04: MOV P1,#0FBH ; turn on DS6
A05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS5
MOV P0,R2 ; send character to DS5
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#03H,B02 ; "03" is flash on DS5&DS6
SJMP B03
B02: CJNE A,#03H,B04
B03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC B05 ; check bit C ( 1 or 0 )
B04: MOV P1,#0F7H ; turn on DS5
B05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS4
MOV A,R3
ANL A,#7FH ;该位增加小数点显示
MOV P0,A ; send character to DS4
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#02H,C02 ; "02" is flash on DS3&DS4
SJMP C03
C02: CJNE A,#02H,C04
C03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC C05 ; check bit C ( 1 or 0 )
C04: MOV P1,#0EFH ; turn on DS4
C05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS3
MOV P0,R4 ; send character to DS3
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#02H,D02 ; "02" is flash on DS3&DS4
SJMP D03
D02: CJNE A,#02H,D04
D03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC D05 ; check bit C ( 1 or 0 )
D04: MOV P1,#0DFH ; turn on DS3
D05: LCALL DELAY
MOV P1,#0FFH ; close all showing
;Display DS2
MOV A,R5
ANL A,#7FH ;该位增加小数点显示
MOV P0,A ; send character to DS2
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#01H,E02 ; "01" is flash on DS1&DS2
SJMP E03
E02: CJNE A,#01H,E04
E03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC E05 ; check bit C ( 1 or 0 )
E04: MOV P1,#0BFH ; turn on DS2
E05: LCALL DELAY
MOV P1,#0FFH ; close all showing
MOV P0,R6 ; send character to DS1
MOV A,FLASH_FLAG ; get flag of un-flash/flash
CJNE A,#01H,F02 ; "01" is flash on DS1&DS2
SJMP F03
F02: CJNE A,#01H,F04
F03: MOV A,TICK_CNT ; take times of overflow
RRC A
JNC F05 ; check bit C ( 1 or 0 )
F04: MOV P1,#07FH ; turn on DS1
F05: LCALL DELAY
MOV P1,#0FFH ; close all showing
RET
; -------------------------------------------------------------------
; ----------------------------------------
; sub: delay (1.542ms for 12MHz, 3.084ms for 6MHz)
;延时子程序
D_CNT_2 EQU 28H
D_CNT_1 EQU 29H
DELAY:MOV D_CNT_2,#03H
D_LOOP2: MOV D_CNT_1,#0FFH ;[1]
D_LOOP1: DJNZ D_CNT_1,D_LOOP1 ;[2]
DJNZ D_CNT_2,D_LOOP2 ;[2]
RET
; ----------------------------------------
; ---------------------------------------------------------
;外部中断 0
; sub: INT0 interrupt
; 处理按键 K0,切换时间/日期/闹钟/闹钟设置/秒表显示或者调整
EX0_INT: NOP ; switch or adjust with date/time
PUSH ACC
PUSH PSW
LCALL DIS_DELAY ; re-bounce (with LED display)
JNB P3.3,OUT ; check port INT1
;K0 按下
NOP ; inhibit INT1 ( use k0)
;---------------------------------------------------
MOV A,FLASH_FLAG
CJNE A,#00H,JUDGE_MODE ;有闪烁进入调整模式
SET_DIS: ;无闪烁进入设置显示或秒表模式
CLR P2.0 ;按键滴一声
MOV DI_41H,#19H
DI_LPO:
MOV DI_40H,#0FFH
DI_LP:
DJNZ DI_40H,DI_LP
DJNZ DI_41H,DI_LPO
SETB P2.0
;---------------------------------------------------
MOV A,DIS_FLAG
INC A
MOV DIS_FLAG,A
CJNE A,#04H,CROSSTIMER ;进入秒表
;---------------------------------------------------
TIMER:
MOV TIMER_FLAG,#01H ;进入秒表秒表模式设置为开
LJMP EX0_RET ;退出
;---------------------------------------------------
CROSSTIMER: ;显示模式切换
CJNE A,#05H,OUT
MOV DIS_FLAG,#00H ;已到 5 需置零
MOV TIMER_FLAG,#00H
MOV A,TIMER_START_FLAG
JNZ OUT ;秒表后台工作暂停计数时退出则对秒表清零
MOV TCC_BCD,#00H ; BCD of "second" 秒表清零
MOV TBB_BCD,#00H ; BCD of "minute"
MOV TAA_BCD,#00H ; BCD of "hour"
OUT: LJMP EX0_RET ; 退出
;---------------------------------------------------
JUDGE_MODE: ;进入调整模式
MOV A,DIS_FLAG ; 读取当前显示内容为时间/日期/秒表/闹钟
CJNE A,#00H,JDATE ;是否进入时间调整 00
;---------------------------------------------------
JTIME: ;调整时间
MOV A,FLASH_FLAG ; take flag of un-flash/flash
ADH: CJNE A,#01H,ADM ; "03" for adjusting "hour"
MOV A,HOUR_BCD ; take BCD of "hour"
CJNE A,#23H,JH0 ; is up to 23 hours ?
MOV HOUR_BCD,#00H ; keep the first hour
LJMP JHF
JH0: ADD A,#01H ; increase "hour"
DA A ; adjust BCD
MOV HOUR_BCD,A ; keep "hour"
JHF: LJMP EX0_RET
;-----------------------------------------
ADM: CJNE A,#02H,ADS ; "02" for adjusting "minute"
MOV A,MINUTE_BCD ; take BCD of "minute"
CJNE A,#59H,JM0 ; is up to 59 minutes ?
MOV MINUTE_BCD,#00H ; keep the first minute
LJMP JMF
JM0: ADD A,#01H ; increase "minute"
DA A ; adjust BCD
MOV MINUTE_BCD,A ; keep "minute"
JMF: LJMP EX0_RET
ADS: MOV A,SECOND_BCD ; take BCD of "second"
CJNE A,#59H,JS0 ; is up to 59 seconds ?
MOV SECOND_BCD,#00H ; keep the first second
LJMP JSF
JS0: ADD A,#01H ; increase "second"
DA A ; adjust BCD
MOV SECOND_BCD,A ; keep "second"
JSF: NOP
LJMP EX0_RET
;---------------------------------------------------
JALAM0: LJMP JALAM
JDATE: CJNE A,#01H,JALAM0 ;是否进入日期调整 01
JYY: NOP ; "01 to 06" is in flash
MOV A,FLASH_FLAG
CJNE A,#01H,JMM ; "01" for adjusting "year"
;调节年
MOV A,YEAR_BCD ; take BCD of "year"
CJNE A,#99H,YY0 ; is up to 99 year ?
MOV YEAR_BCD,#00H ; keep the first year
LJMP YYF
YY0: ADD A,#01H ; increase "year"
DA A ; adjust BCD
MOV YEAR_BCD,A ; keep "year"
YYF: LJMP EX0_RET
;---------------------------------------
JMM: CJNE A,#02H,JDD ; "02" for adjusting "month"
;调节月
MOV A,MONTH_BCD ; take BCD of "month"
CJNE A,#12H,MM0 ; is December ?
MOV MONTH_BCD,#01H ; keep the first month
LJMP MMF
MM0: ADD A,#01H ; increase "month"
DA A ; adjust BCD
MOV MONTH_BCD,A ; keep "month"
MMF: LJMP EX0_RET
;---------------------------------------
JDD: CJNE A,#03H,AA1 ; "03" for adjusting "day"
LJMP BB1
AA1: LJMP ADH ;
BB1: MOV A,MONTH_BCD ; first, should take "month"
CJNE A,#02H,NFB ; is February ?
IFB: NOP
ACALL BCD_DIV4 ; BCD of "year in YEAR_BCD" divided by 4
MOV A,R3 ; remainder in R3
CJNE A,#00H,ANG ; "00" means leap year
ARN: MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#29H,D0A ; is up to 29 days in Feb.?
LJMP D0B
D0A: LJMP DDA
D0B: LJMP DD1
ANG: MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#28H,D0A ; is up to 28 days in Feb.?
LJMP DD1
NFB: NOP ; check "little/large" month
CJNE A,#04H,Y04 ; is April ?
LJMP AD1
Y04: CJNE A,#06H,Y05 ; is June ?
LJMP AD1
Y05: CJNE A,#09H,Y06 ; is September ?
LJMP AD1
Y06: CJNE A,#11H,Y07 ; is November ?
LJMP AD1
Y07: NOP ; for "large" month
MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#31H,D0A ; is up to 31 days ?
LJMP DD1
AD1: NOP ; for "little" month
MOV A,DAY_BCD ; take BCD of "day"
CJNE A,#30H,D0A ; is up to 30 days ?
DD1: MOV DAY_BCD,#01H ; keep the first day
LJMP DDF
DDA: ADD A,#01H ; increase "day"
DA A ; adjust BCD
MOV DAY_BCD,A ; keep "day"
DDF: LJMP EX0_RET
;---------------------------------------------------
JALAM: ;调整闹钟
MOV A,FLASH_FLAG ; take flag of un-flash/flash
NADH: CJNE A,#01H,NADM ; "03" for adjusting "hour"
MOV A,NHOUR_BCD ; take BCD of "hour"
CJNE A,#23H,NJH0 ; is up to 23 hours ?
MOV NHOUR_BCD,#00H ; keep the first hour
LJMP NJHF
NJH0: ADD A,#01H ; increase "hour"
DA A ; adjust BCD
MOV NHOUR_BCD,A ; keep "hour"
NJHF: LJMP EX0_RET
;-----------------------------------------
NADM: CJNE A,#02H,NADS ; "02" for adjusting "minute"
MOV A,NMINUTE_BCD ; take BCD of "minute"
CJNE A,#59H,NJM0 ; is up to 59 minutes ?
MOV NMINUTE_BCD,#00H ; keep the first minute
LJMP NJMF
NJM0: ADD A,#01H ; increase "minute"
DA A ; adjust BCD
MOV NMINUTE_BCD,A ; keep "minute"
NJMF: LJMP EX0_RET
NADS: MOV A,NSECOND_BCD ; take BCD of "second"
CJNE A,#59H,NJS0 ; is up to 59 seconds ?
MOV NSECOND_BCD,#00H ; keep the first second
LJMP NJSF
NJS0: ADD A,#01H ; increase "second"
DA A ; adjust BCD
MOV NSECOND_BCD,A ; keep "second"
NJSF: NOP
LJMP EX0_RET
;---------------------------------------------------
EX0_RET:NOP ;中断退出
POP PSW
POP ACC
RETI
;---------------------------------------------------
;---------------------------------------------------
; sub: INT1 interrupt
; 处理按键 K1,设置闪烁
EX1_INT:NOP ; revise flag(00 to 06) in FLASH_FLAG
PUSH ACC
PUSH PSW
JNB P3.2,EX1_RET ; check port INT0
LCALL DIS_DELAY ; re-bounce (with LED display)
;;K1 按键按下
NOP ; inhibit INT0 (use k1)
MOV A,DIS_FLAG
CJNE A,#03H,TIMER_START0 ;非设置闹钟开关模式
MOV A,ALAM_STATE
CPL A ;取非
ANL A,#01H ;保留最后
MOV ALAM_STATE,A ;设置闹钟开关
AJMP DI_START ;提示音后退出
;---------------------------------------------------
TIMER_START0:
MOV A,TIMER_FLAG
CJNE A,#01,FLASH_SHIFT ;非秒表模式
TIMER_START:
MOV A,TIMER_START_FLAG
CPL A
ANL A,#01H ;保留最低位
MOV TIMER_START_FLAG,A ;设置秒表开关
;---------------------------------------------------
DI_START:
CLR P2.0 ;按键滴一声
MOV DI_41H,#19H
DI_LOOPO:
MOV DI_40H,#0FFH
DI_LOOP:
DJNZ DI_40H,DI_LOOP
DJNZ DI_41H,DI_LOOPO
SETB P2.0
AJMP EX1_RET ;退出
;---------------------------------------------------
FLASH_SHIFT: ;进入切换闪烁
MOV A,FLASH_FLAG ; take flag of un-flash/flash
CJNE A,#00H,ED1 ; "00" 无闪烁
MOV FLASH_FLAG,#01H ; 设置 1,2 号数码管闪烁
SJMP EX1_RET
ED1: CJNE A,#01H,ED2 ; "01" 1,2 号闪烁中
MOV FLASH_FLAG,#02H ; 设置 3,4 号闪烁
SJMP EX1_RET
ED2: CJNE A,#02H,ED3 ; "02" 3,4 号闪烁
MOV FLASH_FLAG,#03H ; 设置 5,6 号闪烁
SJMP EX1_RET
ED3: MOV FLASH_FLAG,#00H ; 关闭所有闪烁
EX1_RET:NOP
POP PSW
POP ACC
RETI
;------------------------------------
; ---------------------------------------------
; 带显示延迟
D_CNT_DIS EQU 2AH
DIS_DELAY: MOV D_CNT_DIS,#10H ; or(#0BH)
DELAY_LOOP: LCALL DISPLAY ; with LED display
DJNZ D_CNT_DIS,DELAY_LOOP
RET
; -----------------------------------------------
; ----------------------------------------------------------
; sub: BCD division
; BCD 除法除 4
; 输出
; R3: 余数
; R2: 商
BCD_DIV4: MOV R0,YEAR_BCD ; dividend in BCD
MOV R1,#04H ; divider in BCD
MOV R2,#00H ; R2输出商
MOV A,R1
CPL A
ADD A,#9BH
MOV R1,A ; R1BCD 补码
MOV A,R0
ANL A,#0F0H ; BCD 高位
SWAP A
LP0: MOV R3,A ; BCD 码的余数
ADD A,R1
DA A
JNC LP1
INC R2
SJMP LP0
LP1: MOV A,R3
SWAP A
MOV R3,A
MOV A,R2
SWAP A
MOV R2,A ; 商的高位
MOV A,R0
ANL A,#0FH ; 年 BCD 的低位
ORL A,R3
LP2: MOV R3,A
ADD A,R1
DA A
JNC LP3
INC R2
SJMP LP2
LP3: NOP ; no rounding
RET
;----------------------------------------------
; ------------------------------------------------------
; 放在代码段的字模表
TAB:
DB 0c0H ; for "0"
DB 0f9H ; for "1"
DB 0a4H ; for "2"
DB 0b0H ; for "3"
DB 99H ; for "4"
DB 92H ; for "5"
DB 82H ; for "6"
DB 0f8H ; for "7"
DB 80H ; for "8"
DB 90H ; for "9"
TAB2: ;闹钟状态显示的字模
DB 0C0H ; "0"
DB 11001000B ; "N"
DB 10001110B ; "F"
DB 0FFH ; " "
DB 40H ; "0."
DB 07FH ; "."
DB 00001110B ; "F."
END

此文关键字:led数码管时钟,led数码管时钟程序

FPC柔性线路板 LED数码管显示屏 led触控方案开发