;初始化
P_Lcd equ P0 ;液晶lcd數據總線
pq equ p3 ;按鍵接口
pf bit p2.1 ;蜂鳴器接口
led bit p2.0 ;led燈指示接口
lcdrs bit p2.6 ;lcdrs=1選擇數據寄存器,lcdrs=0選擇指令寄存器
lcdrw bit p2.5 ;lcdrw=1進行讀操作,lcdrw=0進行寫操作
lcde bit p2.7 ;lcdep由1-->0 時,液晶模塊執行命令
sclk bit p3.6 ;時鐘芯片時鐘線引腳
io bit p3.4 ;時鐘芯片數據傳輸線引腳
rst bit p3.5 ;時鐘芯片復位線引腳
IsSheZhi bit 30h ;設置狀態標示位
BJ bit 31h ;比較標示位
QH bit 32h ;切換標示位
bs bit 33h ;報時功能標示位
cxbs bit 34h ;執行報時標志位
sec equ 50h
min equ 51h
hour equ 52h
day equ 53h
week equ 54h
month equ 55h
year equ 56h
KeyCode equ 57h ;按鍵1功能子程序序號存儲地址
jiepai equ 58h ;存放報時聲音的節拍常數
chuzhi equ 59h ;報時開始秒時間常數
shengshu equ 5ah ;存放報時聲數
DspBuf equ 60h ;當前時間拆字后存儲首地址
dspba equ 70h ;鬧鐘時間首地址
org 0h
ljmp main
org 00bh
ljmp sub1
org 01bh
ljmp sub2
org 30h
;主程序
main:
clr IsSheZhi
clr QH
setb BJ
setb bs
setb cxbs
mov KeyCode,#00h
mov sp ,#30h
mov year,#16h ;為當前時間賦初值
mov month,#06h
mov week,#4h
mov day,#30h
mov hour,#00h
mov min,#00h
mov sec,#00h
mov DspBuf-1,#0h
mov DspBuf-2,#02h
mov jiepai,#80h ;設置節拍常數
mov chuzhi,#00h ;設置1秒時開始報時
mov dspba+0,#00h ;為鬧鐘時間賦初值
mov dspba+1,#09h
mov dspba+2,#0h
mov dspba+3,#0h
mov TH0,#0ffh
mov TL0,#0ffh
mov TH1,#0ffh
mov TL1,#0ffh
mov IE,#8aH
mov TMOD,#11h
setb pf
acall lcd_init ;調LCM的初始化程序
lcall word ;把自創字符寫入CGRAM的子程序
lcall set1302 ;DS1302初始化
mainloop:
jb IsSheZhi, SheZhi ;判斷是否處于設置狀態,處于設置狀態則跳轉
lcall get1302 ;調讀時間子程序
lcall chaizi
lcall display ;調顯示子程序,顯示當前時間與溫度
SheZhi:
jb BJ,xq ;判斷鬧鐘功能是否開啟,未開啟則跳轉
lcall bijiao ;調比較子程序,比較當前時間與鬧鐘時間
xq:
lcall anjian ;按鍵掃描
jb bs,bs_1
lcall zhengshi ;判斷當前時間是否是整時,即能否報時
bs_1:
jb cxbs,cx_1
lcall baoshi ;執行報時功能
cx_1:
sjmp mainloop
;液晶顯示初始化設定
lcd_init:
mov a,#01h ;清除LCD的顯示內容(清屏)
acall LcdWrCmd
mov a,#10 ;10ms延時
acall delay
mov a,#38h ;顯示模式設置(使用8位數據,顯示兩行,使用5*7的字型)
acall LcdWrCmd
mov a,#10
acall delay
mov a,#0ch ;顯示開及光標設置(顯示器開,光標關,字符不閃爍)
acall LcdWrCmd
mov a,#10
acall delay
mov a,#06h ;顯示光標移動設置(字符不動,光標自動右移)
acall LcdWrCmd
mov a,#10
acall delay
ret
;LCM命令嵌入
LcdWrCmd:
clr LCDRW
clr LCDRS
mov P_Lcd, A
mov a,#6
acall delay
setb LcdE
clr LcdE
ret
;LCM數據輸入
LcdWrDat:
setb LCDRS
clr LCDRW
mov P_Lcd, A
mov a,#6
acall delay
setb LcdE
clr LcdE
ret
;延時子程序
delay:
mov r7,a ;設置a為自定義變量,可省去其他延時程序的編寫
d2: mov r6,#250 ;設置1ms延時
d1:
nop
nop
djnz r6,d1
djnz r7,d2
ret
;ds1302初始化程序set1302
set1302:
mov a,#8eh ;寫ds1302控制寄存器地址
mov b,#00h ;允許寫操作,將WP位設置為低電平
lcall clockwr
mov a,#8ch ;寫年初值
mov b,year
lcall clockwr
mov a,#88h ;寫月初值
mov b,month
lcall clockwr
mov a,#8ah ;寫星期初值
mov b,week
lcall clockwr
mov a,#86h ;寫日期初值
mov b,day
lcall clockwr
mov a,#84h ;寫時初值
mov b,hour
lcall clockwr
mov a,#82h ;寫分初值
mov b,min
lcall clockwr
mov a,#80h ;寫秒初值
mov b,sec
lcall clockwr
ret
;讀時間子程序get1302
get1302:mov a,#81h ;讀秒
lcall clockrd
mov sec,a
mov a,#83h ;讀分
lcall clockrd
mov min,a
mov a,#85h ;讀時
lcall clockrd
mov hour,a
mov a,#87h ;讀日
lcall clockrd
mov day,a
mov a,#8bh ;讀星期
lcall clockrd
mov week,a
mov a,#89h ;讀月
lcall clockrd
mov month,a
mov a,#8dh ;讀年
lcall clockrd
mov year,a
ret
;ds1302讀子程序
clockrd:clr rst ;rst先設置低電平,再設置高電平,起到去亂碼作用
clr sclk ;sclk置為低電平
setb rst ;rst置為高電平,選通DS1302
mov r7,#8 ;串行移位傳送次數
rds1:
rrc a
mov io,c ;輸出一位寄存器讀地址
setb sclk ;發串行脈沖
nop
nop
clr sclk ;sclk置為低電平
djnz r7,rds1
nop ;延時,防后面串行讀數據丟失
nop
setb io ;8位地址輸出完畢,IO設置為輸入端口
mov r7,#8
rds2:
mov c,io ;讀入一位數據
rrc a
setb sclk ;發串行脈沖
nop
nop
clr sclk
djnz r7,rds2
clr rst
setb sclk
ret
;ds1302寫數據子程序
clockwr:
push acc ;設置堆棧,入棧
push b
clr rst
clr sclk
setb rst ;選通DS1302
mov r7,#8
wrs1:
rrc a
mov io,c ;輸出一位寄存器寫地址
clr sclk ;發串行輸出脈沖
setb sclk
djnz r7,wrs1
nop
mov a,b ;將待寫入數據送A
mov r7,#8
wrs2:
rrc a
mov io,c ;經IO輸出一位數據
clr sclk
setb sclk
djnz r7,wrs2
pop b ;出棧
pop acc
ret
;顯示設置—— 分配時間顯示空間
chaizi:
mov a,year ;拆年
mov r0,#60h
acall hex2bcd
mov a,month ;拆月
mov r0,#62h
acall hex2bcd
mov a,day ;拆日期
mov r0,#64h
lcall hex2bcd
mov a,week;
mov 66h,a
mov a,hour ;拆時
mov r0,#67h
lcall hex2bcd
mov a,min
mov r0,#69h ;拆分
lcall hex2bcd
mov a,sec
mov r0,#6bh ;拆秒
acall hex2bcd
ret
;顯示設置—— 采用除法指令實現的拆字子程序
hex2bcd:
mov b,a
anl a,#0f0h
swap a
mov @r0,a
mov a,b
anl a,#0fh
inc r0
mov @r0,a
ret
;顯示設置——連續顯示相鄰的兩字節
LcdDspBuf:
mov A, @R0
orl a,#30h
acall LcdWrDat
inc R0
djnz R2, LcdDspBuf
ret
;顯示設置——自創字符寫入CGRAM的子程序
word:
mov a,#40h
lcall LcdWrCmd
mov r5,#40
mov dptr,#tab1
mov r4,#0
nextt:
mov a,r4
movc a,@a+dptr
lcall LcdWrDat
inc r4
djnz r5,nextt
ret
tab1:
db 08h,0fh,12h,0fh,0ah,1fh,02h,00h;年
db 0fh,09h,0fh,09h,0fh,09h,13h,00h;月
db 0fh,09h,09h,0fh,09h,09h,0fh,00h;日
db 06h,0fh,1fh,0fh,07h,1bh,19h,00h;顯示鬧鐘功能開啟標示符號
db 15h,15h,04h,11h,1bh,1fh,0eh,00h;顯示報時功能開啟標示符號
;進入鬧鐘功能設置顯示
display_nz:
mov a,#0c2h
acall LcdWrCmd ;確定鬧鐘時間的首地址
mov R0, #dspba+0
mov R2, #2
acall LcdDspBuf ;顯示時
mov a,#3ah ;顯示分隔符號
acall LcdWrDat
mov R0, #dspba+2
mov R2, #2
acall LcdDspBuf ;顯示時
jb BJ,XT ;判斷鬧鐘功能是否開啟
mov a,#0c0h
acall LcdWrCmd
mov a,#03h ;顯示鬧鐘功能開啟標示符號
acall LcdWrDat
XT: ret
;正常顯示設置
display:
mov a,#80h
acall LcdWrCmd ;指明顯示的首地址
mov R0, #DspBuf-2
mov R2, #2
acall LcdDspBuf ;顯示年份前兩位
mov R0, #DspBuf+0
mov R2, #2
acall LcdDspBuf ;顯示年后兩位
mov a,#00h ;顯示漢字年
acall LcdWrDat
mov R0, #DspBuf+2
mov R2, #2
acall LcdDspBuf ;顯示月份
mov a,#01h ;顯示漢月字年
acall LcdWrDat
mov R0, #DspBuf+4
mov R2, #2
acall LcdDspBuf ;顯示日期
mov a,#02h ;顯示漢日字年
acall LcdWrDat
mov a,#8ch ;w指明星期的首地址
acall LcdWrCmd
mov a,#57h
acall LcdWrDat ;顯示w
mov a,#3ah ;顯示分隔符號
acall LcdWrDat
mov a,66h ;顯示星期值
orl a,#30h
acall LcdWrDat
jb bs,XtT ;判斷報時功能是否開啟
mov a,#04h ;顯示報時功能開啟標示符號
acall LcdWrDat
XtT:
mov a,#0c2h
acall LcdWrCmd ;確定地址
mov R0, #DspBuf+7
mov R2, #2
acall LcdDspBuf ;顯示時
mov a,#3ah ;顯示分隔符號
acall LcdWrDat
mov R0, #DspBuf+9
mov R2, #2
acall LcdDspBuf ;顯示分
mov a,#3ah ;顯示分隔符號
acall LcdWrDat
mov R0, #DspBuf+11
mov R2, #2
acall LcdDspBuf ;顯示秒
jb BJ,xyz ;判斷鬧鐘功能是否開啟
mov a,#0c0h
acall LcdWrCmd
mov a,#03h ;顯示鬧鐘功能開啟標示符號
acall LcdWrDat
xyz: ret
ret
;按鍵處理
anjian:
mov a,pq
anl a,#0fh
cjne a,#0fh,kp1
ret
kp1:
mov a,#5 ;設置5ms延時,起到去抖掃描
acall delay
mov a,pq
anl a,#0fh
cjne a,#0fh,kp2
ret
kp2:
JB pq.0,KK1
jnb pq.0,$
lcall anjian1
ret
KK1:
JB pq.1,KK2
jnb pq.1,$
lcall anjian2
ret
KK2:
JB pq.2,KK3
jnb pq.2,$
lcall anjian3
ret
KK3:
JB pq.3,KK4
jnb pq.3,$
lcall anjian4
KK4: ret
;該子程序根據的KeyCode內容轉入各對應的操作程序中
anjian1:
mov a,KeyCode
mov dptr,#tab5
add a,KeyCode
jnc nadd
inc dph ;KeyCode乘2進位加到DPH中
nadd:
mov r3,a ;暫存
movc a,@a+dptr ;取地址高八位
xch a,r3 ;保存轉移地址高8位
inc a
movc a,@a+dptr ;取地址低八位
mov dpl,a ;置轉移地址低8位
mov dph,r3
clr a
jmp @a+dptr
ret
tab5: dw opr00,opr01,opr02 ,opr03 ;16位轉移地址表的首地址
;進入時間調整設置狀態
opr00:
setb IsSheZhi
mov r1,#DspBuf+12 ;編輯時間從秒個位開始
mov a,#0fh
acall LcdWrCmd
mov a,#0c9h
acall LcdWrCmd
mov KeyCode,#02h
ret
;進入設置鬧鐘時間狀態
opr01:
setb IsSheZhi
mov r1,#dspba+3 ;編輯時間從分個位開始
mov a,#0fh
acall LcdWrCmd
mov a,#0c6h
acall LcdWrCmd
mov KeyCode,#03h
ret
;把所設置的時間作為當前時間
opr02:
mov a,DspBuf+11
swap a
mov b,DspBuf+12
orl a,b
mov sec,a ;存秒
mov a,DspBuf+9
swap a
mov b,DspBuf+10
orl a,b
mov min,a ;存分
mov a,DspBuf+7
swap a
mov b,DspBuf+8
orl a,b
mov hour,a ;存時
mov a,DspBuf+4
swap a
mov b,DspBuf+5
orl a,b
mov day,a ;存日期
mov week,DspBuf+4; ;存星期值
mov a,DspBuf+2
swap a
mov b,DspBuf+3
orl a,b
mov month,a ;存月
mov a,DspBuf+0
swap a
mov b,DspBuf+1
orl a,b
mov year,a ;存年
lcall set1302 ;為當前時間
cpl IsSheZhi ;退出設置狀態
mov a,#0ch ;開啟 閃動
acall LcdWrCmd
mov KeyCode,#00h
ret
;把所設置的時間作為鬧鐘時間
opr03:
mov a,#0c0h
acall LcdWrCmd
mov a,#03h ;顯示鬧鐘功能開啟標示符號
acall LcdWrDat
mov a,#0ch ;撤銷閃動
acall LcdWrCmd
clr IsSheZhi ;退出設置狀態
mov KeyCode,#00h
clr QH
clr BJ ;開啟鬧鐘功能
ret
anjian2:
mov a, KeyCode
clr c
subb a,#02h
jc ppr1 ;判斷鐘是否處于設置狀態,不是則跳
jb QH, opr1a
mov a,r1
clr c
subb a,#5eh
mov dptr,#taba4
movc a,@a+dptr
mov b,a
inc @r1
mov a,@r1
cjne a, b,ppra1
mov @r1,#0
ppra1:
lcall www ;掃描當前時間編輯位
ret
taba4: db 0ah,0ah,0ah,0ah,02h,0ah,04h,0ah,08h,03h,0ah,06h,0ah,06h,0ah;當前時間各編輯位極大值表
opr1a:
mov a,r1
clr c
subb a,#70h
mov dptr,#taba6
movc a,@a+dptr
mov b,a
inc @r1
mov a,@r1
cjne a,b,ppra1k
mov @r1,#0
ppra1k:
lcall wwwa ;掃描鬧鐘時間編輯位
ret
taba6 : db 03h,0ah,06h,0ah ;鬧鐘時間各編輯位極大值表
ppr1: cpl IsSheZhi
cpl QH ;切換屏幕
jnb QH,TY
mov a,#01h ;清屏幕
acall LcdWrCmd
mov KeyCode,#01h ;指明按鍵1下次執行的功能子程序
acall display_nz ;顯示鬧鐘時間
ret
TY: mov KeyCode,#00h ;指明按鍵1下次執行的功能子程序
ret
;按鍵3處理設計
anjian3:
mov a, KeyCode
clr c
subb a,#02h
jc ajppr2 ;判斷鐘是否處于設置狀態,不是跳
jb QH, opr2b ;判斷鐘是否處于編輯鬧鐘時間狀態
dec r1 ;移位
cjne r1,#DspBuf-3,ppr2a
mov r1,#DspBuf+12
ppr2a:
lcall www ;掃描當前時間編輯位
ret
opr2b:
dec r1 ;移位
cjne r1,#dspba-1,ppr2ak
mov r1,#dspba+3
ppr2ak:
lcall wwwa ;掃描鬧鐘時間編輯位
ret
ajppr2:
mov a,#01h ;清除屏幕
acall LcdWrCmd
cpl BJ
JB BJ,TY_1
ret
TY_1:
clr tr0
setb pf
ret
;按鍵4處理設計
anjian4:
mov a, KeyCode
clr c
subb a,#02h
jc anjian4_1 ;判斷鐘是否處于設置狀態,否則跳
clr IsSheZhi
mov KeyCode,#00h
mov a,#0ch ;取消閃動
acall LcdWrCmd
ret
anjian4_1:
mov a,#01h ;清除屏幕
acall LcdWrCmd
cpl bs ;控制報時功能
JB bs,TY_2
ret
TY_2:
clr tr1
setb pf
ret
;掃描當前時間編輯位
www:
mov a,r1
clr c
subb a,#5eh
mov dptr,#tab4
movc a,@a+dptr
mov b,a ;暫存 閃動位置
acall LcdWrCmd ;寫入編輯位的位置
mov a,#10 ;設置10ms延時
acall delay
mov a,@r1
orl a,#30h
acall LcdWrDat ;寫入數據
mov a,b ;確定閃動位置
acall LcdWrCmd
ret
;掃描鬧鐘時間編輯位
wwwa:
mov a,r1
clr c
subb a,#70h
mov dptr,#tab6
movc a,@a+dptr
mov b,a ;暫存 閃動位置
acall LcdWrCmd ;寫入編輯位的位置
mov a,#10 ;設置10ms延時
acall delay
mov a,@r1
orl a,#30h
acall LcdWrDat ;寫入數據
mov a,b ;確定閃動位置
acall LcdWrCmd
ret
tab4:db 80h,81h,82h,83h,85h,86h,88h,89h,8eh,0c2h,0c3h,0c5h,0c6h,0c8h,0c9h
;當前時間各編輯位在LCD上的位置表
tab6:db 0c2h,0c3h,0c5h,0c6h ;鬧鐘時間各編輯位在LCD上的位置表
;比較子程序
bijiao:
mov a, dspba+0
cjne a,DspBuf+7,bijiao_1 ;比較當前時間與鬧鐘時間的時十位
mov a, dspba+1
cjne a,DspBuf+8,bijiao_1 ;比較當前時間與鬧鐘時間的時個位
mov a, dspba+2
cjne a,DspBuf+9,bijiao_1 ;比較當前時間與鬧鐘時間的分鐘十位
mov a, dspba+3
cjne a,DspBuf+10,bijiao_1;比較當前時間與鬧鐘時間的分鐘個位
setb TR0
ret
bijiao_1:
clr TR0
setb pf
clr led
ret
; 整點報時子程序
zhengshi:
mov a,sec ;判斷當前時間是否是整時,即能否報時
jnz js ;判斷是否位0秒
mov a,min
jnz js ;判斷是否位0分
mov a,DspBuf+7
mov b,#10
mul ab
add a,DspBuf+8 ;;BCD碼轉化位二進制
cjne a,#13,$+3 ;判斷時是否超過12小時
jc ss
clr c
subb a,#12
ss:
mov shengshu,a
cpl bs ;暫時關閉判斷整時
clr cxbs ;開始報時
js: ret
;執行報時baoshi
baoshi: ;執行報時功能
mov a,chuzhi
cjne a,sec,ltt
setb tr1
mov a,chuzhi
add a,#01h
da a
mov chuzhi,a
djnz shengshu,ltt
cpl bs
setb cxbs
mov chuzhi,#00h
ltt: ret
;蜂鳴器響功能設置
sub1:
cpl pf
reti
sub2:
mov th1,#0f8h ;設置報時聲的音色
cpl pf
djnz jiepai,sub2_1
mov jiepai,#80h ;設置節拍常數
clr tr1
sub2_1: reti
end
|