㈠ 請問如何使用單片機定時器製作一個以00-00-00為初始的24小時制時鍾
程序比較長,可用定時器定時50mS,累積20次,即1S,秒加1,60S後分加1,秒清0,60分後,小時加1,分清0 ,24小時後小時清0,這些都在定時器中斷程序中完成,主程序只管顯示時 分 秒即可。
㈡ 單片機電子時鍾怎麼調星期
按鍵控制電路中共有4個按鍵,按鍵1的功能是進行日期,時間的設置。
按下1次,進入「秒」設置;按下2次,進入「分」設置;按下3次,進入「時」設置;按下4次,進入「星期」設置;按下5次,進入「日」設計;按下6次;進入「月」設置;按下7次,進入「年」設置。按鍵2的功能是增加時間或日期。按鍵3的功能是減少時間或日期。按鍵4的功能是數碼管顯示的相應時間進行加或減。
系統上電首先初始化LCD1602和定時器,設置定時器模式、開啟定時器中斷,然後循環執行更新顯示時間,實時掃描按鍵狀態。當單片機上電以後,LCD上會立即顯示出2021. 12.12 SUN 7 21:42:00即2021年12月12號,周日,21 時 42 分 0 秒,通過與實時掃描單片機 IO 口相連接的按鍵的控制可以實現對時間以及模式的調整,以調整到正確的時間和模式。
㈢ 求一個簡單的單片機時鍾程序
#include<reg51.h>
#defineucharunsignedchar
ucharcodeledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsignedcharsec=0,min=0,hour=0,scanled;
unsignedcharkey,time;
unsignedchardisdat[6];
sbitK=P1^0;
voiddischg()
{
disdat[0]=sec%10;
disdat[1]=sec/10;
disdat[2]=min%10;
disdat[3]=min/10;
disdat[4]=hour%10;
disdat[5]=hour/10;
}
voidt0isr()interrupt1 //秒計時
{
TR0=0;
TH0=0x3c;
TL0=0xb0;
TR0=1;
time++;
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
min=0;
hour++;
if(hour>23)hour=0;
}
}
}
dischg();
}
voidt1isr()interrupt3 //顯示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case0:
P2=0x01;
P0=~ledtab[disdat[5]];
break;
case1:
P2=0x02;
P0=~ledtab[disdat[4]]&0x7f;
break;
case2:
P2=0x04;
P0=~ledtab[disdat[3]];
break;
case3:
P2=0x08;
P0=~ledtab[disdat[2]]&0x7f;
break;
case4:
P2=0x10;
P0=~ledtab[disdat[1]];
break;
case5:
P2=0x20;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
EA=1;
TR1=1;
ET0=1;
ET1=1;
sec=0;
min=0;
hour=0;
scanled=0;
time=0;
key=0;
dischg();
while(1)
{
if(K==0)
{
while(K==0);
key++;
key%=2;
}
switch(key)
{
case0:
TR0=1;
break;
case1:
TR0=0;
break;
}
}
}
㈣ 51單片機定時器定時時間t的影響因素有哪些
單片機的定時器,是對系統時鍾脈沖進行計數的,因此定時器的最小定時時間,即響應時間,受制於系統時鍾頻率。
定時器的響應,大都是通過中斷常式來實現,因此,運行起來就包括進入退出中斷常式的基本耗時,以及用戶的應用耗時,都在現實中影響到定時器的最小時間設定。
看見,影響定時器的根本是系統時鍾頻率,可操作的機會不大,在中斷常式中摳點時間吧,主要還是在用戶應用目的上,因此,代碼效率很重要。
不要什麼都放在中斷常式中運行,可通過設置標記,讓大部分代碼在中斷常式外運行。
㈤ 單片機電子時鍾直接設置定時時間,並實時顯示剩餘時間
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
#defineu8unsignedchar
#defineu16unsignedint
sbitk1=P3^1;//第一個按鍵,選擇設置
ucharcodedistab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共陰數碼管段碼表
uchardisbuf[8];//聲明顯示緩沖區8個單元
ucharhour=12;//聲明小時變數,初值為12
ucharminute=59;//聲明分變數,初值為59
ucharsecond;//聲明秒變數
uchart0n;//定時器T0中斷計數,定時50ms,中斷20次為1秒
uchardis;//調時狀態下,顯示小數點位
voiddelay()//延時子程序,用於顯示子程序
{
uintj;
for(j=300;j>0;j--);
}
//顯示子程序,參數dis為顯示小數點位
voiddisplay(uchardis)
{
ucharj,disbit=0x01;//位碼
for(j=0;j<8;j++)
{
P2=~disbit;//P2口輸出位碼
if(dis>0&&dis==j)//調時狀態下,顯示小數點
P0=distab[disbuf[j]]+0x80;//在小時,分,秒位上顯示小數點
else
P0=distab[disbuf[j]];//其它位正常顯示
disbit<<=1;//取下一個位碼
delay();//延時
}
}
#defineRxBUFSIZE10
u8RxBuf[RxBUFSIZE];
u8Rxcount=0;
u8Rxtime=0;
voidUartInit(){
SCON=0x50;
TMOD&=0x0f;
TMOD|=0x20;
TH1=TL1=0xfd;//11.059269600
TR1=1;
ES=1;
EA=1;
}
//格式Txx:xx:xx
//解析時間
voidJX1(){
u8a;
a=(RxBuf[1]-'0')*10+(RxBuf[2]-'0');
if(a>23)return;
hour=a; //時
a=(RxBuf[4]-'0')*10+(RxBuf[5]-'0');
if(a>59)return;
minute=a; //分
a=(RxBuf[7]-'0')*10+(RxBuf[8]-'0');
if(a>59)return;
second=a; //秒
}
voidUartCl(){
if((Rxtime>4)&&(Rxcount>=9)){
if(RxBuf[0]=='T'){
JX1();
}
Rxcount=0;
}
}
voidUartInterrupt()interrupt4
{
if(RI){
RI=0;
Rxtime=0;
if(Rxcount<RxBUFSIZE){
RxBuf[Rxcount++]=SBUF;
}
}
}
voidmain()
{
disbuf[2]=disbuf[5]=10;//數碼管第3,6位顯示-
TMOD=0x01;
TH0=0x3C;//單片機晶振頻率=12M,定時50ms,時間常數=3CB0
TL0=0xB0;
IE=0x82;//開定時器T0中斷
TR0=1;//啟動定時器T0
IT0=1;//設置外部中斷為下降沿有效
IT1=1;
UartInit();
while(1)
{
display(dis);//調顯示子程序
UartCl();
if(k1==0)//選擇設置
{
dis++;//停止計時,進入調時狀態
EX0=1;//調時狀態下,允許外部INT0,INT1中斷
EX1=1;//用來調小時,分,秒
if(dis>7)//調小時,在小時位顯示小數點
{
dis=0;//滅小數點
t0n=0;//調時結束,開始計時
TR0=1;
EX0=0;//關外部中斷
EX1=0;
}
elseif(dis==2)dis=4;//調分,在分位顯示小數點
elseif(dis==5)dis=7;//調秒,在秒位顯示小數點
while(k1==0)display(dis);//等待按鍵釋放
}
if(t0n>=20&&dis==0)//中斷20次,1秒到,計時狀態下時鍾計時
{
t0n=0;
second++;//秒加1
if(second>=60)//到60秒
{
second=0;
minute++;//分加1
if(minute>=60)//到60分
{
minute=0;
hour++;//小時加1
if(hour>=24)
hour=0;
}
}
}
disbuf[0]=hour/10;//顯示小時十位
disbuf[1]=hour%10;//顯示小時個位
disbuf[3]=minute/10;//顯示分十位
disbuf[4]=minute%10;//顯示分個位
disbuf[6]=second/10;//顯示秒十位
disbuf[7]=second%10;//顯示秒個位
}
}
//定時器T0中斷服務子程序
voidT0_isr()interrupt1
{
TH0=0x3C;//重寫時間常數
TL0=0xb0;
t0n++;//中斷次加1
if(++Rxtime>(20*5)){//超時處理
Rxtime=0;
Rxcount=0;
}
}
//外部中斷INT0服務程序,調時狀態下,加1
voidINT0_ISR()interrupt0
{
if(dis==1)//調小時
{
hour++;//小時加1
if(hour>=24)
hour=0;
}
if(dis==4)//調分
{
minute++;//分加1
if(minute>=60)
minute=0;
}
if(dis==7)//調秒
{
second++;//秒加1
if(second>=60)
second=0;
}
}
//外部中斷INT1服務程序,調時狀態下,減1
voidINT1_ISR()interrupt2
{
if(dis==1)//調小時
{
hour--;//小時減1
if(hour==0xff)
hour=23;
}
if(dis==4)//調分
{
minute--;//分減1
if(minute==0xff)
minute=59;
}
if(dis==7)//調秒
{
second--;//秒減1
if(second==0xff)
second=59;
}
}
㈥ 用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;
(6)單片機定時時鍾擴展閱讀
51機器周期和指令周期
1、機器周期是指單片機完成一個基本操作所花費的時間,一般使用微秒來計量單片機的運行速度,51單片機的一個機器周期包括12個時鍾振盪周期,也就是說如果51單片機採用12MHz晶振,那麼執行一個機器周期就只需要1μs;如果採用的是6MHz的晶振,那麼執行一個機器周期就需要2μs。
2、指令周期是指單片機執行一條指令所需要的時間,一般利用單片機的機器周期來計量指令周期。在51單片機里有單周期指令(執行這條指令只需一個機器周期),雙周期指令(執行這條指令只需要兩個機器周期),四周期指令(執行這條指令需要四個機器周期)。
除了乘、除兩條指令是四周期指令,其餘均為單周期或雙周期指令。也就是說,如果51單片機採用的是12MHz晶振,那麼它執行一條指令一般只需1~2微秒的時間;如果採用的是6MH晶振,執行一條指令一般就需2~4微秒的時間。
㈦ 如何做一個單片機電子時鍾
這個很簡單啊,兩種思路:1,用單片機定時器來做,優點是外圍電路簡單,只需要一個單片機最小系統,和一個顯示模塊(1602液晶比較好);缺點是:定時不是很准,跑的時間長了會有誤差,而且主要是程序,要寫很多,不過程序不是很難。2,用時鍾晶元,一般都用DS1302,還需要單片機最小系統和顯示模塊,優點是:定時准確,誤差很小,在有備用電池的情況下,即使單片機掉電,也可以維持很長時間,程序相對簡單。缺點是:外圍電路比前者相對復雜一點。如果想做個實際的東西拿來用,建議使用第二種方法,如果是想鍛煉自己的編程能力的話,選第一種吧。祝成功!
㈧ 單片機定時器時鍾設計程序,急求
#include<reg51.h>
#define uchar unsigned char
uchar code ledtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0-9
unsigned char sec=0,min=0,hour=12,scanled;
unsigned char key,flashbit,mode,time;
unsigned char disdat[6];
sbit led=P1^0;
void delay(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<120;j++);
}
void dischg()
{
disdat[0]=sec%10;
disdat[1]=sec/10;
disdat[2]=min%10;
disdat[3]=min/10;
disdat[4]=hour%10;
disdat[5]=hour/10;
}
void flash()
{
switch(flashbit)
{
case 0:break;
case 1:
disdat[4]=0x10;
disdat[5]=0x10;
delay(50);
dischg();
delay(80);
break;
case 2:
disdat[2]=0x10;
disdat[3]=0x10;
delay(50);
dischg();
delay(80);
break;
case 3:
disdat[0]=0x10;
disdat[1]=0x10;
delay(50);
dischg();
delay(80);
break;
default:break;
}
}
void t0isr() interrupt 1 //秒計時
{
TH0=0x3c;
TL0=0xb0;
time++;
switch(mode)
{
case 0:
if(time==20)
{
time=0;
sec++;
if(sec>59)
{
sec=0;
min++;
if(min>59)
{
hour++;
if(hour>23)hour=0;
}
}
}
break;
case 1:
if(time==20)
{
time=0;
if(sec>0)sec--;
else if(min>0){sec=59;min--;}
else if(hour>0){sec=59;min=59;hour--;}
else {hour=0;min=0;sec=0;}
}
break;
}
dischg();
}
void t1isr() interrupt 3 //顯示
{
TH1=0xec;
TL1=0x78;
switch(scanled)
{
case 0:
P2=0x01;
P0=~ledtab[disdat[5]];
break;
case 1:
P2=0x02;
P0=~ledtab[disdat[4]];
break;
case 2:
P2=0x04;
P0=~ledtab[disdat[3]];
break;
case 3:
P2=0x08;
P0=~ledtab[disdat[2]];
break;
case 4:
P2=0x10;
P0=~ledtab[disdat[1]];
break;
case 5:
P2=0x20;
P0=~ledtab[disdat[0]];
break;
default:break;
}
scanled++;
scanled%=6;
}
main()
{
TMOD=0x11;
TH0=0x3c;
TL0=0xb0;
TH1=0xec;
TL1=0x78;
EA=1;
TR1=1;
ET0=1;
ET1=1;
sec=0;
min=0;
hour=12;
flashbit=0;
scanled=0;
time=0;
mode=0;
dischg();
while(1)
{
flash();//閃爍
// led=1;
if((P3&0x0f)!=0x0f){
key=P3&0x0f;
while((P3&0x0f)!=0x0f);
led=0;
delay(10);
key|=0xf0;
switch(~key)
{
case 0x01: //p3.1選擇調時、分、秒
TR0=0;
flashbit+=1;
if(flashbit>3){flashbit=0;TR0=1;}
break;
case 0x02: //p3.2調數
if(flashbit==0)break;
if(flashbit==1)
{
hour++;
if(hour>23)hour=0;
}
if(flashbit==2)
{
min++;
if(min>59)min=0;
}
if(flashbit==3)
{
sec++;
if(sec>59)sec=0;
}
break;
case 0x04: //選擇正/倒
TR0=0;
mode++;
mode&=0x01;
if(mode==0){sec=0;min=0;hour=0;}
dischg();
break;
case 0x08: //啟動/暫停
TR0=~TR0;
break;
default:break;
}
}
}
}