该数字钟可实现精度误差≤ 1S/天的变精度时钟,并能方便地调节时钟、时间、定时时间等,秩序结构清晰,一看即懂,还可以配编附加一些功能如计数器功能等(扩展键盘)。
led_data equ p2 ;数码管定义
key1 bit p3.5 ;按键定义
key2 bit p3.6
key3 bit p3.7
key equ 56h
time_h equ 57h ;定时初值高位
time_l equ 58h ;低位
t_h equ 60h ;时分秒对应的地址
t_s equ 61h
t_m equ 62h
time equ 63h ;时钟计数单元
timer_h equ 64h ;定时时单元
timer_m equ 65h ;定时分单元
timset bit 00h ;设置时间标志
disstart equ 70h ;显示单元首地址
int_data equ 45h ;中断数据地址
count_data equ 44h ;计数单元地址
timer_data equ 43h ;定时地址
; ************** 以上为预定义部分
; ************** 以下程序开始
org 00h ;程序开始地址
jmp main ;跳转到代码开始处
org 1bh ;定时器 T1 中断服务程序入口
jmp tim1
org 030h ;主程序开始的地址 30H
main:mov sp,#30h ;首先定义堆栈
lcall rest ;初始化
lcall pro_set ;设置定时器开始工作
lpp:lcall time_set ;接受用户设置时间
lcall timer ;时钟处理
lcall time_pro ;时间格式处理,码型变化等
lcall time_display ;显示
jmp lpp
; *************** 定时器 T1 中断服务程序 ****
tim1:clr tr1 ;首先停止定时操作
mov th1,time_h ;
mov tl1,time_l
inc time ;自增
mov a,time ;取得溢出次数
cjne a,#20,retend ;如果满20此表示到 1 秒
cpl p1.0 ;取反p1.0,p1.1指示秒钟
cpl p1.1
mov time,#00h ;重新开始等待1秒
inc t_s ;秒单元加1
retend:setb tr1 ;定时开始
reti ;中断返回
; ***************** 设置定时器初始化,定时时间为 50ms ****
pro_set:mov dptr,#0000h ;数据指针清零
mov tmod,#10h ;设置定时器1工作在方式1
mov time_h,#3ch ;计算定时50ms需要的初值
mov th1,time_h ;保存高位
mov time_l,#0c1h ;低位
mov tl1,time_l ;保存低位
setb ea ;总的中断允许
setb et1 ;定时器1允许
setb tr1 ;定时器1开始运行
ret ;返回
; ************ time_display 程序主要为显示时间值用 *************
time_display: mov r0,#disstart ;取得显示单元首地址
mov r1,#01h ;从第一个数码管开始
mov r2,#06h ;共6个数码管
dislp:mov led_data,@r0 ;获得当前单元数据
inc r0 ;指向下一个单元
mov p0,r1 ;数码显示
mov a,r1 ;为下一个数准备
rl a ;下一个单元
mov r1,a ;保存
lcall delay5ms ;为了保证数码管亮度,
;但要防止闪烁,延时5ms
djnz r2,dislp ;重复显示,直到全部数据刷新过
ret ;返回
; ******* time_pro 时间处理,主要为 bcd码转换,查表 ***********
time_pro:lcall bcd ;BCD码转换
mov r0,#disstart ;获得显示单元首地址
mov r2,#06h ;需要转换的个数
prlp:mov a,@r0 ;取得当前需要转换的数据
mov dptr,#tab_nu ;获得表头
movc a,@a+dptr ;获得转换后的数据
mov @r0,a ;存回去
inc r0 ;指向下一个
djnz r2,prlp ;重复转换,直到6个全部完成
ret ;返回
; **************** 码型变换 ****************************************
bcd:mov r0,#disstart ;获得首地址
mov a,t_s ;获得待转化的低位
mov b,#10 ;转化进制,如果要进行十进制转换 改为 10
div ab ;计算 A/B
mov @r0,b ;第一位转换完毕,保存低位转化后的数据
inc r0 ;自增
mov @r0,a ;保存高位
inc r0 ;取第二个数据地址
mov a,t_m ;获得第二个需要转换的数据
mov b,#10 ;十六进制
div ab ;计算
mov @r0,b ;存低位
inc r0
mov @r0,a ;存高位
inc r0 ;第三位
mov a,t_h ;获得数据
mov b,#10 ;十六进制
div ab ;计算
mov @r0,b ;存低位
inc r0
mov @r0,a ;存高位
ret ;完毕,返回
;=====================================
;Define area
debounce_num equ 16
scl equ pb.1 ;serial clock data input
sda equ pb.0 ;Serial data I/O
read_out equ [3ch] ;write register
write_in equ [3dh] ;Read register
word_address equ [3eh]
data_8 equ [3fh]
;---------------------------
;---------------------------
;Define Macro
;Delay Macro,delay 100us
d_1 macro
local label
mov a,64h
mov delay,a
label:
sdz delay
jmp label
endm
;*************************************************************
SAMPLE .SECTION 'DATA'
;; --- Temp RAM ---
a_sr10 db ? ;;WORK Temp Register
a_sr11 db ? ;;
temp_num db ?
;;------CODE RAM---------
array_data db 8 dup (?) ;;8 byte password
;;--------- Program RAM --------
column db ? ;;Scan Key column Step Number
key_code0 db ? ;;Save Previous Key Number
key_code db ? ;;Scan Key Number
col_value db ? ;;Read on column value to a_COL_value
kd_temp db ? ;;Key Debounce Check Times
nkd_temp db ? ;;Key Release Confirm Times
Key_data db ? ;;PA temp register
Key_data1 db ?
delay db ?
delay0 db ?
delay1 db ?
t_count db ?
t_count1 db ?
release_num db ? ;;count release key
;;--- User FLAG define ---
fg_SendActive dbit ;;VALIDITY KEY Flag
fg_PressRec dbit ;;Check Column Multi_Key Flag
fg_repeat dbit ;;REPEAT KEY Flag
fg_Multi_Key dbit ;;INVALID KEY Flag
release_flg dbit ;;release flag
flg_chang_key dbit
flg_chang_personal dbit
flg_chang_manage dbit
flg_chang dbit
;*************************************************************
code .section at 0 'code'
org 00h
START:
set pa
mov a, 20H
mov mp0, a
mov a, 50H
CLR_RAM:
clr r0
inc mp0
sdz acc
jmp clr_ram
mov a,070h
mov t_count,a
mov a,050h
mov t_count1,a
mov a,07fh
mov release_num,a
ini_clock:
mov a, offset personal_clock
mov tblp,a
mov a,00h ;write 00H to eeprom address,it is personal password
mov word_address,a
ini_personal_clock:
tabrdl write_in
call ht24_write
inc TBLP
inc word_address
mov a,offset personal_clock+8
xor a,TBLP
sz acc
jmp ini_personal_clock
mov a, offset manage_clock
mov tblp,a
mov a,010h ;write 10H to eeprom address,it is administration password
mov word_address,a
ini_manage_clock:
tabrdl write_in
call ht24_write
inc TBLP
inc word_address
mov a,offset manage_clock+8
xor a,TBLP
sz acc
jmp ini_manage_clock
clr pa.1
clr pa.2
mov a, offset array_data
mov mp0, a
;@*********** Polling System Event ***********
MAIN_PROC:
call scan_key_proc ;SCAN KEY PROCEDURE
mov a,0bh ;* key
xor a,key_code
sz acc
jmp $+2
jmp release_proc
sz fg_repeat
jmp sleep
sz fg_Multi_Key ;Check Invalid Key
jmp main_proc ;
mov a,0ch ;red key
xor a,key_code
sz acc
jmp $+4
set flg_chang_key
set flg_chang_personal
jmp main_proc
mov a,0ah ;"0" key
xor a,key_code
sz acc
jmp $+4
clr flg_chang_personal
set flg_chang_manage
jmp main_proc
sz key_code ;Check NO Key Press
jmp judge
jmp sleep
judge:
set pa.1
call delay30ms
clr pa.1
mov a,070h
mov t_count,a
mov a,050h
mov t_count1,a
sz release_flg
jmp release_proc ;;deal with “*” key
sz flg_chang_key
jmp manage_code ;;input mange password
sz flg_chang_manage
jmp chang_manage_proc ;;change mange password
sz flg_chang_personal
jmp chang_personal_proc ;;change personal password
jmp personal_code ;;input personal password
DELAY:
PUSH PSW
SETB RS0
MOV R7,#50
D1: MOV R6,#50
D2: DJNZ R6,$
DJNZ R7,D1
POP PSW
RET
DISPTAB: DB 28H,7EH,0a4H,64H,72H,61H,21H,7CH,20H,60H
D60MS:
PUSH PSW
SETB RS0
MOV R7,#150
D61:
MOV R6,#200
DJNZ R6,$
DJNZ R7,D61
POP PSW
RET
END