|
基于51單片機數碼管顯示的單片機時鐘仿真原理圖(proteus工程文件可到本帖附件下載):
單片機匯編語言程序:
- ;-----------------------------------------------------------------
- ;文件名稱:SZ10-3.ASM
- ;程序功能:帶倒計時的鬧鐘
- ;----------------------------------------------------------------
- ;******************* 鬧鐘(含插入倒計時)程序部分 *******************
- ;----- -------- 程序初始化 -------------
- ; 定義存放計時單元地址
- ALB EQU 20H.0 ;鬧鈴設置標志
- BUF EQU 30H ;30~33H 連續(xù)4個字節(jié)存放顯示器數據
- HOUR EQU 34H ;存放小時變量
- MIN EQU 35H ;存放分鐘變量
- SEC EQU 36H ;存放秒鐘變量
- DEDA EQU 37H ;存放5ms計數值
- HH EQU 38H ;鬧鈴設置小時變量
- MM EQU 39H ;鬧鈴設置分鐘變量
- ;………………………………
- SEC0 EQU 3AH ;存放舊的秒數
- MM_D EQU 3BH ;倒數時間分鐘數
- SS_D EQU 3CH ;倒數時間秒鐘數
- ;………………………………
- ;按鍵輸入引腳定義
- K1 EQU P2.4 ;按鍵K1引腳定義
- K2 EQU P2.5 ;按鍵K2引腳定義
- K3 EQU P2.6 ;按鍵K3引腳定義
- K4 EQU P2.7 ;按鍵K4引腳定義
-
- ;蜂鳴器和指示燈引腳定義
- SPK EQU P3.7 ;蜂鳴器控制信號引腳定義
- WLED EQU P3.0 ;工作指示燈引腳定義
-
- ;程序開始執(zhí)行地址
- ORG 0H ;程序代碼由地址0開始
- JMP MAIN
- ORG 0BH ;定時器T0中斷地址設置
- JMP TO_SRV
- ;-------------- 主 程 序 ------------
-
- MAIN: ;主程序
- CLR ALB ;清除鬧鈴標志
- ACALL BZ ;蜂鳴器連續(xù)兩次鳴響
- ACALL BZ
- ACALL LED_BL ;LED 閃動,表示程序開始執(zhí)行
- ACALL INIT ;初始變化量
- ACALL INIT_TIMER ;設置定時器
-
- ;加載顯示器初值數據
- MOV A, #0C0H
- MOV P0, A
-
- ;無窮循環(huán)
- LOOP:
- ACALL CONV
- ACALL TIME_PRO ;檢查鬧鈴時間
- ACALL DISP ;掃描顯示
- ;設置走時時間
- JB K1, M1 ;未按下K1鍵,則繼續(xù)掃描
- ACALL LED_BL ;LED閃動
- ACALL SET_TIME ;設置目前時間
- JMP LOOP ;跳轉到LOOP處運行
-
- ;設置鬧鈴時間
- M1: JB K2, M2 ;未按下K2鍵,則繼續(xù)掃描
- ACALL LED_BL
- ACALL SET_ATIME ;設置鬧鈴時間
- JMP LOOP ;跳轉到LOOP處運行
-
- ;設置倒計時間
- M2: JB K3, M3 ;未按下K3鍵,則繼續(xù)掃描
- ;…………………………
- ACALL LED_BL
- ACALL DOWN_ATIME ;設置倒計時間
- ;…………………………
- JMP LOOP ;跳轉到LOOP處運行
-
- M3: JB K4, M4 ;未按下K4鍵,則繼續(xù)掃描
- CPL ALB
- JNB ALB, M31
-
- ;鬧鈴啟動連續(xù)3次發(fā)出響聲
- ACALL BZ
- ACALL BZ
- ACALL BZ
- JMP LOOP ;跳轉到LOOP處運行
- M31:
- ACALL BZ ;鬧鈴停止,發(fā)出一聲響
- JMP LOOP ;跳轉到LOOP處運行
- M4:
- JMP LOOP ;跳轉到LOOP處運行
-
- ;----------- 實現走時功能的子程序 ----------
- ;使用定時器T0模式0計時
- INIT_TIMER: ;初始化定時器,使用定時器T0模式0計時
- MOV TMOD,#00000000B ;設置定時器T0工作模式0
- MOV IE, #10000010B ;啟用定時器T0中斷產生
- MOV TL0, #(8192-4900)MOD 32 ;加載初始化數據
- MOV TH0, #(8192-4900)/32
- SETB TR0 ;啟動定時器0開始計時
- RET
- ;-----------―――
- ;中斷服務程序
- TO_SRV: ;定時器T0計時中斷程序每隔5ms中斷一次
- PUSH ACC ;將A值壓入堆棧
- MOV TL0, #(8192-4900)MOD 32 ;重加載初始化數據
- MOV TH0, #(8192-4900)/32
- INC DEDA ;加1
- ;秒輸出
- MOV A, DEDA
- CJNE A,#200,TT1 ;是否1s到了
- MOV DEDA, #0 ;計數值清0
- CPL WLED ;LED燈亮滅變換
- INC SEC ;秒計數加1
- MOV A, SEC
- CJNE A, #60, TT1 ;是否1min到了
- ;分輸出
- INC MIN ;分計數加1
- MOV SEC, #0 ;秒計數清0
- MOV A, MIN
- CJNE A, #60, TT1 ;是否1h到了
- ;小時輸出
- INC HOUR ;小時計數加1
- MOV MIN, #0 ;分計數清0
- MOV A, HOUR
- CJNE A, #24, TT1 ;是否24h到了
- MOV SEC, #0 ;秒鐘變量清0
- MOV MIN, #0 ;分鐘變量清0
- MOV HOUR, #0 ;小時變量清0
- TT1:
- POP ACC ;將A值由堆棧取出
- RETI
- ;------------- 實現顯示功能的子程序 ---------
-
- CONV:
- ;轉換小時數據
- MOV A, HOUR
- MOV B, #10
- DIV AB
- MOV DPTR,#TABLE ;查表轉換
- MOVC A, @A+DPTR
- MOV BUF, A
- MOV A, B
- MOVC A, @A+DPTR
- MOV BUF+1, A
- ;轉換分鐘數據
- MOV A, MIN
- MOV B, #10
- DIV AB
- MOV DPTR,#TABLE ;查表轉換
- MOVC A, @A+DPTR
- MOV BUF+2, A
- MOV A, B
- MOVC A, @A+DPTR
- MOV BUF+3, A
- RET
-
- ;字型數據編碼表
- TABLE:
- DB 0C0H,0F9H,0A4H,0B0H
- DB 99H,92H,82H,0F8H
- DB 80H,90H,88H,83H
- DB 0C6H,0A1H,86H,8EH
-
- ;-------------- 掃描顯示子程序 -----------
- ;掃描顯示
- DISP:
- MOV R0, #BUF ;指向顯示器顯示緩沖區(qū)起始地址
- MOV R2, #4 ;循環(huán)執(zhí)行4次
- MOV ACC, #11110111b ;加載掃描信號初值11110111B
- S1:
- PUSH ACC
- MOV A, @R0 ;取出顯示器數據
- MOV P0, A ;由P0送出一位顯示器數據
- POP ACC
- MOV P2, ACC ;由P2送出掃描輸出信號
- MOV R5, #2 ;延遲一段時間
- ACALL DELAY
- ;改變掃描碼 EX:XXXX1011
- RR A ;累加器A向右移動一位
- INC R0 ;顯示器顯示緩沖區(qū)地址加1
- DJNZ R2, S1 ;判斷是否繼續(xù)執(zhí)行循環(huán)
- RET
-
- ;------------- 實現調整時間子程序 -----------
- ;設置目前時間
- SET_TIME:
- CLR TR0 ;定時器工作暫停
- MOV SEC, #0 ;秒鐘變量清0
- L0:
- ACALL DISP ;掃描顯示
-
- JB K2, L1 ;未按下K2鍵,則繼續(xù)掃描
- JNB K2, $ ;按下,則等待放開
- ;K2小時調整
- INC HOUR ;小時計數加1
- MOV A, HOUR
- CJNE A,#24, L11 ;是否24h到了
- MOV HOUR, #0 ;小時變量清0
- L11:
- ACALL CONV ;轉換顯示數據
- ACALL DISP ;掃描顯示
- JMP L0 ;跳轉到L0處執(zhí)行
-
- L1: JB K3, L2 ;未按下K3鍵,則繼續(xù)掃描
- JNB K3,$ ;按下,則等待放開
- ;K3分鐘調整
- INC MIN ;分鐘計數加1
- MOV A, MIN
- CJNE A,#60, L21 ;是否60min到了
- MOV MIN, #0 ;分鐘變量清0
- L21:
- ACALL CONV ;轉換顯示數據
- ACALL DISP ;掃描顯示
- JMP L0 ;跳轉到L0處運行
-
- L2: JB K4,L0 ;未按下K4鍵,則繼續(xù)掃描
- JNB K4, $ ;按下,則等待放開
- ACALL BZ ;蜂鳴器鳴響一聲
- ;K4設置完成
- ACALL LED_BL ;LED閃動
- SETB TR0 ;啟動定時器
- RET
- ;------------- 計時單元清0子程序 ----------
- ;計時單元清0
- INIT:
- MOV DEDA, #0 ;5ms計數值清0
- MOV SEC, #0 ;秒鐘變量清0
- MOV MIN, #0 ;分鐘變量清0
- MOV HOUR, #0 ;小時變量清0
- RET
- ; ------------―蜂鳴器鳴響一聲子程序 ----------
- ;蜂鳴器
- BZ: ;蜂鳴器鳴響一聲
- MOV R6, #250
- B1: ACALL DEX
- CPL SPK
- DJNZ R6, B1
- MOV R5, #50
- ACALL DELAY
- RET
-
- ;-------------工作指示燈閃爍子程序 ----------
- ;工作指示
- LED_BL: ;工作指示燈閃爍
- MOV R4, #6
- LE1: CPL WLED ;位反向
- MOV R5,#25
- ACALL DELAY ;延遲50ms
- DJNZ R4, LE1
- RET
- ;-------------- 延時子程序 -------------
- ;延時子程序
- DELAY: ;總延遲時間R5 2ms
- MOV R6,#10
- D1: MOV R7,#100
- DJNZ R7,$
- DJNZ R6, D1
- DJNZ R5, DELAY
- RET
- ;------------ 蜂鳴器短暫延時子程序-----------
- ; 蜂鳴器
- DEX: MOV R7, #180 ;短暫延時
- DE1: NOP
- DJNZ R7, DE1
- RET
- ;******************** 增加定時鬧鈴程序部分 *********************
- ; ----------- 設置鬧鈴時間子程序 ------------
- ;設置鬧鈴時間
- SET_ATIME:
- MOV HH, #0
- MOV MM, #0
- ACALL CONVA ;加載鬧鈴時間數據
- N0:
- ACALL DISP
- ;-----------
- JB K2, N1 ;未按下K2鍵,則繼續(xù)掃描
- JNB K2, $ ;按下,則等待放開
- ;K2調整小時
- INC HH ;小時數加1
- MOV A, HH
- CJNE A, #24, N11 ;是否24h到了
- MOV HH, #0 ;小時數清0
- N11:
- ACALL CONVA ;加載鬧鈴時間數據
- ACALL DISP ;掃描顯示
- JMP N0 ;跳轉到N0處運行
- ;------------
- N1: JB K3, N2 ;未按下K3鍵,則繼續(xù)掃描
- JNB K3, $ ;按下,則等待放開
- ;K3調整分鐘
- INC MM ;調整分鐘數
- MOV A, MM ;分鐘數加1
- CJNE A, #60, N21 ;是否60min到了
- MOV MM, #0 ;分鐘數清0
- N21:
- ACALL CONVA ;加載鬧鈴時間數據
- ACALL DISP ;掃描顯示
- JMP N0 ;跳轉到N0處運行
- ;------------
- N2: JB K4, N0 ;未按下K4鍵,則繼續(xù)掃描
- JNB K4, $ ;等K4鍵放開
- ;K4設置完成
- ACALL LED_BL ;LED閃動
- ACALL CONV ;加載現在時間數據
- RET
- ; ----------- 加載鬧鈴時間數據子程序 ----------
-
- CONVA:
- ;轉換小時數據
- MOV A, HH
- MOV B, #10
- DIV AB
- ;-----------
- MOV DPTR,#TABLE ;查表轉換
- MOVC A, @A+DPTR
- MOV BUF, A
- ;-----------
- MOV A, B
- MOVC A, @A+DPTR
- MOV BUF+1, A
- ;轉換分鐘數據
- MOV A, MM
- MOV B, #10
- DIV AB
- ;-----------
- MOV DPTR, #TABLE ;查表轉換
- MOVC A, @A+DPTR
- MOV BUF+2, A
- ;-----------
- MOV A, B
- MOVC A, @A+DPTR
- MOV BUF+3, A
- RET
-
- ; ---------- 檢查鬧鈴時間處理子程序 ----------
- ;檢查是否啟動鬧鈴
- TIME_PRO:
- JB ALB, TI3
- RET
- ; --------------
- ;檢查鬧鈴時間是否到了
- TI3:
- MOV A, HOUR
- MOV B, HH
- CJNE A, B, BK ;檢查鬧鈴小時時間
- ;-----------
- MOV A, MIN
- MOV B, MM
- CJNE A, B, BK ;檢查鬧鈴分鐘時間
- ;-----------
- ACALL TIME_OUT ;調用執(zhí)行檢查鬧鈴時間處理子程序
- BK:
- RET
- ;---------- 執(zhí)行鬧鈴時間處理子程序 -----------
- TIME_OUT: ;所設置的鬧鈴數據到了
- X1: ACALL LED_BL ;LED閃動
- ACALL BZ ;蜂鳴器發(fā)聲
- ;按下K4鍵停止鬧鈴
- JB K4, X1 ;等待是否按下K4鍵
- JNB K4,$ ;若按下鍵,則等待按鍵放開
- ACALL LED_BL ;LED閃動
- CLR ALB ;清除鬧鈴位
- RET
- ; -----------------------------------
-
- ;******************** 增加倒計時程序部分 ***********************
- ;----------- 設置倒計時時間子程序 ----------
- ;設置倒計時時間
- DOWN_ATIME:
- CLR TR0 ;定時器工作暫停
- MOV HH, #0
- MOV MM, #0
- MOV SS_D, #1 ;秒鐘變量為1
- S0:
- ACALL DISP ;掃描顯示
- ;-----------
- ;按K2分鐘數增加
- JB K2, S12 ;未按下K2,則繼續(xù)掃描
- JNB K2, $ ;按下,則等待放開
-
- INC MM_D ;分鐘數加1
- MOV A, MM_D
- CJNE A, #60, S11 ;是否60min到了
- MOV MM_D, #0 ;分鐘變量清0
- S11:
- ACALL DOWN_CONV ;顯示倒數的時間
- ACALL DISP ;掃描顯示
- JMP S0 ;跳轉到S0處運行
- ;------------
- ;按K3分鐘數減少
- S12: JB K3, S2 ;未按下K3,則繼續(xù)掃描
- JNB K3, $ ;按下,則等待放開
- DEC MM_D ;分鐘數減少1
- MOV A, MM_D
- CJNE A, #0,S21 ;判斷是否為0
- MOV MM_D, #60 ;分鐘數賦值為60
- S21:
- ACALL DOWN_CONV ;加載倒數時間數據
- ACALL DISP ;掃描顯示
- JMP S0 ;循環(huán)執(zhí)行
- ;------------
- S2: JB K4, S0 ;未按下K4鍵,則繼續(xù)掃描
- JNB K4, $ ;等K4鍵放開
- ;K4設置完成
- ACALL BZ ;響4聲
- ACALL BZ
- ACALL BZ
- ACALL BZ
-
- ACALL LED_BL ;LED閃動
- SETB TR0 ;啟動定時器
-
- S3:
- ACALL DOWN_TIME ;檢查倒計時
- ACALL DOWN_CONV ;加載倒數時間數據
- ACALL DISP ;掃描顯示
- JMP S3
- RET
-
- ; ---------- 加載倒計時時間子程序 ---------
- ;顯示倒數的分鐘數
- DOWN_CONV:
- MOV A, MM_D
- MOV B, #10 ;設置被除數
- DIV AB ;除法運算,結果A存商數,B存余數
- MOV DPTR, #TABLE ;查表轉換
- MOVC A, @A+DPTR
- MOV BUF+2, A ;商數存入BUF+2
- MOV A, B ;余數暫存入A
- MOVC A, @A+DPTR ;查表轉換
- MOV BUF+3, A ;余數存入BUF+3
- RET
-
- ;------------- 檢查倒計時子程序 ------------
- ;檢查倒計時
- DOWN_TIME: ;檢查是否倒數終止
- MOV A,SEC ;加載現在秒數
- MOV B, SEC0 ;載入舊秒數
- CJNE A, B, D01 ;是否過了1s
- RET
- ; -----------
- D01:
- MOV SEC0, SEC ;記錄舊的秒數
- DEC SS_D ;秒數減1
- MOV A, SS_D
- CJNE A, #0, D11 ;秒鐘數是否為0
- MOV A, MM_D
- CJNE A, #0, D12 ;分鐘數是否為0
- ;秒鐘數為0且分鐘數為0,則倒數終止
- ACALL TIME_OUT ;倒數終了處理程序
- JMP LOOP
- RET
- ;-----------
- D12:
- MOV SS_D,#59 ;秒鐘數賦值為59
- DEC MM_D ;分鐘數減1
-
- D11:
- ACALL DOWN_CONV ;顯示倒計時時間
- RET
- ;----------------------------------
- END
- ;-----------------------------------------------------------------
復制代碼
單片機c語言源程序:
- // --------------------------------------------------------------------------------------
- // 文件名稱:SZ10-1.c
- // 程序功能:單片機時鐘
- // --------------------------------------------------------------------------------------
- #include <reg51.h> // 包含器件配置文件
- #define uchar unsigned char
- #define uint unsigned int
- char DATA_7SEG[10]={0xC0,0xF9,0xA4,0xB0,0x99,
- 0x92,0x82,0xF8,0x80,0x90}; // 0~9的數碼管段碼
- uchar hour=0,min=0,sec=0; // 時、分、秒單元清0
- uchar deda=0; // 5ms計數單元清0
- bit d_05s=0; // 0.5s標志
- uchar set=0; // 模式設定標志
- uchar m=0;
- uchar flag=0; // RAM掉電標志
- void delay(uint k); // 延時函數
- void conv(); // 走時單元轉換
- void disp(); // 走時時間顯示函數
- //-----------------------
- sbit K1=P2^4; // 按鍵K1引腳定義
- sbit K2=P2^5; // 按鍵K2引腳定義
- sbit K3=P2^6; // 按鍵K3引腳定義
- sbit K4=P2^7; // 按鍵K4引腳定義
- //-----------------------
- sbit SPK=P3^7; // 蜂鳴器引腳定義
- sbit SET_2=P2^2;
- sbit M_D=P0^7;
- // ---------------------------- 定時器初始化函數----------------------------
- // 定時器T0初始化
- void init_timer()
- {
- TMOD=0x01; // 設置定時器T0工作模式為1
- TH0=-(4800/256); // 加載高字節(jié)計數初值
- TL0=-(4800%256); // 加載低字節(jié)計數初值
- IE=0x82; // 啟用定時器T0中斷產生
- TR0=1; // 啟動定時器T0開始計時
- }
- // ------------------------------- 中斷T0函數 ------------------------------
-
- // 5ms定時中斷
- void T0_srv(void) interrupt 1
- {
- TH0=-(4800/256); // 重置定時器計時初始值
- TL0=-(4800%256);
- deda++; // 計數單元deda 值遞增
- }
-
- // ----------------------------- 走時單元轉換函數 -------------------------
- // 時、分、秒單元及走時單元轉換
- void conv()
- {
- if(deda<=100)d_05s=0; // 秒位標志,每秒的后0.5s置0
- else d_05s=1; // 秒位標志,每秒的前0.5s置1
- if(deda>=200){sec++;deda=0;} // 中斷200次秒加1,deda清0
- if(sec==60){min++;sec=0;} // 秒滿60次后,分加1,秒清0
- if(min==60){hour++;min=0;} // 分滿60次后,時加1,分清0
- if(hour==24){hour=0;} // 小時滿24后,小時清0 */
- }
- // ------------------------------ 走時時間顯示函數 ------------------------
- // 走時時間顯示
- void disp()
- {
- P0=DATA_7SEG[hour/10];P2=0xf7;delay(2);
- P0=DATA_7SEG[hour%10];P2=0xfb;delay(2);
- if(d_05s==1){if(SET_2==0)M_D=0;else M_D=1;}
- delay(2);
- P0=DATA_7SEG[min/10];P2=0xfd;delay(2);
- P0=DATA_7SEG[min%10];P2=0xfe;delay(2);
- }
- // ----------------------------- 調整走時時間函數 -------------------------
- /* 調整走時時間 */
- void set_time()
- {
- uchar m;
- //TR0=0;
- if(K2==0)delay(1); // 按下K2鍵,消除抖動
- if(K2==0)hour++; // 小時數遞增
- if(hour==24)hour=0; // 小時數到24,從0開始
- for(m=0;m<30;m++) // 循環(huán)30次
- {
- disp(); // 調用disp()顯示函數
- if(SET_2==0)M_D=0; // 點亮U2小數點(秒點)
- else M_D=1;
- delay(1); // 調用delay(1)延時函數
- }
- if(K3==0)delay(1); // 按下K3鍵,消除抖動
- if(K3==0)min++; // 分鐘數遞增
- if(min==60)min=0; // 分鐘數到60,從0開始
- for(m=0;m<30;m++) // 循環(huán)30次
- {
- disp(); // 調取disp()顯示函數
- if(SET_2==0)M_D=0; // 點亮U2小數點(秒點)
- else M_D=1;
- delay(1); // 調取delay(1)延時函數
- }
- }
- // ------------------------------ 走時函數 ---------------------------------
- //走時
- void time()
- {
- conv(); // 走時單元轉換
- disp(); // 走時時間顯示函數
- }
- // ----------------------------- 按鍵模式函數 ------------------------------
- // 掃描按鍵次數
- void scan_key()
- {
- delay(1); // 調用延時函數
- if(K1==0) set++; // 按一下K1鍵,set 加1
- if(set>=2)set=0; // 按兩次K1鍵,set 為0
- if(set==1)flag=0x55; // set =1,flag等于55H
- F0:if(K1==0)goto F0; // 按鍵未釋放,在此等候
- }
- //------------------------------ 延時函數 ---------------------------------
- //延時
- void delay(uint k) // 總延時時間:1ms k
- {
- uint i,j; // 定義局部變量i、j
- for(i=0;i<k;i++){ // 外層循環(huán)
- for(j=0;j<121;j++) // 內層循環(huán)
- {;}}
- }
- //------------------------------- 發(fā)聲函數 --------------------------------
-
- // 發(fā)聲
- void fs_d ()
- {
- unsigned int j,y; // 聲明無符號整型變量j, y
- {
- for(y=0;y<1000;y++) // 循環(huán)1000次,嘀響0.5s
- {
- SPK=~SPK; // 反相輸出
- for(j=0;j<50;j++); // 延時500μs
- }
- delay(200); // 停0.2s
- }
- }
-
- //--------------------------------- 主函數 --------------------------------
- //主函數
- void main()
- {
- init_timer(); // 定時器T0初始化
- while(1) // 無限循環(huán)
- {
- if(K1==0)
- {
- scan_key(); // 有按鍵,調用按鍵掃描函數
- fs_d ();
- }
- switch(set) // 根據set鍵值散轉
- {
- case 0:time(); break; // 走時時間程序
- case 1: set_time();break; // 走時時間調整
- default:break; // 其他,退出
- }
- if(flag!=0x55) // 判斷掉電標志
- {
- P0=0xc0; P2=0xc0; delay(200); // 點亮4個數碼管
- P2=0xff; delay(400); // 熄滅 4個數碼管
- }
- }
- }
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
該系列源碼包含有很多非常經典,代碼風格十分規(guī)范,而且注釋詳細的單片機例程,還帶仿真,對于MCU學習特別是初學者是很有幫助的,全部源碼下載(共25個項目):http://www.torrancerestoration.com/bbs/dpj-79328-1.html
本例程下載(含proteus仿真工程文件與源碼):
單片機數碼管單片機時鐘實驗.rar
(62.5 KB, 下載次數: 59)
2017-3-30 01:40 上傳
點擊文件名下載附件
|
|