❶ 用51單片機實現時鍾功能程序
anEQUP0;
weiEQUP2;
keyBITP3.7;
ORG0000H
AJMPMAIN;絕對轉移指令,2kb范圍(11位)內跳轉LJMP16位64kb范圍內跳轉
;短轉移指令的功能是先使程序計數器PC加1兩次(即:取出指令碼),然後把加2後的地址和rel相加作為目標轉移地址。因此,短轉移指令是一條相對轉移指令,是一條雙位元組雙周期指令
ORG0030H;指明後面的程序從程序存儲器的0030H單元開始存放
DELAY200US:;@11.0592MHz
NOP
NOP
NOP
PUSH30H
PUSH31H
MOV30H,#2
MOV31H,#179
NEXT:
DJNZ31H,NEXT
DJNZ30H,NEXT
POP31H
POP30H
RET
ORG0060H
;DISPLAY子程序
DISPLAY:
PUSHACC;不能寫A,此處ACC代表地址,push後跟地址,代表把地址內的內容壓入棧中
PUSH00H;R0
PUSH06H;R6
PUSH07H;R7
PUSH83H;DPH
PUSH82H;DPL
MOVR6,#01H;位選數據,01指的是緩沖區最低位數據
MOVR7,#08H;循環次數
FLAG:
MOVan,#0x00;消影
MOVA,R6
CPLA;取反
MOVwei,A;位選
MOVA,#disBufDat
ADDA,R7
SUBBA,#0X08
MOVR0,A
MOVA,@R0;讀出要顯示的數據到A
MOVDPTR,#disTab
MOVCA,@A+DPTR;從rom取數據,取出要顯示的數據對應的段碼
MOVan,A;段選
MOVA,R6
RLA
MOVR6,A;更新下一次位選
LCALLDELAY200US
DJNZR7,FLAG
POP82H;DPL
POP83H;DPH
POP07H
POP06H
POP00H
POPACC
RET
ORG0100H
;定時器中斷0初始化
T0_INIT:
MOVTMOD,#0X01
MOVTH0,#0X3C
MOVTL0,#0XB0
SETBEA
SETBTR0
SETBET0
RET
ORG0130H
;T0中斷處理程序
INT_TIMERE0:
PUSHACC
SETBRS0
MOVTH0,#0X3C
MOVTL0,#0XB0
INCR0
MOVA,R0
SUBBA,#0X14
JBCY,SECFLAG
MOVR0,#0x00
INCsec
SECFLAG:
CLRRS0
POPACC
RETI
ORG000BH;定時器/計數器T0入口地址
LJMPINT_TIMERE0;跳轉到定時器/計數器中斷服務程序中去
disTab:DB0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40;0-f,空白,橫杠的段選數據
disBufDatEQU47H;定義顯示緩沖數據變數區,8個
disBufDatHeadEQU40H//單片機上顯示在最左邊
secEQU48H
;主程序
ORG0180H
MAIN:
MOVSP,#0X60;將0x60到0x7f設為堆棧區
LCALLT0_INIT
MOVdisBufDatHead,#0X00
MOVdisBufDatHead+1,#0X00
MOVdisBufDatHead+2,#0X11
MOVdisBufDatHead+3,#0X11
MOVdisBufDatHead+4,#0X11
MOVdisBufDatHead+5,#0X11
MOVdisBufDatHead+6,#0X11
MOVdisBufDatHead+7,#0X11
MOVsec,#0X3A
WHILE:
JBkey,KEYSCAN
MOVsec,0x00
KEYSCAN:
MOVA,sec
SUBBA,#3CH;超過60s歸零
JBCY,CLEAR
MOVsec,#0X00;clr加ram地址無效
CLEAR:
MOVA,sec
MOVB,#0AH
DIVAB;A/B,商存到A中,余數存B中
MOVdisBufDatHead,A
MOVdisBufDatHead+1,B
LCALLDISPLAY
LJMPWHILE;循環
END;
(1)單片機在線時鍾的應用擴展閱讀
51機器周期和指令周期
1、機器周期是指單片機完成一個基本操作所花費的時間,一般使用微秒來計量單片機的運行速度,51單片機的一個機器周期包括12個時鍾振盪周期,也就是說如果51單片機採用12MHz晶振,那麼執行一個機器周期就只需要1μs;如果採用的是6MHz的晶振,那麼執行一個機器周期就需要2μs。
2、指令周期是指單片機執行一條指令所需要的時間,一般利用單片機的機器周期來計量指令周期。在51單片機里有單周期指令(執行這條指令只需一個機器周期),雙周期指令(執行這條指令只需要兩個機器周期),四周期指令(執行這條指令需要四個機器周期)。
除了乘、除兩條指令是四周期指令,其餘均為單周期或雙周期指令。也就是說,如果51單片機採用的是12MHz晶振,那麼它執行一條指令一般只需1~2微秒的時間;如果採用的是6MH晶振,執行一條指令一般就需2~4微秒的時間。
❷ 單片機實現電子時鍾
ORG 0000H ;程序執行開始地址
LJMP START ;跳到標號START執行
ORG 0003H ;外中斷0中斷程序入口
LJMP OUTINTT0 ;外中斷0中斷返回
ORG 000BH ;定時器T0中斷程序入口
LJMP INTT0 ;跳至INTTO執行
ORG 0013H ;外中斷1中斷程序入口
RETI;外中斷1中斷返回
ORG 001BH ;定時器T1中斷程序入口
LJMP INTT1 ;跳至INTT1執行;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 主 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
START:
MOV R0,#70H ;清70H-7AH共11個內存單元
MOV R7,#0BH ;
CLEARDISP:
MOV @R0,#00H ;
INC R0 ;
DJNZ R7,CLEARDISP ;
MOV 70H,#07H;
MOV 71H,#05H;
MOV 76H,#09H;
MOV 77H,#05H;
MOV 78H,#05H;
MOV 79H,#00H;
MOV 20H,#00H ;清20H(標志用)
MOV 7AH,#0AH ;放入"熄滅符"數據
MOV 7BH,#00H ;清報時寄存器
MOV TMOD,#11H ;設T0、T1為16位定時器
MOV TL0,#0B0H ;50MS定時初值(T0計時用)
MOV TH0,#3CH ;50MS定時初值
MOV TL1,#0B0H ;50MS定時初值(T1閃爍定時用)
MOV TH1,#3CH ;50MS定時初值
SETB PT1;定時器T1為高優先順序
SETB EA ;總中斷開放
SETB ET0 ;允許T0中斷
SETB TR0 ;開啟T0定時器
SETB EX0 ;開啟外部中斷0
MOV R4,#14H ;1秒定時用初值(50MS×20)
MOV R2,#06H ;0.3秒的閃動初值(50MS*6)
START1:
LCALL DISPLAY;調用顯示子程序
LCALL BELL;
LCALL DISCLOSE;
SJMP START1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 計時程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T0中斷服務程序
INTT0:
PUSH ACC ;累加器入棧保護
PUSH PSW ;狀態字入棧保護
CLR ET0 ;關T0中斷允許
CLR TR0 ;關閉定時器T0
MOV TL0,#0B0H ;重裝初值(低8位修正值)
MOV TH0,#3CH ;重裝初值(高8位修正值)
SETB TR0 ;開啟定時器T0
DJNZ R4, OUTT0 ;20次中斷未到中斷退出
ADDSS:
MOV R4,#14H ;20次中斷到(1秒)重賦初值
MOV R0,#71H ;指向秒計時單元(70H-71H)
ACALL DBchange ;調用數據處理程序(加1並存入顯示單元)
MOV A,R3 ;秒數據放入A(R3為2位十進制數組合)
CLR C ;清進位標志
CJNE A,#60H,ADDMM ;
ADDMM:
JC OUTT0 ;小於60秒時中斷退出
LCALL CLR0 ;大於或等於60秒時對秒計時單元清0
MOV R0,#77H ;指向分計時單元(76H-77H)
ACALL DBchange ;
MOV A,R3 ;分數據放入A
CLR C ;清進位標志
CJNE A,#60H,ADDHH ;
ADDHH:
JC OUTT0 ;小於60分時中斷退出
ACALL CLR0 ;大於或等於60分時分計時單元清0
MOV R0,#79H ;指向小時計時單元(78H-79H)
ACALL DBchange ;
MOV A,R3 ;時數據放入A
CLR C ;清進位標志
MOV 7BH,#01H
CJNE A,#24H,HOUR ;
HOUR:
JC OUTT0 ;小於24小時中斷退出
ACALL CLR0 ;大於或等於24小時小時計時單元清0
OUTT0:
MOV 72H,76H ;中斷退出時將分、時計時單元數據移
MOV 73H,77H ;入對應顯示單元
MOV 74H,78H ;
MOV 75H,79H ;
POP PSW ;恢復狀態字(出棧)
POP ACC ;恢復累加器
SETB ET0 ;開放T0中斷
RETI ;中斷返回;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 閃動調時 程 序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;T1中斷服務程序,用作時間調整時調整單元閃爍指示
INTT1:
PUSH ACC ;中斷現場保護
PUSH PSW ;
MOV TL1, #0B0H ;裝定時器T1定時初值
MOV TH1, #3CH ;
DJNZ R2,INTT1OUT ;0.3秒未到退出中斷(50MS中斷6次)
MOV R2,#06H ;重裝0.3秒定時用初值
CPL 02H ;0.3秒定時到對閃爍標志取反
JB 02H,FLASH1 ;02H位為1時顯示單元"熄滅"
MOV 72H,76H ;02H位為0時正常顯示
MOV 73H,77H ;
MOV 74H,78H ;
MOV 75H,79H ;
INTT1OUT:
POP PSW ;恢復現場
POP ACC ;
RETI ;中斷退出
FLASH1:
JB 01H,FLASH2 ;01H位為1時,轉小時熄滅控制
MOV 72H,7AH ;01H位為0時,"熄滅符"數據放入分
MOV 73H,7AH ;顯示單元(72H-73H),將不顯示分數據
MOV 74H,78H ;
MOV 75H,79H ;
AJMP INTT1OUT ;轉中斷退出
FLASH2:
MOV 72H,76H ;01H位為1時,"熄滅符"數據放入小時
MOV 73H,77H ;顯示單元(74H-75H),小時數據將不顯示
MOV 74H,7AH ;
MOV 75H,7AH ;
AJMP INTT1OUT ;轉中斷退出
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 數據處理程序,把6個數碼管顯示內容存入相應的地址;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
DBchange:
MOV A,@R0 ;取當前計時單元數據到A
DEC R0 ;指向前一地址
SWAP A ;A中數據高四位與低四位交換
ORL A,@R0 ;前一地址中數據放入A中低四位
ADD A,#01H ;A加1操作
DA A ;十進制調整
MOV R3,A ;移入R3寄存器
ANL A,#0FH ;高四位變0
MOV @R0,A ;放回前一地址單元
MOV A,R3 ;取回R3中暫存數據
INC R0 ;指向當前地址單元
SWAP A ;A中數據高四位與低四位交換
ANL A,#0FH ;高四位變0
MOV @R0,A ;數據放入當削地址單元中
RET ;子程序返回
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 清零程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;對計時單元復零用
CLR0:
CLR A ;清累加器
MOV @R0,A ;清當前地址單元
DEC R0 ;指向前一地址
MOV @R0,A ;前一地址單元清0
RET ;子程序返回
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 時鍾調整中斷程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;當調時按鍵按下時進入此程序
OUTINTT0:
PUSH ACC;
PUSH PSW;
CLR ET0 ;關定時器T0中斷
CLR TR0 ;關閉定時器T0
CLR EX0 ;關閉外部中斷0
MOV R2,#06H ;進入調時狀態,賦閃爍定時初值
SETB ET1 ;允許T1中斷
SETB TR1 ;開啟定時器T1
SET2: JNB P1.0,SET1 ;P1.0口為0(鍵未釋放),等待
SETB 00H ;鍵釋放,分調整閃爍標志置1
SET4:
JB P1.0,SET3 ;p1.0沒有按下時進入分調整程序
LJMP SETHH ;p1.0按下轉調小時狀態
SET3:
LCALL DISPLAY ;等待調分按鍵時時鍾顯示用
JB P1.1,SET4;等待p1.1按下
LCALL DL1S; MOV R0,#77H;按下時加1分鍾操作
LCALL DBchange ;調用加1子程序
MOV A,R3 ;取調整單元數據
CLR C ;清進位標志
CJNE A,#60H,HHH ;調整單元數據與60比較
HHH:
JC SET4 ;調整單元數據小於60轉SET4循環
LCALL CLR0 ;調整單元數據大於或等於60時清0
CLR C ;清進位標志
lJMP SET4 SETHH:
CLR 00H ;分閃爍標志清除(進入調小時狀態)
SETHH1:
JNB P1.0,SET5 ;等待鍵釋放
SETB 01H ;小時調整標志置1
SET6:
JNB P1.0,SETOUT ;P1.0再次按下時退出時間調整
LCALL DISPLAY;
JB P1.1,SET6;等待按鍵按下
LCALL DL1S;
MOV R0,#79H ;按下P1.1時加1小時操作
LCALL DBchange ;調加1子程序
MOV A,R3 ;
CLR C ;
CJNE A,#24H,HOUU ;計時單元數據與24比較
HOUU:
JC SET6;小於24轉SET6循環
LCALL CLR0 ;大於或等於24時清0操作
AJMP SET6;跳轉到SET6循環
SETOUT:
JNB P1.0,SETOUT1 ;調時退出程序。等待鍵釋放
LCALL DISPLAY ;延時削抖
JNB P1.0,SETOUT ;是抖動,返回SETOUT再等待
OUTRETEND:
CLR 01H ;清調小時標志
CLR 00H ;清調分標志
CLR 02H ;清閃爍標志
CLR TR1 ;關閉定時器T1
CLR ET1 ;關定時器T1中斷
SETB TR0 ;開啟定時器T0
SETB ET0 ;開定時器T0中斷(計時開始)
SETB EX0;開啟外部中斷0
POP PSW;
POP ACC;
RETI ;反回主程序
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SET1:
LCALL DISPLAY ;鍵釋放等待時調用顯示程序(調分)
LJMP SET2 ;防止鍵按下時無時鍾顯示
SET5:
LCALL DISPLAY ;鍵釋放等待時調用顯示程序(調小時)
LJMP SETHH1 ;防止鍵按下時無時鍾顯示
SETOUT1:
LCALL DISPLAY ;退出時鍾調整時鍵釋放等待
LJMP SETOUT ;防止鍵按下時無時鍾顯示
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 顯示程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 顯示數據在70H-75H單元內,用六位LED共陽數碼管顯示,P0口輸出段碼數據,P2口作
; 掃描控制,每個LED數碼管亮1MS時間再逐位循環。
DISPLAY:
MOV R1,#70H ;指向顯示數據首址
MOV R5,#01H ;掃描控制字初值
PLAY:
MOV A,R5 ;掃描字放入A
MOV P2,A ;從P2口輸出
MOV A,@R1 ;取顯示數據到A
MOV DPTR,#TAB ;取段碼表地址
MOVC A,@A+DPTR ;查顯示數據對應段碼
MOV P0,A ;段碼放入P0口
LCALL DL1MS ;顯示1MS
INC R1 ;指向下一地址
MOV A,R5 ;掃描控制字放入A
JB ACC.5,ENDOUT ;ACC.5=1時一次顯示結束
RL A ;A中數據循環左移
MOV R5,A ;放回R5內
LJMP PLAY ;跳回PLAY循環
ENDOUT:
MOV P0,#00H ;P0口復位
RET ;子程序返回
TAB: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,00H
;共陰段碼表 "0""1""2" "3""4""5""6""7" "8""9""不亮"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;整點報時;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BELL:
MOV A,7BH;
CLR C;
MOV 7BH,#00H ;
CJNE A,#01H,BELLEND MOV A,79H;
SWAP A;
ORL A,78H;
MOV 7CH ,ABELLRING:
CLR P1.7;
LCALL DL05S;
SETB P1.7;
LCALL DL05S;
DJNZ 7CH,BELLRING; MOV A ,#00H;
MOV 7BH,#00H ;BELLEND:RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;省電模式
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DISCLOSE:
JB P1.3,OUTDISCLOSE;
CLOSE1: MOV P2,#0FFH;
JNB P1.3,CLOSE1;
JB P1.3,CLOSE1;
CLOSE2: JNB P1.3,CLOSE2;
MOV P2,R5;
OUTDISCLOSE:RET;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 延時程序 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;1MS延時程序,LED顯示程序用
DL1MS: MOV R6,#14H
DL1: MOV R7,#19H
DL2: DJNZ R7,DL2
DJNZ R6,DL1
RET
;20MS延時程序,採用調用顯示子程序以改善LED的顯示閃爍現象
DS20MS: ACALL DISPLAY
ACALL DISPLAY
ACALL DISPLAY
RET
;延時程序,用作按鍵時間的長短判斷
DL1S: LCALL DL05S
LCALL DL05S
RET
DL05S: MOV R3,#20H ;8毫秒*32=0.196秒
DL05S1: LCALL DISPLAY
DJNZ R3,DL05S1
RET
END ;程序結束 但是做這個是自己做的,是可以調時間,不要的話可以把那個部分刪除。
❸ 單片機中的時鍾指的是什麼有什麼用通俗點,謝謝
時鍾就是系統的一個基準時間。(一般是與單片機的晶振、機械周期有關,高級一點的可以倍頻或分頻),一般是在寫定時器和計數器時候需要用到,還有就是寫通信協議的時候需要考慮…
❹ 求用單片機c語言做一個電子時鍾,實現調時、顯示、整點報時等功能。
(1)用數字邏輯集成塊實現;
(2)時間以24小時為一個周期,顯示時、分、秒;
(3)計時過程具有報時功能,當時間到達整點前5秒進行蜂鳴報時;
(4)為了保證計時的穩定及准確須由晶體振盪器提供表針時間基準信號。
c51單片機 晶振為11.0592MHz
#include<reg52.h>
#define HOUR1 1
#define HOUR0 0
#define MIN1 2
#define MIN0 8
#define SEC1 2
#define SEC0 0
#define uint unsigned int
#define ulint unsigned long int
#define uchar unsigned char
sbit la=P2^6;
sbit wela=P2^7;
sbit beep=P2^3;
int i;
ulint
sharp,second,count=0,sec0=SEC0,sec1=SEC1,min0=MIN0,min1=MIN1,hour0=HOUR0,hour1=HOUR1;//秒計數全局變數
uchar code segment[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};
uchar code time[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
void delay(uint);//程序毫秒延時
void beeper(uchar);//開蜂鳴器毫秒
void init();//初始化函數
void display();//從數碼管上顯示
void counter();//計算進行過程中的時、分、秒值
void scan();//掃描鍵盤
void main()
{
init();
while(1)
{
scan();//掃描鍵盤看是否有鍵按下
for(i=6;i>0;i--)//動態掃描6位數碼管
{
display();//顯示時、分、秒
}
}
}
void init()
{
second=hour1*36000+hour0*3600+min1*600+min0*60+sec1*10+sec0;
TMOD=0x01;
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
EA=1;
ET0=1;
TR0=1;
}
void delay(uint z)//程序毫秒延時
{
uint x=0,y=0;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void timer0() interrupt 1
{
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
count++;
if(count==20)//判斷是否到1秒
{
counter();//計算進行過程中的時、分、秒值
if(sharp!=hour0) beeper(1000);//判斷小時的值是否改變,變則啟動蜂鳴器
}
}
void beeper(uchar tt)
{
uchar t=tt;
count=0;
beep=0;//開蜂鳴器
delay(t);
beep=1;//關蜂鳴器
}
void display()
{
P0=0xff;//位消影(低電平選擇位)
//送位選信號
wela=1;
P0=segment[i-1];
wela=0;
P0=0x00;//段消影(高電平選擇段)
//送段選信號
la=1;
switch(i)
{
case 6 : P0=time[sec0]; break;
case 5 : P0=time[sec1]; break;
case 4 : P0=time[min0]; break;
case 3 : P0=time[min1]; break;
case 2 : P0=time[hour0]; break;
case 1 : P0=time[hour1]; break;
}
delay(1);
P0=0x00; //配合上面用於消隱
la=0;
}
void counter()
{
second++;
if(second==86400) second=0;
count=0;
sharp=hour0;//設置報時檢測KEY
sec0=second%10;
sec1=(second%60-sec0)/10;
min0=((second%3600-sec1*10-sec0)/60)%10;
min1=((second%3600-sec1*10-sec0)/60-min0)/10;
hour0=(second%36000-min1*600-min0*60-sec1*10-sec0)/3600;
hour1=second/36000;
}
void scan()
{
}