導航:首頁 > 編程語言 > 89c51單片機時鍾程序

89c51單片機時鍾程序

發布時間:2023-11-26 21:05:02

❶ 89c51單片機的數字鍾程序

/*********************************************
ILONG編做
【注意P3口輸出模擬和在{實驗板}上不一樣。實驗板不用取反】
【目的】:用20次T0定時產生1s.進而形成 HH-mm-ss時間
【參數說明】:
40H~47H :顯示管,每位暫存器,存放要顯示的數碼的地址。可根據地址加1,實現該位數加1;
並且低4位可以代表管子要顯示的值(42H、45H除外)。
48H :要顯示的位值(0~7,由解碼器翻譯出)
49H :每位每次刷出時要顯示的時間0~256us
4A :20次定時,的次數計數器
4BH,4CH :小時十位進位刷0,時,小時兩位數的暫存
4DH :調試時,要調整類型,每次INT0中斷自增一次
50H~5FH :0~F 16個數的碼值
60H :"-"的碼值
61H :"空" 的碼值
62H,63H :要閃的兩位地址暫存 (好像沒用著)
R0 :存放 每位暫存器 的地址,用於 刷新位時 移位
00H(位) :是否有INT0(調整)中斷
01H(位) :是閃亮,還是閃空,即:閃爍時的亮暗狀態
【存在問題】:
1,調整時間時,分鍾位開始亂碼。
2,調整時間時,必須亮的時候才能調
3,時間差:慢於實際時間
2011.10.21 ilong(crazy night)
*********************************************/
SJMP 0x0030
ORG 0x0030
MAIN:
//啟動外部中斷
SETB IT0
SETB IE0
SETB EX0
SETB PX0
SETB IT1
SETB IE1
SETB EX1
SETB PX1
SETB EA
CLR 00H //沒有調整中斷
CLR 01H //閃空
MOV 4DH,#04H //0xFC
MOV P3,#0FH
MOV 62H,46H //從分開始閃
MOV 63H,47H
//十位數********************
MOV 50H,#3FH
MOV 51H,#06H
MOV 52H,#5BH
MOV 53H,#4FH
MOV 54H,#66H
MOV 55H,#6DH
MOV 56H,#7DH
MOV 57H,#07H
MOV 58H,#7FH
MOV 59H,#6FH
MOV 5AH,#77H
MOV 5BH,#7CH
MOV 5CH,#39H
MOV 5DH,#5EH
MOV 5EH,#79H
MOV 5FH,#71H
MOV 60H,#40H
MOV 61H,#00H
//八位管的暫存 從左到右40-47
MOV 40H,#50H
MOV 41H,#50H
MOV 42H,#60H
MOV 43H,#50H
MOV 44H,#50H
MOV 45H,#60H
MOV 46H,#50H
MOV 47H,#50H
MOV 48H,#00H //掃描位暫存
MOV R0,#40H //掃描值地址
MOV 4AH,00H //20次定時 計數
LCALL TIMER_GO20 //開啟並初始定時器
//主函數進程,就是掃描碼管值並顯示,其他為中斷操作***************************************************
SCAN: //顯示器掃描輸出*************************************
MOV P2,48H //選擇顯示位(從左到右0-7)
MOV A,@R0 //獲取該位的數碼值 地址
MOV R1,A
MOV A,@R1 //獲取該位碼值
//CPL A //根據數碼管是共陰、共陽 是否取反
MOV P0,A //從P0輸出每位的碼值,注意:該埠時下面的「清屏」一起改
LCALL DELAY //進入每位延時
MOV P0,#0FFH //清屏
INC 48H //暫存器後移
INC R0 //位後移
MOV A,48H //通過 (48H)的值+08H 判斷是否到了 位尾
ADD A,#08H
JB 0D6H,RER //D6H(位)為AC(輔助進位:半進位)。為1時說明(48H)的值+08H=F,即(48H)=8,此時跳向RER
SJMP SCAN
RER: //掃描重置
CLR 0D6H //重置 AC(輔助進位:半進位)
MOV 48H,#00H
MOV R0,#40H
SJMP SCAN
//End 主函數*********************************************************************************************
DELAY: //延時,用於掃描7段管時,在每一位停留的時間.時間太短,回使不該亮的段也有些亮
MOV 49H,#25H //49H的值不可以等於FF,因為FF取反後49H為0,不會延遲了
MOV A,0FEH //用取反設置循環次數,
CPL A
MOV 49H,A
ADD_1:
INC 49H
MOV R1,49H //因為DJNZ判斷完後要把判斷的地址減去1,所以為了DJNZ不對49H的內容造成影響,把49H的值裝到R1中去判斷
DJNZ R1,ADD_1
RET
//20次定時*********************************************************************************************************
TIMER_GO20:
//用4AH 設置循環次數*********************************
MOV 4AH,#15H //20(=0x15)次定時
MOV A,4AH //用取反設置定時次數,
CPL A
MOV 4AH,A
SJMP TIMER_S
TIMER_GO5: //與TIMER_GO20類似,只是這里只讓定時5次一循環。用於調整閃爍
MOV 4AH,#05H //5(=0x05)次定時
MOV A,4AH //用取反設置定時次數,
CPL A
MOV 4AH,A
TIMER_S://未重置(4AH)的調用,
//設置啟動T0
MOV TMOD,#01H //設置模式:T0模式1
MOV TH0,#3CH //T0初值高8位
MOV TL0,#0AH //T0初值低8位
//CLR TF0 //未知問題
SETB ET0 //T0允許中斷
SETB EA //CPU允許中斷
SETB TR0 //啟動T0
RET
T0_INT: //T0中斷程序段
CPL P1.7 //測試埠:T0重新定時一次發生一次跳轉
LCALL TIMER_S //T0重新定時,繼續跑。但:不會初始化20次計數
INC 4AH //T0定時次數加1
MOV A,4AH
JNZ CY_20 //50H加到FF再加就到0了。不為0回去接著執行主程序;為0 則20次定時 溢出即:00H(位)為1
CPL P1.6 //測試埠每秒發生一次跳轉
JB 00H,GO_BLINK //如果00H(位)被置1,則不再執行時間系統加1。用於調整時顯示閃爍
LCALL CLOCK_GO //時間系統加1秒
LCALL TIMER_GO20 //20次重新開始
SJMP CY_20
GO_BLINK:
LCALL TIMER_GO5 //5次重新開始,
LCALL BLINK
CY_20: RET
//時間系統進位設置*******************************************************************************************
CLOCK_GO:
INC 47H //秒加1
//個位秒 進位 十位
MOV A,#5AH //主要是看"#5A"中的「A」,
SUBB A,47H
JNZ SS_OUT //如果(47H)值 低4 與A中的低4不相同,跳到「SS_OUT」,不進位
MOV 47H,#50H
INC 46H
SS_OUT:
//秒 進位 分
MOV A,#56H //
SUBB A,46H
JNZ SM_OUT //如果(46H)值 低4 與A中的低4不相同,跳到「SS_OUT」,不進位
MOV 46H,#50H
CLOCK_GO_M:INC 44H
//分調整用
SM_OUT:
//分個位 進位 分
MOV A,#5AH //
SUBB A,44H
JNZ MM_OUT //如果(44H)值 低4 與A中的低4不相同,跳到「SS_OUT」,不進位
MOV 44H,#50H
INC 43H
MM_OUT:
//分 進位 時
MOV A,#56H //
SUBB A,43H
JNZ MH_OUT //如果(43H)值 低4 與A中的低4不相同,跳到「SS_OUT」,不進位
MOV 43H,#50H
CLOCK_GO_H:INC 41H
//時調整用
MH_OUT:
//時個位 進位 時
MOV A,#5AH //
CLR CY //排除借位影響
SUBB A,41H
JNZ HH_OUT //如果(41H)值 低4 與A中的低4不相同,跳到「SS_OUT」,不進位
MOV 41H,#50H
INC 40H
HH_OUT:
//時十位置0
MOV 4BH,40H //為了不影響暫存器數據,把40H、41H轉到4BH、4CH中進行 操作
MOV 4CH,41H
MOV A,4BH
SWAP A //獲得小時十位數,並放到A的高4位上
ANL A,#0F0H //清0低4位
ANL 4CH,#0FH //小時個位 高4位清0
ADD A,4CH //小時的十位與個位相加(高4位來自小時的十位暫存器40H,低四位來自小時個位的寄存器41H)
SUBB A,#24H
JNZ HD_OUT //如果(46H)值 低4 與A中的低4不相同,跳到「SS_OUT」,不進位
MOV 41H,#50H //個位 清零
MOV 40H,#50H //十位清零
HD_OUT:
CG_OUT: RET
//END 時間系統進位設置*******************************************************************************************
//INTO中斷程序段*********************************************************************************
INT0_INT:
SETB 00H
CPL P1.5
CPL P1.5
CLR 01H //使得在換位閃爍時不會把上位的數帶給下一位,
HMS_BACK: //在每次換位時都要把,被放到暫存上的值那回去,使其顯示出來
MOV A,4DH
CJNE A,#02H,BSH_S //back second OR hour _select
LCALL LIGHT_M
SJMP B_END
BSH_S: //恢復秒小時選擇
JB CY,B_H
SJMP B_S
B_S: LCALL LIGHT_S //把調好的數據裝回暫存器
SJMP B_END
B_H: LCALL LIGHT_H
B_END:
// CLR TR0 //定時器0,停止計時
DEC 4DH //調整類型(時、分、秒)改變
MOV A,4DH
JNZ INT0_OUT //是否恢復時鍾
CLR 00H //置0,調整中斷(ilong 定義)
CLR 01H
MOV 4DH,#04H //初始化調整類型

INT0_OUT:
RET
////閃爍*****************************************************************
BLINK:
CPL P1.1
CPL 01H
MOV A,4DH
CJNE A,#02H,SH_S
SJMP MM_SET
SH_S: //閃爍秒小時選擇
JB CY,HH_SET
SJMP SS_SET
SS_SET: //秒鍾設置****************
JB 01H,DACK_S
LIGHT_S:
MOV 46H,4EH
MOV 47H,4FH
SJMP BLINK_OUT
DACK_S:
MOV 4EH,46H
MOV 4FH,47H
MOV 46H,#61H
MOV 47H,#61H
RET
MM_SET: // 分鍾設置**************
JB 01H,DACK_M
LIGHT_M:
MOV 43H,4EH
MOV 44H,4FH
SJMP BLINK_OUT
DACK_M:
MOV 4EH,43H
MOV 4FH,44H
MOV 43H,#61H
MOV 44H,#61H
RET
HH_SET: //小時設置****************
JB 01H,DACK_H
LIGHT_H:
MOV 40H,4EH
MOV 41H,4FH
SJMP BLINK_OUT
DACK_H:
MOV 4EH,40H
MOV 4FH,41H
MOV 40H,#61H
MOV 41H,#61H
BLINK_OUT:RET
//INT1中斷程序段***************************************************************
INT1_INT:
//lcall HMS_BACK
//clr tr0
CPL P1.4
MOV A,4DH
CJNE A,#02H,ADDSH_S //ADD Hour OR ADD second OR _select
SJMP ADD_M
ADDSH_S: //調整秒小時選擇
JB CY,ADD_H
SJMP ADD_S
ADD_S: LCALL CLOCK_GO
SJMP ADD_END
ADD_M: LCALL CLOCK_GO_M
SJMP ADD_END
ADD_H: LCALL CLOCK_GO_H
ADD_END:
// LCALL CLOCK_GO
RET
/*********************************************************************************
最後放中斷保險些
*********************************************************************************/
//T0中斷程序***************
ORG 000BH
LCALL T0_INT
RETI
//INT0中斷*****************
ORG 0003H
LCALL INT0_INT
RETI
//INT1中斷*****************
ORG 0013H
LCALL INT1_INT
RETI
END

❷ 用C語言編寫AT89C51單片機程序,設計一個智能數字鍾。

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char

sbit QB1=P1^0;
sbit QB2=P1^1; //數碼管段選
sbit QB3=P1^2;
sbit QB4=P1^3;
sbit QB5=P1^4;
sbit QB6=P1^5;
sbit fm=P1^6; //蜂鳴器
sbit s1=P2^4; //s5按鍵,切換顯示
sbit s2=P2^3; //s2按鍵,設置調時
sbit s3=P2^2; //s3按鍵,加1
sbit s4=P2^1; //s4按鍵,減1

sbit led1=P0^0;
sbit led2=P0^1;
sbit led3=P0^2;

uchar count;
uchar sec,minu,hour,day,week,mon;
uchar n_sec,n_minu,n_hour;
uint year;
uchar set_2=1,set_1=1;
uchar hs,hg,mis,mig,ss,sg;
uchar nhs,nhg,nms,nmg,nss=0,nsg=0;
uchar ms,mg,ds,dg,w;
uchar code table[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,
0X90,0X88,0X83,0XC6,0XA1,0X8E,0X86,0xbf}; //0~F,-,共陽
//uchar code tableyi[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
//0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};//0-F,-,共陰
uchar code table_d[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
0x87,0xff,0xef}; //0~9數組,帶小數點

uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; //閏年
uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; //非閏年

void delay(uint); //延時函數
void timer0(); //走時中斷函數
void jishi(); //計時函數
void key_change(); //切換顯示按鍵函數
void key_set(); //設置時間按鍵函數
void disp(uchar,uchar,uchar,uchar,uchar,uchar); //顯示函數
void zd_clock(); //整點報時函數
void nz_clock(); //鬧鍾函數
uchar incone(uchar); //加1函數
uchar decone(uchar); //減1函數
void set_time(); //設置時間函數
void set_clock(); //設置鬧鍾函數
void set_mdw(); //設置月日星期函數

void main() //主函數
{
EA=1;
ET0=1;
TR0=1;
TMOD=0x01;
TH0=0x4c; //50ms初值 晶振11.0592
TL0=0x00;
hour=23;minu=59;sec=49; //賦初值:11點59分0秒
n_hour=12;n_minu=56;n_sec=0; //鬧鍾賦初值12點1分0秒
year=2008;mon=5;day=14;week=3;//年月日星期賦初值2008年5月11日星期天;祝天下所有母親節日快樂
while(1)
{
hs=hour/10; //時分秒HH.MM.SS
hg=hour%10;
mis=minu/10;
mig=minu%10;
ss=sec/10;
sg=sec%10;

ms=mon/10; //月日-星期MM.DD.-W
mg=mon%10;
ds=day/10;
dg=day%10;
w=week;

nhs=n_hour/10; //鬧鍾定時HH.MM.SS
nhg=n_hour%10;
nms=n_minu/10;
nmg=n_minu%10;
nss=n_sec/10;
nsg=n_sec%10;

key_change(); //s4按鍵掃描
key_set(); //s2按鍵掃描
set_time(); //設置時間
set_mdw(); //設置月日星期
set_clock(); //設置鬧鍾
if(set_1==1) //正常走時顯示
{
disp(hs,hg,mis,mig,ss,sg);
}
if(set_1==2) //設置時間,LED1閃亮
{
disp(hs,hg,mis,mig,ss,sg);
if(sec%2==0)
{led2=1;led3=1;led1=~led1;}
// else
// {led1=1;}
}
if(set_1==3) //正常顯示月日-星期
{
disp(ms,mg,ds,dg,16,w);
}
if(set_1==4) //設置月日-星期,LED2閃亮
{
disp(ms,mg,ds,dg,16,w);
if(sec%2==0)
{led1=1;led3=1;led2=~led2;}

// else
// {led2=1;}
}

if(set_1==5) //正常顯示定時
{
disp(nhs,nhg,nms,nmg,nss,nsg);
}
if(set_1==6) //設置鬧鍾定時,LED3閃亮
{
disp(nhs,nhg,nms,nmg,nss,nsg);
if(sec%2==0)
{led1=1;led2=1;led3=~led3;}

// else
// {led3=1;}
}

zd_clock(); //整點報時
nz_clock(); //鬧鍾
}

}

void timer0() interrupt 1 //50ms中斷函數

{
TMOD=0x01;
TH0=0x4c; //50ms初值 晶振11.0592
TL0=0x00;
count++;
if(count==20)
{
count=0;
sec++;
jishi(); //調計時函數
}
}

void jishi() //計時函數
{
if(sec==60)
{
sec=0;
minu++;
if(minu==60)
{
minu=0;
hour++;
if(hour==24)
{ hour=0;
day++;
week++;
if(week==8)
{week=0;}
if(year%4==0&&year%100!=0||year%400==0) //閏年
{
if(day==table1[mon]+1)
{
day=0;
mon++;
if(mon==13)
{mon=0;year++;}
}
}
else //非閏年
{
if(day==table2[mon]+1)
{
day=0;
mon++;
if(mon==13)
{mon=0;year++;}
}
}

}
}
}
}

void key_change() //s1按鍵掃描
{
if(s1==0)
{
delay(200);
if(s1==0)
{
set_1++;
while(!s1);
if(set_1==7)
{set_1=1;}
}
}
}

void key_set() //s2按鍵掃描
{
if(s2==0)
{
delay(10);
if(s2==0)
{
set_2++;
while(!s2);
if(set_2==4)
{set_2=1;}
}
}
}
void disp(uchar a1,uchar a2,uchar a3,uchar a4,uchar a5,uchar a6) //顯示函數
{
QB1=1;
QB2=0;
QB3=0;
QB4=0;
QB5=0;
QB6=0;
P3=table[a1]; //段碼送P0口
delay(10); //延時一小會
QB1=0;
QB2=1;
QB3=0;
QB4=0;
QB5=0;
QB6=0;
P3=table[a2]; //第2個數碼管顯示,帶小數點
delay(10);
QB1=0;
QB2=0;
QB3=1;
QB4=0;
QB5=0;
QB6=0;

P3=table[a3]; //第3個數碼管顯示
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=1;
QB5=0;
QB6=0;

P3=table[a4]; //第4個數碼管顯示,帶小數點
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=0;
QB5=1;
QB6=0;

//第5個數碼管顯示
P3=table[a5];
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=0;
QB5=0;
QB6=1;

P3=table[a6]; //第6個數碼管顯示
delay(10);
QB1=0;
QB2=0;
QB3=0;
QB4=0;
QB5=0;
QB6=0;

}

void zd_clock() //整點報時函數
{
if(minu==59&&(sec==53||sec==55||sec==57))
{
fm=0;
delay(5);
fm=1;
delay(5);
}
fm=0;
if(minu==59&&sec==59)
{
fm=0;
delay(5);
fm=1;
delay(5);
fm=0;
}
}

void nz_clock() //鬧鍾函數
{
if(hour==n_hour&&minu==n_minu&&sec==n_sec)
//if((sec%2==0)&&sec<30)
{
fm=0;
delay(1);
fm=1;
delay(1);
}
}

void set_time() //設置時間函數
{
if(set_1==2)
{
if(set_2==1)
{
hour=incone(hour);
if(hour==24)
{hour=0;}
// if(hour<0)
// {hour=23;}
hour=decone(hour);

}
if(set_2==2)
{
minu=incone(minu);
if(minu==60)
{minu=0;}
// if(minu<0)
// {minu=59;}
minu=decone(minu);

}
}
}

void set_mdw() //設置月日星期函數
{
if(set_1==4)
{
if(set_2==1)
{
mon=incone(mon);
if(mon==13)
{mon=1;}
mon=decone(mon);
// if(mon==0)
// {mon=12;}
}
if(set_2==2)
{
day=incone(day);
if(day==32)
{day=0;}
day=decone(day);
// if(day==0)
// {day=0;}
}
if(set_2==3)
{
week=incone(week);
if(week==8)
{week=0;}
week=decone(week);
// if(week==0)
// {week=7;}
}
}
}

void set_clock() //設置鬧鍾函數
{
if(set_1==6)
{
if(set_2==1)
{
n_hour=incone(n_hour);
if(n_hour==24)
{n_hour=0;}
n_hour=decone(n_hour);
if(n_hour==0)
{n_hour=0;}
}
if(set_2==2)
{
n_minu=incone(n_minu);
if(n_minu==60)
{n_minu=0;}
n_minu=decone(n_minu);
if(n_minu==0)
{n_minu=0;}
}
}

}

uchar incone(uchar n) //加1函數
{
if(s3==0)
{ delay(200);
if(s3==0)
{
n++;
while(!s3);
}
}
return(n);
}

uchar decone(uchar m) //減1函數
{
if(s4==0)
{
delay(200);
if(s4==0)
{
m--;
while(!s4);
if(m<0)
{m=0;}
}
}
return(m);
}

void delay(uint k) //延時函數
{
uint i,j;
for(i=k;i>0;i--)
for(j=80;j>0;j--);
}

閱讀全文

與89c51單片機時鍾程序相關的資料

熱點內容
bpn配置文件 瀏覽:932
501完美越獄工具 瀏覽:119
中間夾菜單裡面不能顯示壓縮文件 瀏覽:952
如何指導小學生參加編程比賽 瀏覽:275
物業的招標文件有哪些 瀏覽:452
保存游戲文件名非法或只讀 瀏覽:258
js怎麼做圖片時鍾 瀏覽:451
華為應用裡面有了app說明什麼 瀏覽:801
資料庫中xy是什麼意思 瀏覽:893
u盤打不開提示找不到應用程序 瀏覽:609
網站功能介紹怎麼寫 瀏覽:954
word在試圖打開文件時錯誤 瀏覽:108
主板無vga插槽怎麼連接編程器 瀏覽:521
錄視頻文件在哪裡刪除 瀏覽:881
word2013如何插入文件 瀏覽:233
proe教程百度網盤 瀏覽:197
如何控制遠程linux伺服器 瀏覽:740
it教學app有哪些 瀏覽:34
怎麼在ps摳的圖變成矢量文件 瀏覽:405
口袋妖怪銀魂安卓v11 瀏覽:1

友情鏈接