led數(shù)碼管電子時鐘制作及程序
一、 題目及功能要求
1 制作一個電子日歷時鐘使用匯編語言進(jìn)行軟件編程
2 實(shí)現(xiàn)功能
(1) 顯示北京時間并能校準(zhǔn)
(2) 時、分、秒之間以及年、月、日之間以小數(shù)點(diǎn)隔開
(3) 顯示公歷日期并能校準(zhǔn)能夠自動識別“閏年”以及“大月、小月”
(4) 運(yùn)動秒表能夠后臺計(jì)時秒表精確到 0.05S
(5) 鬧鐘功能有鬧鐘開關(guān)并能顯示當(dāng)前鬧鐘是否開啟
(6) 整點(diǎn)報時提醒
二、 硬件方案
1 AT89S52 最小系統(tǒng)
2 顯示電路采用動態(tài)掃描驅(qū)動電路AT89S52 的 P0 口連接 74LS244 總線驅(qū)動器輸
出信號利用三極管 8550 進(jìn)行放大通過 P1 口對數(shù)碼管進(jìn)行段選掃描AT89S52 的
P1.2~P1.7 口對數(shù)碼管進(jìn)行位選掃描
3 兩個按鍵開關(guān)分別接 AT89S52 的兩個外部中斷引腳
4 AT89S52 的 P2.0 口輸出經(jīng)三極管 9012 放大驅(qū)動有源蜂鳴器發(fā)聲
三、 電路原理圖
四、 系統(tǒng)元件布局、布線圖
五、 元器件清單
六、 軟件方案
1 “時鐘”基準(zhǔn)時間由 AT89S52 定時器 0 中斷提供設(shè)置為最高優(yōu)先級定時器 0
設(shè)為工作方式 1即 16 進(jìn)制計(jì)數(shù)器方式計(jì)數(shù)初值設(shè)為 15536即可實(shí)現(xiàn) 0.05s 中
斷一次連續(xù)中斷 20 次即可實(shí)現(xiàn)一秒定時。
2 由于使用較多數(shù)碼管顯示模塊使用動態(tài)掃描方式定義全局變量保存各個數(shù)位
的 BCD 碼通過查表將字模送到 P0 口進(jìn)行輸出為了顯示鬧鐘的狀態(tài)設(shè)置了
另一字模數(shù)據(jù)表在顯示前進(jìn)行判斷若為鬧鐘開關(guān)設(shè)置狀態(tài)則調(diào)用此字模數(shù)據(jù)表。
3 按鍵中斷的時候在 2 個按鍵都沒按下的狀態(tài)2 個中斷引腳都為低電平則一直
調(diào)用中斷 0 的子程序每次進(jìn)入中斷 0 子程序中便檢測中斷 1 的引腳是否為高電平
即檢測開關(guān) KEY1 是否按下相反在按下 KEY0 時進(jìn)入中斷 1 子程序每次進(jìn)
入中斷 1 子程序都檢測中斷 0 的引腳是否為高電平為高電平則表示已按下。
4 用寄存器 R7 來記錄當(dāng)前切換的功能分別為0時間1日期2-鬧鐘3-鬧鐘
開關(guān)4-秒表。
5 秒表的實(shí)現(xiàn)采用基準(zhǔn)時鐘作為秒表時鐘源,精度可以達(dá)到 0.05s。
6 鬧鐘的實(shí)現(xiàn)在主程序中循環(huán)判斷鬧鐘設(shè)置的時分與當(dāng)前時分是否相等鬧鐘持
續(xù) 1 分鐘
7 整點(diǎn)報時的實(shí)現(xiàn)在主程序中先判斷當(dāng)前時間的秒若為 0 再判斷分再為 0 則
使蜂鳴器嘀一聲循環(huán)判斷。
七、 程序框圖
1. 主程序
2. 定時器 0 中斷子程序
3. 外部中斷 0 子程序
4. 外部中斷 1 子程序
八、 系統(tǒng)使用說明
1 接通電源自動復(fù)位讀取初始狀態(tài)時鐘--“00.00.00”日期—“10.06.06”鬧鐘
—“06.00.00”鬧鐘狀態(tài)—“OFF”秒表—“00.00.00”。
2 按鍵 KEY1 為“切換功能/調(diào)節(jié)”按鈕按鍵 KEY0 為“確定/計(jì)時開始/計(jì)時暫停/
鬧鐘開關(guān)按鈕
3 第一功能----電子時鐘按 KEY0 鍵進(jìn)入時校準(zhǔn)狀態(tài)“時”數(shù)碼管閃爍此時按
KEY1 鍵可以調(diào)節(jié)小時“時”調(diào)節(jié)范圍為 00~24按 KEY0 可切換到“分”設(shè)置
調(diào)節(jié)范圍為 00~59 再按 KEY0 可切換到“秒”設(shè)置 調(diào)節(jié)范圍為 00~59。
4 第二功能----電子日歷在電子時鐘功能下按 KEY1 可以切換到電子日歷功能。
進(jìn)入電子日歷功能可以對“年”.“月”.“日”進(jìn)行校準(zhǔn)校準(zhǔn)方式同電子時鐘
的校準(zhǔn)方式一樣自行摸索。
5 第三功能----鬧鐘設(shè)置在電子日歷功能下按 KEY1 可以切換到鬧鐘設(shè)置功能。
鬧鐘的設(shè)置同電子時鐘的設(shè)置一樣。
6 第四功能----鬧鐘開關(guān)在鬧鐘設(shè)置功能下按 KEY1 可以切換到鬧鐘開關(guān)設(shè)置。
默認(rèn)狀態(tài)為關(guān)閉鬧鐘功能顯示“OFF”按 KEY0 可以調(diào)節(jié)鬧鐘開關(guān)打開鬧鐘
功能則顯示“ON”。鬧鐘設(shè)置為“ON”時最后一個數(shù)碼管的小數(shù)點(diǎn)會亮起可
以在任何功能狀態(tài)下提示鬧鐘功能已開啟。
7 第五功能----秒表在鬧鐘設(shè)置功能下按 KEY1 可以切換到秒表功能。進(jìn)入秒表
功能按 KEY0 開始計(jì)時再按 KEY0 則暫停計(jì)時在秒表計(jì)時的時候按 KEY1 可
以切換到其他功能而秒表則在后臺計(jì)時在秒表暫停時按 KEY1 可以將秒表清零。
九、 體會
第一次使用Atmel Designer Winter 09布出一個完整的PCB制板圖并用覆銅板做成實(shí)
物最大的體會是軟件能畫出來的圖我們不一定就能把這樣的 電路板做出來。布線時
要考慮的因素除整體布局、飛線數(shù)目外最重要的是線的寬度、線與線的間距、焊盤的大小。
唯有線寬合適、間距合 理才能做出符合要求的電路板。剛制成的電路板要先使用萬用表檢
測各導(dǎo)線的連接情況解決斷路、短路的問題之后方能進(jìn)行焊接。這樣做 的好處是保證
了調(diào)試程序時不會受硬件接觸不良等情況的影響。
由于第一次嘗試完全使用匯編語言對AT89S52進(jìn)行編程操作對匯編語言的陌生給前期
編程工作帶來諸多不便。匯編語言不同于C或其它高級 語言程序間的跳轉(zhuǎn)各種寄存器的
壓棧出棧都需要人工考慮而這種疏漏編譯器也不會給出任何提示于是往往一些大意的疏
忽程序便 無法達(dá)到預(yù)期的效果。加之沒有相關(guān)條件使用在線調(diào)試也給故障排除帶來一
些障礙。
對此的體會是確定是程序出現(xiàn)問題時優(yōu)先往程序間的跳轉(zhuǎn)條件、重要寄存器等的現(xiàn)
場保護(hù)、循環(huán)退出的條件方面考慮尋找原因。由于 此次硬件電路設(shè)計(jì)采用低電平導(dǎo)通的
PNP三極管和74LS244電平驅(qū)動器也沒有將IO口做通用數(shù)據(jù)傳輸口用故不需考慮上拉電
阻的選用及 將相應(yīng)管腳寫入高電平以正確接收數(shù)據(jù)的問題。當(dāng)然在調(diào)試的過程中合理的使
用軟件仿真機(jī)熟練的設(shè)置程序斷點(diǎn)同時觀察單片機(jī)各寄存 器值的變化可以極大方便
我們查找程序漏洞解決問題。
在書寫代碼的過程中應(yīng)該注意代碼的規(guī)范化尤其是使用匯編編程時必須加上必要
的注釋方便程序閱讀及故障排查。對于需要使用 到的各個變量必須在程序開頭集中定
義存儲位置以求一目了然在新增變量的時候也不至于出現(xiàn)存儲單元被重復(fù)使用而導(dǎo)致數(shù)
據(jù)丟失的 情況。
最后看著忙碌數(shù)日得來的勞動成果乖乖的工作確實(shí)蠻有成就感。希望今后有更多的
機(jī)會進(jìn)行這樣的實(shí)踐實(shí)驗(yàn)。
十、 附錄
;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
; 學(xué)生姓名黃錦波黃卓佳
; 學(xué)生學(xué)號200830240380200830240434
; 分組編號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 ;當(dāng)前顯示內(nèi)容標(biāo)志 ;DIS_FLAG: 0時間1日期;2-鬧鐘3-鬧鐘開
關(guān)4-秒表
;------------------
NSECOND_BCD EQU 2BH ;鬧鐘時間
NMINUTE_BCD EQU 2CH
NHOUR_BCD EQU 2DH
;------------------
TCC_BCD EQU 2EH ;秒表計(jì)時器
TBB_BCD EQU 2FH
TAA_BCD EQU 30H
;------------------
TIMER_FLAG EQU 31H ;秒表模式
TIMER_START_FLAG EQU 32H ;秒表開始
;------------------
ALAM_STATE EQU 33H ;鬧鐘開啟標(biāo)志
;------------------
DI_40H EQU 34H ;提示音延時變量
DI_41H EQU 35H ;延時
;------------------
ALAM_ON1 EQU 36H ;鬧鐘狀態(tài)顯示
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 ;秒表工作標(biāo)志
MOV TIMER_FLAG,#00H ;秒表模式標(biāo)志
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 鬧鐘狀態(tài)顯示
MOV ALAM_ON2,#01H
MOV ALAM_ON3,#55H
MOV ALAM_OFF1,#63H
MOV ALAM_OFF2,#42H
MOV ALAM_OFF3,#33H
MOV ALAM_STATE,#00H ;初始化鬧鐘狀態(tài)為 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高優(yōu)先級
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 ;整點(diǎn)滴
SETB P2.0
SCANALARM: ;鬧鐘掃描
MOV A,ALAM_STATE
JZ SCAN_HOUR ;鬧鐘開關(guān)已打開
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 ;秒表計(jì)時
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 ; 秒進(jìn)位
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 ; 分進(jìn)位
MOV A,HOUR_BCD ; take BCD of "hour"
CJNE A,#23H,HOUR_INC ; is up to 23 hours ?
MOV HOUR_BCD,#00H ; “時”進(jìn)位
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 ?
;天進(jìn)位
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 ?
; 月進(jìn)位
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 碼調(diào)整
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 碼調(diào)整
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 碼調(diào)整
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 碼調(diào)整
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 碼調(diào)整
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 碼調(diào)整
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 碼調(diào)整
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 碼調(diào)整
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" 當(dāng)前顯示內(nèi)容為時間
;R0: point to display buffer
DISP_TIME: MOV R0,#SECOND_BCD ; beginning from "second"
SJMP TSA
DISP_DATE:
CJNE A,#01H,DISP_ALAM ; "01" 當(dāng)前顯示內(nèi)容為日期
MOV R0,#DAY_BCD ; "FF" for showing date
SJMP TSA;顯示時間或日期
DISP_ALAM:
CJNE A,#02H,DISP_ALAM_SET ; "02" 當(dāng)前顯示內(nèi)容為鬧鐘
MOV R0,#NSECOND_BCD ; beginning from "second"
SJMP TSA
DISP_ALAM_SET:
CJNE A,#03H,DISP_TIMER ; "03" 當(dāng)前顯示內(nèi)容為鬧鐘設(shè)置
MOV A,ALAM_STATE ; 鬧鐘狀態(tài)顯示
JZ SHOWOFF
MOV R0,#ALAM_ON1 ; 顯示”ON“
SJMP TSA
SHOWOFF:
MOV R0,#ALAM_OFF1 ;顯示“OFF”
SJMP TSA
DISP_TIMER: ;"04"當(dāng)前顯示內(nèi)容為秒表
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 ;是否顯示鬧鐘狀態(tài)位最末位小數(shù)點(diǎn)
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 ;該位增加小數(shù)點(diǎn)顯示
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 ;該位增加小數(shù)點(diǎn)顯示
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,切換時間/日期/鬧鐘/鬧鐘設(shè)置/秒表顯示或者調(diào)整
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 ;有閃爍進(jìn)入調(diào)整模式
SET_DIS: ;無閃爍進(jìn)入設(shè)置顯示或秒表模式
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 ;進(jìn)入秒表
;---------------------------------------------------
TIMER:
MOV TIMER_FLAG,#01H ;進(jìn)入秒表秒表模式設(shè)置為開
LJMP EX0_RET ;退出
;---------------------------------------------------
CROSSTIMER: ;顯示模式切換
CJNE A,#05H,OUT
MOV DIS_FLAG,#00H ;已到 5 需置零
MOV TIMER_FLAG,#00H
MOV A,TIMER_START_FLAG
JNZ OUT ;秒表后臺工作暫停計(jì)數(shù)時退出則對秒表清零
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: ;進(jìn)入調(diào)整模式
MOV A,DIS_FLAG ; 讀取當(dāng)前顯示內(nèi)容為時間/日期/秒表/鬧鐘
CJNE A,#00H,JDATE ;是否進(jìn)入時間調(diào)整 00
;---------------------------------------------------
JTIME: ;調(diào)整時間
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 ;是否進(jìn)入日期調(diào)整 01
JYY: NOP ; "01 to 06" is in flash
MOV A,FLASH_FLAG
CJNE A,#01H,JMM ; "01" for adjusting "year"
;調(diào)節(jié)年
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"
;調(diào)節(jié)月
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: ;調(diào)整鬧鐘
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,設(shè)置閃爍
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 ;非設(shè)置鬧鐘開關(guān)模式
MOV A,ALAM_STATE
CPL A ;取非
ANL A,#01H ;保留最后
MOV ALAM_STATE,A ;設(shè)置鬧鐘開關(guān)
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 ;設(shè)置秒表開關(guān)
;---------------------------------------------------
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: ;進(jìn)入切換閃爍
MOV A,FLASH_FLAG ; take flag of un-flash/flash
CJNE A,#00H,ED1 ; "00" 無閃爍
MOV FLASH_FLAG,#01H ; 設(shè)置 1,2 號數(shù)碼管閃爍
SJMP EX1_RET
ED1: CJNE A,#01H,ED2 ; "01" 1,2 號閃爍中
MOV FLASH_FLAG,#02H ; 設(shè)置 3,4 號閃爍
SJMP EX1_RET
ED2: CJNE A,#02H,ED3 ; "02" 3,4 號閃爍
MOV FLASH_FLAG,#03H ; 設(shè)置 5,6 號閃爍
SJMP EX1_RET
ED3: MOV FLASH_FLAG,#00H ; 關(guān)閉所有閃爍
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: 余數(shù)
; 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 ; R1BCD 補(bǔ)碼
MOV A,R0
ANL A,#0F0H ; BCD 高位
SWAP A
LP0: MOV R3,A ; BCD 碼的余數(shù)
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: ;鬧鐘狀態(tài)顯示的字模
DB 0C0H ; "0"
DB 11001000B ; "N"
DB 10001110B ; "F"
DB 0FFH ; " "
DB 40H ; "0."
DB 07FH ; "."
DB 00001110B ; "F."
END
同類文章排行
- LED數(shù)碼管的檢測
- LED數(shù)碼管故障檢測檢修
- LED數(shù)顯溫度控制器設(shè)計(jì)論述
- LED大屏幕數(shù)顯裝置在隨流孕育裝置上的應(yīng)用
- LED數(shù)碼管正裝與倒裝結(jié)構(gòu)區(qū)別
- led數(shù)碼管靜態(tài)顯示方式和動態(tài)顯示方式
- LED七段數(shù)碼管數(shù)字鐘
- led數(shù)碼管顯示種類簡介
- LED數(shù)碼管顯示器介紹
- LED數(shù)碼管動態(tài)掃描顯示控制器設(shè)計(jì)