?? 164_wnl.asm
字號:
;2051帶農歷顯示的萬年歷最簡電路
;帶74L164三片
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AT89C2051日歷程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;轉載請署名來自 www.01mcu.com 否則謝絕轉載
time_week data 52h ;星期存放單元
time_year data 5dh ;年份低兩位存放單元(bcd碼)
time_month data 5eh ;月份存放單元(bcd碼)
time_data data 5fh ;日存放單元(bcd碼)
yearh data 36h ;年份高兩位
year data 35h ;年份低兩位存放單元(bcd碼)
month data 34h ;月份存放單元(bcd碼)
day data 33h ;日存放單元(bcd碼)
hour data 32h ;時存放單元(bcd碼)
minute data 31h ;分存放單元(bcd碼)
sec data 30h ;秒存放單元(bcd碼)
aaa bit p3.0 ;顯示位(74ls164 數據)
bbb bit p3.1 ;顯示脈沖(74ls164時鐘)
aa bit p3.3 ;時間調整按鈕
bb bit p3.4 ;加1調整
cc bit p3.5 ;鬧鐘調整
bl bit p3.2 ;鬧鐘輸出
bz1 bit 21h.0
times data 20h ;調時標志
com data p1 ;段碼數據
; 定時器T0溢出周期為40MS,T0為秒計數用
;P1口 為字符輸出口,采用共陽顯示管。
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 中斷入口程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
ORG 0000H ;程序執行開始地址
LJMP START ;跳到標號START執行
ORG 0003H ;外中斷0中斷程序入口
RETI ;外中斷0中斷返回
ORG 000BH ;定時器T0中斷程序
LJMP INTT0 ;跳至INTTO執行
ORG 0013H ;外中斷1中斷程序入口
RETI ;外中斷1中斷返回
ORG 001BH ;定時器T1中斷程序入口
RETI
ORG 0023H ;串行中斷程序入口地址
RETI ;串行中斷程序返回
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START: ;主 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov r0,#30h ;清30H-38H共11個內存單元
mov r7,#9 ;9個字節
cleete:
mov @r0,#00h ;www.01mcu.com
inc r0
djnz r7,cleete
mov times,#00h ;清調時標志
mov tmod,#01h ;設T0為16位定時器
mov tl0,#0c0h ;40ms定時初值(T0計時用)
mov th0,#63h ;40ms定時初值
mov sec,#0
mov minute,#0h
mov hour,#0h
mov day,#01h
mov month,#01h
mov year,#01h
mov yearh,#20h
setb ea ;總中斷開放
setb et0 ;允許T0中斷
setb tr0 ;開啟T0定時器
mov r4,#19 ;1秒定時用(40ms×25)
START1:
call disp ;調用顯示子程序
jnb aa,setmm1 ;P3.3口為0時轉時間調整程序
jmp start1 ;P3.3口為1時跳回START1
SETMM1:
call setmm ;調時間調整程序SETMM
jmp start1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SETMM: ;時間調整程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
call disp
call disp
jb aa,setmmo ;是干擾跳過
setmm2:
jnb aa,setmm3
clr et0
clr tr0 ;關t0中斷
mov sec,#0 ;秒清零
mov times,#01h ;分開始調整
mov r0,#minute ;
setmm4:
nop
inc22:
call offl ;滅顯示
call inc11 ;加調整
call disp
jb aa,inc22
call disp
jb aa,inc22
inc r0
mov a,times
rl a
mov times,a
jnb times.5,setmm4 ;繼續調整下一數據
setmm12:
jnb aa,setmm11
setmmo:
setb tr0
setb et0 ;調整完成開始計時
ret
setmm11:
call disp
jmp setmm12
setmm3:
call disp
jmp setmm2 ;避免調整時無顯示
inc11:
mov r3,#40
inc111:
mov a,@r0
jb bb,inc17
add a,#1 ;加1
da a
call inc000 ;數據比較
inc13:
jnb bb,inc14
inc17:
mov @r0,a ;存入調整后的數據
call disp
djnz r3,inc111
ret
inc14:
call disp
jmp inc13
offl: ;滅顯示
mov 22h,@r0
mov r6,#10
off1:
mov r7,#10
off2:
mov @r0,#0aah ;放入熄滅碼
call disp
djnz r7,off2
djnz r6,off1
mov @r0,22h
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
inc000: ;比較子程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jb times.0,inc001 ;分比較
jb times.1,inc002 ;時比較
jb times.2,inc003 ;日比較
jb times.3,inc004 ;月比較
jb times.4,inc005 ;年比較
jmp incout ;完成www.01mcu.com
inc005:
cjne a,#99h,incout
mov a,#00h ;超過99年為00年
jmp incout
inc004:
cjne a,#13h,incout
mov a,#01h ;超過12月為1月
jmp incout
inc003:
cjne a,#32h,incout
mov a,#01h ;超過31天為1日
jmp incout
inc002:
cjne a,#24h,incout
mov a,#00h ;超過23時為0時
jmp incout
inc001:
cjne a,#60h,incout
mov a,#00h ;超過59分為0分
incout:
ret ;返回
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INTT0: ;1秒計時程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push acc ;累加器入棧保護
push psw ;狀態字入棧保護
orl tl0,#0c0h ;低8位初值修正
mov th0,#63h ;高8位初值修正
djnz r4,clke111 ;25次中斷未到
jmp loop11
clke111:
jmp clke
loop11:
mov r4,#19h ;25次中斷到(1秒)重賦初值
mov a,sec ;調整秒
add a,#1
da a
mov sec,a
cjne a,#60h,clke99 ;整分否
mov sec,#0 ;清秒
mov a,minute ;調整分
add a,#1
da a
mov minute,a
clk0:
cjne a,#60h,clke ;整點否
mov minute,#0 ;清分
mov a,hour ;調整時
add a,#1
da a
mov hour,a
cjne a,#24h,clke ;零點否
mov hour,#0 ;清時
mov a,day ;調整日期
add a,#1
da a
mov day,a
mov a,month ;查閱本月最大日期
inc a
movc a,@a+pc
sjmp clk1
db 31h,28h,31h ;對應月份編碼:01h,02h,03h
db 30h,31h,30h ;對應月份編碼:04h,05h,06h
db 31h,31h,30h ;對應月份編碼:07h,08h,09h
db 00h,00h,00h ;對應無效月份編碼:0ah,0bh,0ch
db 00h,00h,00h ;對應無效月份編碼:0dh,0eh,0fh
db 31h,30h,31h ;對應月份編碼:10h,11h,12h
clk1:
clr c
subb a,day
jnc clke ;本月未滿
mov a,month
cjne a,#2,clk3 ;是二月
mov a,year
anl a,#13h ;保留年份中非4的整數部分
jnb acc.4,clk2
add a,#2
clk2:
anl a,#3 ;能否被4整除
jnz clk3 ;非閏年
mov a,day
xrl a,#29h
jz clke ;閏年二月可以有29日
clk3:
mov day,#1 ;調整到下個月的1日
mov a,month
add a,#1
da a
mov month,a
cjne a,#13h,clke
mov month,#1 ;調整到下一年的一月份
mov a,year ;調整年份
add a,#1
da a
mov year,a
clke99:
call CONvert ;農歷轉換子程序
clke: ;時鐘調整完畢,處理其它定時任務
pop psw
pop acc
reti ;完成
;;;;;;;;;;;;;;;;;;;;
disp: ;顯示寄存器處理
;;;;;;;;;;;;;;;;;;;;
push psw
push acc
mov 23h,r0 ;保存r0
disp99:
mov r1,#40h ;顯示寄存器首址
mov r0,#30h ;待處理寄存器首址
mov r2,#9 ;處理n次
disp1:
mov a,@r0 ;低寄存器1內容存入a
anl a,#0fh
mov @r1,a ;將a的值存入顯示寄存器1
mov a,@r0 ;低寄存器1內容存入a
swap a
anl a,#0fh
inc r1 ;r1地址加1
mov @r1,a ;將A的值存入顯示寄存器2
djnz r2,disp2 ;處理完n次,沒有地址加1
call display
mov r0,23h ;www.01mcu.com
pop acc
pop psw
ret
disp2:
inc r1
inc r0
jmp disp1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
display: ;顯示程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 顯示數據在40H-51H單元內,用19位LED共陽數碼管顯示,P1口輸出段碼數據,
;每個LED數碼管亮1MS;時間再逐位循環。
mov r1,#40h ;指向顯示數據首址
mov r5,#19 ;顯示19個數據
setb aaa
play:
setb bbb
nop
clr bbb ;移一位
clr aaa ;清零
mov a,@r1 ;取顯示數據到A
mov dptr,#tab ;取段碼表地址
movc a,@a+dptr ;查顯示數據對應段碼
mov com,a ;段碼放入P1口
call dl1ms ;顯示1ms
mov com,#0ffh ;P1口復位
djnz r5,play1 ;www.01mcu.com
clr bbb
setb aaa
ret ;返回
play1:
inc r1 ;顯示下一位
jmp play
TAB:
DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,0a3h,8eh,0abh
;共陽段碼表 "0""1""2" "3""4""5""6""7" "8""9""不亮""o""f""n";后面三個在調鬧鐘時用
dl1ms:
mov 25h,r7
mov 24h,r6 ;保存r6,r7
mov r7,#20
ds1:
mov r6,#10
djnz r6,$
djnz r7,ds1
mov r7,25h
mov r6,24h
ret
;下面還有
;下面的程序是我在網上找到的并做了刪減及修改了一點,我可沒這個能力自己編出來
;以下三單元存轉換后農歷日期與入口單元重疊,如要保留入口信息,請重定義?
start_year equ 01
CONvert_yeAr DATA 5ch
CONvert_mONth DATA 38h ;BIT7 為1 表示閏月
CONvert_dAte DATA 37h
temp_Byte1 DATA 57h
temp_Byte2 DATA 58h
temp_Byte3 DATA 59h
temp_Byte4 DATA 5Ah
temp_Byte5 DATA 5Bh
;以下為公歷轉農歷子程序
CONvert:
mov a,year
mov time_year,a
mov a,month
mov time_month,a
mov a,day
mov time_data,a
MOV A,time_year ;將年月日轉化為HEX 格式
;www.01mcu.com
MOV B,#16
DIV AB
MOV CONvert_yeAr,B
MOV B,#10
MUL AB
ADD A,CONvert_yeAr
MOV CONvert_yeAr,A
MOV A,time_month
JNB ACC.4,CON_02
CLR ACC.4 ;ACC.4 為1 表示大于10 月
ADD A,#10
CON_02: MOV CONvert_mONth,A
MOV A,time_data
MOV B,#16
DIV AB
MOV CONvert_dAte,B
MOV B,#10
MUL AB
ADD A,CONvert_dAte
MOV CONvert_dAte,A
MOV dptr,#mONth_dAtA ;以下定位本年數據在表格中的位置
MOV A,CONvert_yeAr
CON_06: CLR C
SUBB A,#stArt_yeAr
MOV B,#3 ;表格每年3 字節
MUL AB
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -