導航:首頁 > 操作系統 > 單片機數字時鍾程序

單片機數字時鍾程序

發布時間:2023-05-19 08:26:06

Ⅰ 用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--);
}

Ⅱ 單片機做時鍾程序

基於DS1302的日歷時鍾
#include<reg51.h> //包含單片機寄存器的頭文件
#include<intrins.h> //包含_nop_()函數定義的頭文件
/***********************************************************************
以下是DS1302晶元的操作程序
************************************************************************/
unsigned char code digit[10]={"0123456789"}; //定義字元數組顯示數字
sbit DATA=P1^1; //位定義1302晶元的介面,數據輸出端定義在P1.1引腳
sbit RST=P1^2; //位定義1302晶元的介面,復位埠定義在P1.1引腳
sbit SCLK=P1^0; //位定義1302晶元的介面,時鍾輸出埠定義在P1.1引腳
/*****************************************************
函數功能:延時若干微秒
入口參數:n
***************************************************/
void delaynus(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
;
}
/*****************************************************
函數功能:向1302寫一個位元組數據
入口參數:x
***************************************************/
void Write1302(unsigned char dat)
{
unsigned char i;
SCLK=0; //拉低SCLK,為脈沖上升沿寫入數據做好准備
delaynus(2); //稍微等待,使硬體做好准備
for(i=0;i<8;i++) //連續寫8個二進制位數據
{
DATA=dat&0x01; //取出dat的第0位數據寫入1302
delaynus(2); //稍微等待,使硬體做好准備
SCLK=1; //上升沿寫入數據
delaynus(2); //稍微等待,使硬體做好准備
SCLK=0; //重新拉低SCLK,形成脈沖
dat>>=1; //將dat的各數據位右移1位,准備寫入下一個數據位
}

}
/*****************************************************
函數功能:根據命令字,向1302寫一個位元組數據
入口參數:Cmd,儲存命令字;dat,儲存待寫的數據
***************************************************/
void WriteSet1302(unsigned char Cmd,unsigned char dat)
{
RST=0; //禁止數據傳遞
SCLK=0; //確保寫數居前SCLK被拉低
RST=1; //啟動數據傳輸
delaynus(2); //稍微等待,使硬體做好准備
Write1302(Cmd); //寫入命令字
Write1302(dat); //寫數據
SCLK=1; //將時鍾電平置於已知狀態
RST=0; //禁止數據傳遞
}
/*****************************************************
函數功能:從1302讀一個位元組數據
入口參數:x
***************************************************/
unsigned char Read1302(void)
{
unsigned char i,dat;
delaynus(2); //稍微等待,使硬體做好准備
for(i=0;i<8;i++) //連續讀8個二進制位數據
{
dat>>=1; //將dat的各數據位右移1位,因為先讀出的是位元組的最低位
if(DATA==1) //如果讀出的數據是1
dat|=0x80; //將1取出,寫在dat的最高位
SCLK=1; //將SCLK置於高電平,為下降沿讀出
delaynus(2); //稍微等待
SCLK=0; //拉低SCLK,形成脈沖下降沿
delaynus(2); //稍微等待
}
return dat; //將讀出的數據返回
}
/*****************************************************
函數功能:根據命令字,從1302讀取一個位元組數據
入口參數:Cmd
***************************************************/
unsigned char ReadSet1302(unsigned char Cmd)
{
unsigned char dat;
RST=0; //拉低RST
SCLK=0; //確保寫數居前SCLK被拉低
RST=1; //啟動數據傳輸
Write1302(Cmd); //寫入命令字
dat=Read1302(); //讀出數據
SCLK=1; //將時鍾電平置於已知狀態
RST=0; //禁止數據傳遞
return dat; //將讀出的數據返回
}
/*****************************************************
函數功能: 1302進行初始化設置
***************************************************/
void Init_DS1302(void)
{
WriteSet1302(0x8E,0x00); //根據寫狀態寄存器命令字,寫入不保護指令
WriteSet1302(0x80,((0/10)<<4|(0%10))); //根據寫秒寄存器命令字,寫入秒的初始值
WriteSet1302(0x82,((0/10)<<4|(0%10))); //根據寫分寄存器命令字,寫入分的初始值
WriteSet1302(0x84,((12/10)<<4|(12%10))); //根據寫小時寄存器命令字,寫入小時的初始值
WriteSet1302(0x86,((16/10)<<4|(16%10))); //根據寫日寄存器命令字,寫入日的初始值
WriteSet1302(0x88,((11/10)<<4|(11%10))); //根據寫月寄存器命令字,寫入月的初始值
WriteSet1302(0x8c,((8/10)<<4|(8%10))); //根據寫小時寄存器命令字,寫入小時的初始值
}
/*******************************************************************************
以下是對液晶模塊的操作程序
*******************************************************************************/
sbit RS=P2^0; //寄存器選擇位,將RS位定義為P2.0引腳
sbit RW=P2^1; //讀寫選擇位,將RW位定義為P2.1引腳
sbit E=P2^2; //使能信號位,將E位定義為P2.2引腳
sbit BF=P0^7; //忙碌標志位,,將BF位定義為P0.7引腳
/*****************************************************
函數功能:延時1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以認為是1毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函數功能:延時若干毫秒
入口參數:n
***************************************************/
void delaynms(unsigned char n)
{
unsigned char i;
for(i=0;i<n;i++)
delay1ms();
}
/*****************************************************
函數功能:判斷液晶模塊的忙碌狀態
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/
bit BusyTest(void)
{
bit result;
RS=0; //根據規定,RS為低電平,RW為高電平時,可以讀狀態
RW=1;
E=1; //E=1,才允許讀寫
_nop_(); //空操作
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
result=BF; //將忙碌標志電平賦給result
E=0; //將E恢復低電平
return result;
}
/*****************************************************
函數功能:將模式設置指令或顯示地址寫入液晶模塊
入口參數:dictate
***************************************************/
void WriteInstruction (unsigned char dictate)
{
while(BusyTest()==1); //如果忙就等待
RS=0; //根據規定,RS和R/W同時為低電平時,可以寫入指令
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
_nop_();
_nop_(); //空操作兩個機器周期,給硬體反應時間
P0=dictate; //將數據送入P0口,即寫入指令或地址
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:指定字元顯示的實際地址
入口參數:x
***************************************************/
void WriteAddress(unsigned char x)
{
WriteInstruction(x|0x80); //顯示位置的確定方法規定為"80H+地址碼x"
}
/*****************************************************
函數功能:將數據(字元的標准ASCII碼)寫入液晶模塊
入口參數:y(為字元常量)
***************************************************/
void WriteData(unsigned char y)
{
while(BusyTest()==1);
RS=1; //RS為高電平,RW為低電平時,可以寫入數據
RW=0;
E=0; //E置低電平(根據表8-6,寫指令時,E為高脈沖,
// 就是讓E從0到1發生正跳變,所以應先置"0"
P0=y; //將數據送入P0口,即將數據寫入液晶模塊
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=1; //E置高電平
_nop_();
_nop_();
_nop_();
_nop_(); //空操作四個機器周期,給硬體反應時間
E=0; //當E由高電平跳變成低電平時,液晶模塊開始執行命令
}
/*****************************************************
函數功能:對LCD的顯示模式進行初始化設置
***************************************************/
void LcdInitiate(void)
{
delaynms(15); //延時15ms,首次寫指令時應給LCD一段較長的反應時間
WriteInstruction(0x38); //顯示模式設置:16×2顯示,5×7點陣,8位數據介面
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x38);
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x38); //連續三次,確保初始化成功
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x0c); //顯示模式設置:顯示開,無游標,游標不閃爍
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x06); //顯示模式設置:游標右移,字元不移
delaynms(5); //延時5ms,給硬體一點反應時間
WriteInstruction(0x01); //清屏幕指令,將以前的顯示內容清除
delaynms(5); //延時5ms,給硬體一點反應時間

}
/**************************************************************
以下是1302數據的顯示程序
**************************************************************/
/*****************************************************
函數功能:顯示秒
入口參數:x
***************************************************/
void DisplaySecond(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x49); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}

/*****************************************************
函數功能:顯示分鍾
入口參數:x
***************************************************/
void DisplayMinute(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x46); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示小時
入口參數:x
***************************************************/
void DisplayHour(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x43); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示日
入口參數:x
***************************************************/
void DisplayDay(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x0c); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示月
入口參數:x
***************************************************/
void DisplayMonth(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x09); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}
/*****************************************************
函數功能:顯示年
入口參數:x
***************************************************/
void DisplayYear(unsigned char x)
{
unsigned char i,j; //j,k,l分別儲存溫度的百位、十位和個位
i=x/10;//取十位
j=x%10;//取個位
WriteAddress(0x06); //寫顯示地址,將在第2行第7列開始顯示
WriteData(digit[i]); //將百位數字的字元常量寫入LCD
WriteData(digit[j]); //將十位數字的字元常量寫入LCD
delaynms(50); //延時1ms給硬體一點反應時間
}

/*****************************************************
函數功能:主函數
***************************************************/
void main(void)
{
unsigned char second,minute,hour,day,month,year; //分別儲存苗、分、小時,日,月,年
unsigned char ReadValue; //儲存從1302讀取的數據
LcdInitiate(); //將液晶初始化
WriteAddress(0x01); //寫Date的顯示地址,將在第1行第2列開始顯示
WriteData('D'); //將字元常量寫入LCD
WriteData('a'); //將字元常量寫入LCD
WriteData('t'); //將字元常量寫入LCD
WriteData('e'); //將字元常量寫入LCD
WriteData(':'); //將字元常量寫入LCD
WriteAddress(0x08); //寫年月分隔符的顯示地址, 顯示在第1行第9列
WriteData('-'); //將字元常量寫入LCD
WriteAddress(0x0b); //寫月日分隔符的顯示地址, 顯示在第1行第12列
WriteData('-'); //將字元常量寫入LCD
WriteAddress(0x45); //寫小時與分鍾分隔符的顯示地址, 顯示在第2行第6列
WriteData(':'); //將字元常量寫入LCD
WriteAddress(0x48); //寫分鍾與秒分隔符的顯示地址, 顯示在第2行第9列
WriteData(':'); //將字元常量寫入LCD
Init_DS1302(); //將1302初始化
while(1)
{
ReadValue = ReadSet1302(0x81); //從秒寄存器讀數據
second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//將讀出數據轉化
DisplaySecond(second); //顯示秒
ReadValue = ReadSet1302(0x83); //從分寄存器讀
minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayMinute(minute); //顯示分
ReadValue = ReadSet1302(0x85); //從分寄存器讀
hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayHour(hour); //顯示小時
ReadValue = ReadSet1302(0x87); //從分寄存器讀
day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayDay(day); //顯示日
ReadValue = ReadSet1302(0x89); //從分寄存器讀
month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayMonth(month); //顯示月
ReadValue = ReadSet1302(0x8d); //從分寄存器讀
year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //將讀出數據轉化
DisplayYear(year); //顯示年
}
}

改改 就是你的了

Ⅲ 求程序用AT89C51單片機......用六位數碼管實現數字時鍾,顯示時分秒,用兩個按鍵可分別調整時、分。

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar temp,aa,miao,fen,shi;
sbit m=P3^0;
sbit n=P3^1;
uchar code table[]={ //數碼管編碼表
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f};
void display(uchar miao,uchar fen,uchar shi);
void delay(uint z);
void init();
void main()
{
init();//初始化子程序
miao=0;
shi=0;
fen=0;
while(1)
{
display(miao,fen,shi);
}
}void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}void display(uchar miao,uchar fen,uchar shi) // 顯示子函數
{
P0=0x00;
P0=table[miao%10];
P2=0x7f;
delay(1);

P0=0x00;
P0=table[miao/10];
P2=0xbf;
delay(1); P0=0x00;
P0=table[fen%10];
P2=0xdf;
delay(1);

P0=0x00;
P0=table[fen/10];
P2=0xef;
delay(1);

P0=0x00;
P0=table[shi%10];
P2=0xf7;
delay(1); P0=0x00;
P0=table[shi/10];
P2=0xfb;
delay(1);
}void init() // 初始化子函數
{
temp=0;
TMOD=0x01;
TH0=(65536-45872)/256;
TL0=(65536-45872)%256; //租茄並定時器初值,定時50ms(12M晶振),由於考慮MCU指令處理時間,此處賦初值位45872
EA=1;
ET0=1;
TR0=1;
}void timer0() interrupt 1 //定時計數器中納族斷
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256; 、
aa++;
if(aa==20) //中斷2次位1S,秒加1
{
miao++;
aa=0;
if(miao==60)
{
fen++; // 滿60S, 分加1,秒清0
miao=0;
if(fen==60)
{
shi++; // 小時弊跡加1
fen=0;
if(shi==24) shi=0; //小時滿
}
}
}
if(m==0) // 調分
{
delay(2);
if(m==0) fen++;
if(fen==60) fen=0;
delay(2);
while(!m);
}
if(n==0) // 調小時
{
delay(2);
if(n==0) shi++;
if(shi==24) shi=0;
delay(2);
while(!n);
}
}

Ⅳ 51單片機時鍾程序設計

朋友以下是本人歷時一個月殫精竭慮自主開發的一個8位51單片機時鍾程序,望吾之兄弟姐妹習之,此程序乃採用一鍵控制,通過感知按下鍵持續時間的長短來進行調整時間,鬧鈴,6隻共陽數碼管輸出顯示,此外還包括整點鈴聲功能,在看程序之前我先交代一下運行該程序的硬體要求:12M晶振,P0埠驅動顯示,P2.0到P2.5控制顯示掃描,P2.7輸出鈴聲,注意:鈴聲功放三極體應採用pnp管。以下是該程序:
ORG 00H
SETB TR0
JMP START
ORG 000BH
LJMP T0
START: MOV IE,#82H
MOV TMOD,#01H
MOV DPTR,#TAB
MOV SP,#60H
MOV 20H,#0
MOV R0,#0
MOV R1,#0
MOV R2,#0
MOV R3,#0
MOV R4,#0
MOV R5,#0
MOV R6,#0
MOV R7,#0
MOV 50H,#0
MOV 51H,#0
MOV 52H,#0
MOV 53H,#0
MOV 54H,#0
MOV 55H,#0
MOV A,TL0
ADD A,0B5H
MOV TL0,A
MOV TH0,#3CH
LOOP: ANL 20H,#08H
UNSV: MOV R1,#0
LCALL DISPLAY
JB 03H,LOP1
LCALL SOUND
LCALL HDLY
LOP1: MOV P3,#0FEH ;按鍵監視
MOV A,P3
CJNE A,#0FEH,LOP2
MOV R1,#0
JMP LOOP
LOP2: MOV R1,#2 ;誤按判斷
LOP3: LCALL HD
DJNZ R1,LOP3
JNB 04H,LOOP
CLR 04H
LOP4: INC R1
MOV C,00H ;調秒
CPL C
MOV 00H,C
LCALL HDLY
CJNE R1,#40,LOP5
JMP LOOP
LOP5: JNB 05H,LOP4
CLR 05H
MOV R1,#0
LCALL HD
CLR 00H
JB 04H,TF
MOV R2,#0
MOV R3,#0
JMP LOP4
TF: CLR 04H
LOP6: INC R1
MOV C,01H ;調分
CPL C
MOV 01H,C
LCALL HDLY
CJNE R1,#40,LOP7
JMP LOOP
LOP7: JNB 05H,LOP6
CLR 05H
MOV R1,#0
LCALL HD
CLR 01H
JB 04H,TS
INC R4
MOV R1,#0
CJNE R4,#10,LOP6
MOV R4,#0
INC R5
CJNE R5,#6,LOP6
MOV R5,#0
JMP LOP6
TS: CLR 04H
LOP8: INC R1
MOV C,02H ;調時
CPL C
MOV 02H,C
LCALL HDLY
CJNE R1,#40,LOP9
JMP LOOP
LOP9: JNB 05H,LOP8
CLR 05H
MOV R1,#0
LCALL HD
CLR 02H
JB 04H,TN
INC R6
CJNE R7,#2,NO2
CJNE R6,#4,LOP8
MOV R7,#0
MOV R6,#0
NO2: CJNE R6,#10,LOP8
MOV R6,#0
INC R7
JMP LOP8
TN: CLR 04H ;調鬧鈴
SETB RS0
CLR RS1
MOV R2,#0
MOV R3,#0
MOV R4,#0
MOV R5,#0
MOV R6,#0
MOV R7,#0
NS: INC R1 ;鬧鈴秒調整
MOV C,00H
CPL C
MOV 00H,C
LCALL HDLY
CJNE R1,#40,NS1
JMP NH2
NS1: JNB 05H,NS
CLR 05H
MOV R1,#0
LCALL HD
CLR 00H
JB 04H,NF
INC R2
CJNE R2,#10,NS
MOV R2,#0
INC R3
CJNE R3,#6,NS
MOV R3,#0
JMP NS
NF: CLR 04H ;鬧鈴分
NF1: INC R1
MOV C,01H
CPL C
MOV 01H,C
LCALL HDLY
CJNE R1,#40,NF2
LJMP NH2
NF2: JNB 05H,NF1
CLR 05H
MOV R1,#0
LCALL HD
CLR 01H
JB 04H,NH
INC R4
CJNE R4,#10,NF1
MOV R4,#0
INC R5
CJNE R5,#6,NF1
MOV R5,#0
JMP NF1
NH: CLR 04H ;鬧鈴時調整
NH1: INC R1
MOV C,02H
CPL C
MOV 02H,C
LCALL HDLY
CJNE R1,#40,NH3
NH2: MOV 50H,R2
MOV 51H,R3
MOV 52H,R4
MOV 53H,R5
MOV 54H,R6
MOV 55H,R7
CLR RS0
CLR RS1
LJMP LOOP
NH3: JNB 05H,NH1
CLR 05H
MOV R1,#0
LCALL HD
CLR 02H
JB 04H,NH2
INC R6
CJNE R7,#2,NOT2
CJNE R6,#4,NH1
MOV R6,#0
MOV R7,#0
JMP NH1
NOT2: CJNE R6,#10,NH1
MOV R6,#0
INC R7
JMP NH1
;子程序區
TIMES: CJNE R0,#20,LOOP16
MOV R0,#0
INC R2
CJNE R2,#10,LOOP16
MOV R2,#0
INC R3
CJNE R3,#6,LOOP16
MOV R3,#0
ADMINI: INC R4
CJNE R4,#10,LOOP16
MOV R4,#0
INC R5
CJNE R5,#6,LOOP16
MOV R5,#0
HOUR: INC R6
LCALL SOUND ;整點鈴聲
CJNE R7,#2,LOOP14
CJNE R6,#4,LOOP16
MOV R6,#0
MOV R7,#0
JMP LOOP16
LOOP14: CJNE R6,#10,LOOP16
MOV R6,#0
INC R7
LOOP16: RET
DISPLAY:MOV P2,#0FFH
MOV A,R2
MOVC A,@A+DPTR
MOV P0,A
MOV C,00H
MOV P2.0,C
MOV P2,#0FFH
MOV A,R3
MOVC A,@A+DPTR
MOV P0,A
MOV P2.1,C
MOV P2,#0FFH
MOV A,R4
MOVC A,@A+DPTR
MOV P0,A
MOV C,01H
MOV P2.2,C
MOV P2,#0FFH
MOV A,R5
MOVC A,@A+DPTR
MOV P0,A
MOV P2.3,C
MOV P2,#0FFH
MOV A,R6
MOVC A,@A+DPTR
MOV P0,A
MOV C,02H
MOV P2.4,C
MOV P2,#0FFH
MOV A,R7
MOVC A,@A+DPTR
MOV P0,A
MOV P2.5,C
MOV P2,#0FFH
RET
HDLY: MOV 40H,#2
HDL1: MOV 41H,#25
HDL2: MOV 42H,#100
HDL3: DJNZ 42H,HDL4
DJNZ 41H,HDL2
DJNZ 40H,HDL1
JMP HDOT
SOUT: SETB 05H
HDOT: RET
HDL4: MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,SOUT
CLR 05H
LCALL DISPLAY
JMP HDL3
HD: MOV 30H,#5
HD1: MOV 31H,#50
HD2: MOV 32H,#100
HD3: LCALL DISPLAY
DJNZ 32H,HD4
DJNZ 31H,HD2
DJNZ 30H,HD1
SETB 04H ;計滿標志位
JMP HDOUT
HD4: MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,HD3
MOV 33H,#50
HD5: MOV 34H,#100
DJNZ 34H,$
DJNZ 33H,HD5
MOV P3,#0FEH
MOV A,P3
CJNE A,#0FEH,HD3
CLR 04H
HDOUT: RET
SOUND: MOV 30H,#10
SO1: MOV 31H,#100
SO2: MOV 32H,#3
MOV C,P2.7
CPL C
MOV P2.7,C
SO3: MOV 33H,#25
DJNZ 33H,$
DJNZ 32H,SO3
DJNZ 31H,SO2
DJNZ 30H,SO1
RET
T0: PUSH PSW
PUSH ACC
CLR RS1
CLR RS0
MOV A,TL0
ADD A,#0B5H
MOV TL0,A
MOV TH0,#3CH
INC R0
LCALL TIMES
MOV A,R2
CJNE A,50H,TO
SETB 03H
MOV A,R3
CJNE A,51H,TO
MOV A,R7
CJNE A,55H,TO
MOV A,R6
CJNE A,54H,TO
MOV A,R5
CJNE A,53H,TO
MOV A,R4
CJNE A,52H,TO
MOV A,R2
ADD A,R3
ADD A,R4
ADD A,R5
ADD A,R6
ADD A,R7
JZ TO
CLR 03H
TO: POP ACC
POP PSW
RETI
TAB: DB 0C0H 0F9H 0A4H 0B0H 099H
DB 092H 082H 0F8H 080H 090H
END

Ⅳ 51單片機做數字電子鍾

這么復雜的東西給這么少分 暈死了 你也太小氣了吧,分多的話還可能幫你動動腦

Ⅵ 求一個簡單的單片機時鍾程序

#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;
}
}
}

Ⅶ 求89c52單片機 C語言實現數字時鍾程序

#include<AT89X52.H>

#include<intrins.h>

#defineRESTP3_4

#defineSCLKP3_7

#defineDATAP3_6

unsignedcharcodedisplayCode[]={0xc0,0xf9,0xa4,0xb0,0x99,

0x92,0x82,0xf8,0x80,0x90};

[]={0x80,0x82,0x84,0x86,0x88,

0x8a,0x8c,0x8e,0x90,0xbe};

unsignedchar顫知hour,minute,second;

unsignedcharday,month,week,year;

unsignedcharclockhour,clockminute;

unsignedintnum;

unsignedcharselect,oneminute;

bitbdatamodeselect;

voiddelay();

voidwritetime();

voiddisplay(unsignedchartemp,unsignedcharmode);

voidsound()

{

while(num<2000)

{

P3_0=0;

}

P3_0=1;

}

voidinitial()

{

P0=0;

TMOD=0x22;

IE=0xCF;

IT0=1;

IT1=1;

T2CON=0;

RCAP2L=0xf0;

RCAP2H=0x1f;

TH2=0x1c;

TL2=0xf0;

IP=0X06;

TH0=0x48;

TL0=0x48;

TH1=0X48;

TR0=1;

PCON=0x01;

hour=12;

minute=0;

second=0;

num=0;

select=0;

clockhour=12;

clockminute=0;

modeselect=0;

day=16;

month=8;

week=7;

year=9;

}

voidinterrupt0()interrupt0using3

{

TR1=1;

select++;

if(select==8)

{

select=0;

}

if(select==1)

ET2=1;

oneminute=second-1;

}

voidtimer0()interrupt1using3

{

num++;

if(num==5000)

{

num=0;

second++;

}

if(second>=60)

{

minute++;

second=0;

}

if(minute>=60)

{

hour++;

minute=0;

}

if(hour>=24)

纖洞搭hour=0;

}

voidinterrupt1()interrupt2using3

{

oneminute=second-1;

switch(select)

{

case4:{

hour++;

if(hour>=24)

hour=0;

break;

}

case5:{

minute++;

if(minute>=60)

minute=0;

break;

}

case6:{

second++;

if(second>=60)

second=0;

break;

}

case2:{

clockhour++;

if(clockhour>=24)

clockhour=0;

break;

}

case3:{

clockminute++;

if(clockminute>=60)

clockminute=0;

break;

}

default:{

modeselect=0;

ET2=!ET2;

break;

}

}

}

voidtimer1()interrupt3using3

{

if(select)

{

if(second==oneminute)

{

select=0;

TR1=0;

}

}

}

void毀拿timer2()interrupt5using3

{

sound();

TF2=0;

if(minute!=clockminute||hour!=clockhour)

TR2=0;

}

voiddelay()

{

unsignedchari=255;

while(--i)

{

;

}

}

voiddisplay(unsignedchartemp,unsignedcharmode)

{

if(temp==4||temp==2)

P0=0;

else

P0=1;

if(mode)

P1=displayCode[hour/10];

else

P1=displayCode[clockhour/10];

delay();

if(temp==4||temp==2)

P0=0;

else

P0=2;

if(mode)

P1=displayCode[hour%10];

else

P1=displayCode[clockhour%10];

delay();

if(temp==1||temp==2||temp==3)

P0=0;

else

P0=4;

P1=0xbf;

delay();

if(temp==5||temp==3)

P0=0;

else

P0=8;

if(mode)

P1=displayCode[minute/10];

else

P1=displayCode[clockminute/10];

delay();

if(temp==5||temp==3)

P0=0;

else

P0=16;

if(mode)

P1=displayCode[minute%10];

else

P1=displayCode[clockminute%10];

delay();

if(temp==1||temp==2||temp==3)

P0=0;

else

P0=32;

P1=0xbf;

delay();

if(temp==6)

P0=0;

else

P0=64;

if(mode)

P1=displayCode[second/10];

else

P1=displayCode[0];

delay();

if(temp==6)

P0=0;

else

P0=128;

if(mode)

{

if(ET2)

P1=displayCode[second%10]+128;

else

P1=displayCode[second%10];

}

else

P1=displayCode[0];

delay();

}

voidwrite(unsignedcharBdata)

{

unsignedchari=8;

for(;i>0;i--)

{

if(Bdata&0x01)

DATA=1;

else

DATA=0;

SCLK=1;

SCLK=0;

Bdata>>=1;

}

}

voidwritedata(unsignedcharaddress,Bdata)

{

REST=0;

SCLK=0;

_nop_();

REST=1;

write(address);

write(Bdata);

REST=0;

}

unsignedcharread(unsignedcharBdata)

{

unsignedchartdata=0,i=8;

REST=0;

SCLK=0;

_nop_();

REST=1;

write(Bdata);

for(;i>0;i--)

{

tdata>>=1;

if(DATA)

tdata=tdata|0x80;

else

tdata|=0x00;

SCLK=1;

SCLK=0;

}

returntdata;

}

voidwritetime()

{

unsignedchari,time,temp[3];

temp[0]=second;

temp[1]=minute;

temp[2]=hour;

for(i=0;i<3;i++)

{

time=temp[i]%10;

time|=(temp[i]/10)<<4;

writedata(controladdress[i],time);

}

}

voidwriteyear()

{

unsignedchari,year0,temp[4];

temp[0]=day;

temp[1]=month;

temp[2]=week;

temp[3]=year;

for(i=0;i<4;i++)

{

year0=temp[i]%10;

year0|=(temp[i]/10)<<4;

writedata(controladdress[i+3],year0);

}

}

voidreadtime()

{

unsignedchari,time,temp[3];

for(i=0;i<3;i++)

{

temp[i]=read(1+controladdress[i]);

time=temp[i]&0x0f;

time+=(temp[i]>>4)*10;

temp[i]=time;

}

second=temp[0];

minute=temp[1];

hour=temp[2];

}

voidreadyear()

{

unsignedchari,year0,temp[4];

for(i=0;i<4;i++)

{

temp[i]=read(1+controladdress[i+3]);

year0=temp[i]&0x0f;

year0+=(temp[i]>>4)*10;

temp[i]=year0;

}

day=temp[0];

month=temp[1];

week=temp[2];

year=temp[3];

}

voidmain()

{

initial();

sound();

writedata(0x8e,0x00);

writedata(0x84,0x12);

writedata(0x8f,0x00);

readtime();

writeyear();

readyear();

while(1)

{

switch(select)

{

case0:{

display(0,1);

break;

}

case1:{

if(num<=2500)

{

display(1,0);

}

else

{

display(0,0);

}

break;

}

case2:{

if(num<=2500)

{

display(2,0);

}

else

{

display(0,0);

}

break;

}

case3:{

if(num<=2500)

{

display(3,0);

}

else

{

display(0,0);

}

break;

}

case4:{

if(num<=2500)

{

display(4,1);

}

else

{

display(0,1);

}

break;

}

case5:{

if(num<=2500)

{

display(5,1);

}

else

{

display(0,1);

}

break;

}

case6:{

if(num<=2500)

{

display(6,1);

}

else

{

display(0,1);

}

break;

}

case7:{

writetime();

writetime();

writetime();

select=0;

break;

}

default:break;

}

if(second==0)

{

if(minute==0||minute==30)

sound();

}

if(minute==clockminute&&hour==clockhour)

{

TR2=1;

modeselect=1;

}

if(modeselect==1&&hour==clockhour&&!((minute-clockminute)%5))

TR2=1;

}

}

Ⅷ 單片機數字時鍾匯編程序設計分析

時鍾設計基本上就是通過電子 定時器定時 到1s給一個中斷 讓單片機去執行中斷 跳轉至相應的數碼管位 然後修改當前顯示值 再設置到10進位加一 之後就出來數字時鍾的效果 弄懂定時器 一切就順下來了
這是一個C得時鍾程序 你看明白思想 就好說匯編的語句了
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char

sbit la=P3^7;

sbit L1=P2^0;
sbit L2=P2^1;
sbit L3=P2^2;
sbit key1=P3^0;
sbit key2=P3^1;
sbit key3=P3^2;
sbit key4=P3^3;

uchar aa;
uchar code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};
uchar nummiao,numfen,numshi,t0;

void delayms(uchar xms)
{
uchar i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void init()
{
TMOD=0x11;
TH0=(65536-50000)%256;
TL0=(65536-50000)/256;

EA=1;
ET0=1;

}
void display(uchar nummiao,numfen,numshi)
{
uchar shishi,geshi,shifen,gefen,shimiao,gemiao;
shimiao=nummiao/10;
gemiao=nummiao%10;
shifen=numfen/10;
gefen=numfen%10;
shishi=numshi/10;
geshi=numshi%10;

la=1;
P0=table[shimiao];
la=0;
L1=0;
L2=1;
L3=1;
delayms(5);

la=1;
P0=table[gemiao];
la=0;
L1=1;
L2=1;
L3=1;
delayms(5);

la=1;
P0=0x40;
la=0;
L1=1;
L2=0;
L3=1;
delayms(5);

la=1;
P0=table[gefen];
la=0;
L1=0;
L2=0;
L3=1;
delayms(5);

la=1;
P0=table[shifen];
la=0;
L1=1;
L2=1;
L3=0;
delayms(5);

la=1;
P0=0x40;
la=0;
L1=0;
L2=1;
L3=0;
delayms(5);

la=1;
P0=table[geshi];
la=0;
L1=1;
L2=0;
L3=0;
delayms(5);

la=1;
P0=table[shishi];
la=0;
L1=0;
L2=0;
L3=0;
delayms(5);

}

void keyscan()
{
if(key1==0)
{
delayms(10);
if(key1==0)
{

numshi++;
if(numshi==24)
numshi=0;
while(!key1);

}

}

if(key2==0)
{
delayms(10);
if(key2==0)
{

if(numfen==60)
numfen=0;
numfen++;
while(!key2);

}
}

if(key3==0)
{
delayms(10);

if(key3==0)
{

nummiao=0;
while(!key3);

}
}

if(key4==0)
{
delayms(10);
if(key4==0)
{

while(!key4);
TR0=~TR0;

}
}
}

void main()
{

init();

aa=0xfe;

while(1)
{
P1=aa;

if(nummiao==60)
{
numfen++;
nummiao=0;}
if(numfen==60)
{ numshi++;
numfen=0;}
if(numshi==24)
numshi=0;
keyscan();
display(nummiao,numfen,numshi);

}

}

void t0time()interrupt 1
{

TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
t0++;
if(t0==20)
{
t0=0;

nummiao++;}

aa=_crol_(aa,1);

}

Ⅸ 用單片機製作可調數字時鍾要匯編語言程序的

用這個程序吧 C和匯編都有。
數字鍾[★]
1. 實驗任務
(1. 開機時,顯示12:00:00的時間開始計時;
(2. P0.0/AD0控制「秒」的調整,每按一次加1秒;
(3. P0.1/AD1控制「分」的調整,每按一次加1分;
(4. P0.2/AD2控制「時」的調整,每按一次加1個小時;
2. 電路原理圖

圖4.20.1
3. 系統板上硬體連線
(1. 把「單片機系統」區域中的P1.0-P1.7埠用8芯排線連接到「動態數碼顯示」區域中的A-H埠上;
(2. 把「單片機系統:區域中的P3.0-P3.7埠用8芯排線連接到「動態數碼顯示」區域中的S1-S8埠上;
(3. 把「單片機系統」區域中的P0.0/AD0、P0.1/AD1、P0.2/AD2埠分別用導線連接到「獨立式鍵盤」區域中的SP3、SP2、SP1埠上;
4. 相關基本知識
(1. 動態數碼顯示的方法
(2. 獨立式按鍵識別過程
(3. 「時」,「分」,「秒」數據送出顯示處理方法
5. 程序框圖
6. 匯編源程序
SECOND EQU 30H
MINITE EQU 31H
HOUR EQU 32H
HOURK BIT P0.0
MINITEK BIT P0.1
SECONDK BIT P0.2
DISPBUF EQU 40H
DISPBIT EQU 48H
T2SCNTA EQU 49H
T2SCNTB EQU 4AH
TEMP EQU 4BH
ORG 00H
LJMP START
ORG 0BH
LJMP INT_T0
START: MOV SECOND,#00H
MOV MINITE,#00H
MOV HOUR,#12
MOV DISPBIT,#00H
MOV T2SCNTA,#00H
MOV T2SCNTB,#00H
MOV TEMP,#0FEH
LCALL DISP
MOV TMOD,#01H
MOV TH0,#(65536-2000) / 256
MOV TL0,#(65536-2000) MOD 256
SETB TR0
SETB ET0
SETB EA
WT: JB SECONDK,NK1
LCALL DELY10MS
JB SECONDK,NK1
INC SECOND
MOV A,SECOND
CJNE A,#60,NS60
MOV SECOND,#00H
NS60: LCALL DISP
JNB SECONDK,$
NK1: JB MINITEK,NK2
LCALL DELY10MS
JB MINITEK,NK2
INC MINITE
MOV A,MINITE
CJNE A,#60,NM60
MOV MINITE,#00H
NM60: LCALL DISP
JNB MINITEK,$
NK2: JB HOURK,NK3
LCALL DELY10MS
JB HOURK,NK3
INC HOUR
MOV A,HOUR
CJNE A,#24,NH24
MOV HOUR,#00H
NH24: LCALL DISP
JNB HOURK,$
NK3: LJMP WT
DELY10MS:
MOV R6,#10
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
DISP:
MOV A,#DISPBUF
ADD A,#8
DEC A
MOV R1,A
MOV A,HOUR
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV@R1,A
DEC R1
MOV A,MINITE
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
MOV A,#10
MOV@R1,A
DEC R1
MOV A,SECOND
MOV B,#10
DIV AB
MOV @R1,A
DEC R1
MOV A,B
MOV @R1,A
DEC R1
RET
INT_T0:
MOV TH0,#(65536-2000) / 256
MOV TL0,#(65536-2000) MOD 256
MOV A,#DISPBUF
ADD A,DISPBIT
MOV R0,A
MOV A,@R0
MOV DPTR,#TABLE
MOVC A,@A+DPTR
MOV P1,A
MOV A,DISPBIT
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P3,A
INC DISPBIT
MOV A,DISPBIT
CJNE A,#08H,KNA
MOV DISPBIT,#00H
KNA: INC T2SCNTA
MOV A,T2SCNTA
CJNE A,#100,DONE
MOV T2SCNTA,#00H
INC T2SCNTB
MOV A,T2SCNTB
CJNE A,#05H,DONE
MOV T2SCNTB,#00H
INC SECOND
MOV A,SECOND
CJNE A,#60,NEXT
MOV SECOND,#00H
INC MINITE
MOV A,MINITE
CJNE A,#60,NEXT
MOV MINITE,#00H
INC HOUR
MOV A,HOUR
CJNE A,#24,NEXT
MOV HOUR,#00H
NEXT: LCALL DISP
DONE: RETI
TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,40H
TAB: DB 0FEH,0FDH,0FBH,0F7H,0EFH,0DFH,0BFH,07FH
END
7. C語言源程序
#include <AT89X51.H>
unsigned char code dispcode[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x00};
unsigned char dispbitcode[]={0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f};
unsigned char dispbuf[8]={0,0,16,0,0,16,0,0};
unsigned char dispbitcnt;
unsigned char second;
unsigned char minite;
unsigned char hour;
unsigned int tcnt;
unsigned char mstcnt;
unsigned char i,j;
void main(void)
{
TMOD=0x02;
TH0=0x06;
TL0=0x06;
TR0=1;
ET0=1;
EA=1;
while(1)
{
if(P0_0==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_0==0)
{
second++;
if(second==60)
{
second=0;
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
while(P0_0==0);
}
}
if(P0_1==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_1==0)
{
minite++;
if(minite==60)
{
minite=0;
}
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
while(P0_1==0);
}
}
if(P0_2==0)
{
for(i=5;i>0;i--)
for(j=248;j>0;j--);
if(P0_2==0)
{
hour++;
if(hour==24)
{
hour=0;
}
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
while(P0_2==0);
}
}
}
}
void t0(void) interrupt 1 using 0
{
mstcnt++;
if(mstcnt==8)
{
mstcnt=0;
P1=dispcode[dispbuf[dispbitcnt]];
P3=dispbitcode[dispbitcnt];
dispbitcnt++;
if(dispbitcnt==8)
{
dispbitcnt=0;
}
}
tcnt++;
if(tcnt==4000)
{
tcnt=0;
second++;
if(second==60)
{
second=0;
minite++;
if(minite==60)
{
minite=0;
hour++;
if(hour==24)
{
hour=0;
}
}
}
dispbuf[0]=second%10;
dispbuf[1]=second/10;
dispbuf[3]=minite%10;
dispbuf[4]=minite/10;
dispbuf[6]=hour%10;
dispbuf[7]=hour/10;
}
}

Ⅹ 用單片機設計一個數字時鍾

#include <REG51.H>#include <intrins.h> #define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //實時時鍾時鍾線引腳 sbit DS1302_IO = P1^6; //實時時鍾數據線引腳 sbit DS1302_RST = P1^5; //實時時鍾復位線引腳sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3; //無線控制sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,時到日,月,年位閃的計數sbit Set = P2^0; //模式切換鍵sbit Up = P2^1; //加法按鈕sbit Down = P2^2; //減法按鈕sbit out = P2^3; //立刻跳出調整模式按鈕sbit DQ = P1^0; //溫度傳送數據IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; //溫度值uchar TempBuffer[5],week_value[2]; void show_time(); //液晶顯示程序/***********1602液晶顯示部分子程序****************///Port Definitions**********************************************************sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.數據埠 //內部等待函數**************************************************************************unsigned char LCD_Wait(void){ LcdRs=0; LcdRw=1; _nop_(); LcdEn=1; _nop_(); LcdEn=0; return DBPort; }//向LCD寫入命令或數據************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 游標返回原點void LCD_Write(bit style, unsigned char input){ LcdEn=0; LcdRs=style; LcdRw=0; _nop_(); DBPort=input; _nop_();//注意順序 LcdEn=1; _nop_();//注意順序 LcdEn=0; _nop_(); LCD_Wait(); } //設置顯示模式************************************************************#define LCD_SHOW 0x04 //顯示開#define LCD_HIDE 0x00 //顯示關 #define LCD_CURSOR 0x02 //顯示游標#define LCD_NO_CURSOR 0x00 //無游標 #define LCD_FLASH 0x01 //游標閃動#define LCD_NO_FLASH 0x00 //游標不閃動 void LCD_SetDisplay(unsigned char DisplayMode){ LCD_Write(LCD_COMMAND, 0x08|DisplayMode); } //設置輸入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default #define LCD_MOVE 0x01 // 畫面可平移#define LCD_NO_MOVE 0x00 //default void LCD_SetInput(unsigned char InputMode){ LCD_Write(LCD_COMMAND, 0x04|InputMode);} //初始化LCD************************************void LCD_Initial(){ LcdEn=0; LCD_Write(LCD_COMMAND,0x38); //8位數據埠,2行顯示,5*7點陣 LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //開啟顯示, 無游標 LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏 LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC遞增, 畫面不動} //液晶字元輸入的位置************************void GotoXY(unsigned char x, unsigned char y){ if(y==0) LCD_Write(LCD_COMMAND,0x80|x); if(y==1) LCD_Write(LCD_COMMAND,0x80|(x-0x40));} //將字元輸出到液晶顯示void Print(unsigned char *str){ while(*str!='\0') { LCD_Write(LCD_DATA,*str); str++; }} /***********DS1302時鍾部分子程序******************/typedef struct __SYSTEMTIME__{ unsigned char Second; unsigned char Minute; unsigned char Hour; unsigned char Week; unsigned char Day; unsigned char Month; unsigned char Year; unsigned char DateString[11]; unsigned char TimeString[9];}SYSTEMTIME; //定義的時間類型SYSTEMTIME CurrentTime; #define AM(X) X#define PM(X) (X+12) // 轉成24小時制#define DS1302_SECOND 0x80 //時鍾晶元的寄存器位置,存放時間#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84 #define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C void DS1302InputByte(unsigned char d) //實時時鍾寫入一位元組(內部函數){ unsigned char i; ACC = d; for(i=8; i>0; i--) { DS1302_IO = ACC0; //相當於匯編中的 RRC DS1302_CLK = 1; DS1302_CLK = 0; ACC = ACC >> 1; } } unsigned char DS1302OutputByte(void) //實時時鍾讀取一位元組(內部函數){ unsigned char i; for(i=8; i>0; i--) { ACC = ACC >>1; //相當於匯編中的 RRC ACC7 = DS1302_IO; DS1302_CLK = 1; DS1302_CLK = 0; } return(ACC); } void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要寫的數據{ DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr); // 地址,命令 DS1302InputByte(ucDa); // 寫1Byte數據 DS1302_CLK = 1; DS1302_RST = 0;} unsigned char Read1302(unsigned char ucAddr) //讀取DS1302某地址的數據{ unsigned char ucData; DS1302_RST = 0; DS1302_CLK = 0; DS1302_RST = 1; DS1302InputByte(ucAddr|0x01); // 地址,命令 ucData = DS1302OutputByte(); // 讀1Byte數據 DS1302_CLK = 1; DS1302_RST = 0; return(ucData);} void DS1302_GetTime(SYSTEMTIME *Time) //獲取時鍾晶元的時鍾數據到自定義的結構型數組{ unsigned char ReadValue; ReadValue = Read1302(DS1302_SECOND); Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MINUTE); Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_HOUR); Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_DAY); Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_WEEK); Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_MONTH); Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); ReadValue = Read1302(DS1302_YEAR); Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); } void DateToStr(SYSTEMTIME *Time) //將時間年,月,日,星期數據轉換成液晶顯示字元串,放到數組里DateString[]{ if(hide_year<2) //這里的if,else語句都是判斷位閃爍,<2顯示數據,>2就不顯示,輸出字元串為 2007/07/22 { Time->DateString[0] = '2'; Time->DateString[1] = '0'; Time->DateString[2] = Time->Year/10 + '0'; Time->DateString[3] = Time->Year%10 + '0'; } else { Time->DateString[0] = ' '; Time->DateString[1] = ' '; Time->DateString[2] = ' '; Time->DateString[3] = ' '; } Time->DateString[4] = '/'; if(hide_month<2) { Time->DateString[5] = Time->Month/10 + '0'; Time->DateString[6] = Time->Month%10 + '0'; } else { Time->DateString[5] = ' '; Time->DateString[6] = ' '; } Time->DateString[7] = '/'; if(hide_day<2) { Time->DateString[8] = Time->Day/10 + '0'; Time->DateString[9] = Time->Day%10 + '0'; } else { Time->DateString[8] = ' '; Time->DateString[9] = ' '; } if(hide_week<2) { week_value[0] = Time->Week%10 + '0'; //星期的數據另外放到 week_value[]數組里,跟年,月,日的分開存放,因為等一下要在最後顯示 } else { week_value[0] = ' '; } week_value[1] = '\0'; Time->DateString[10] = '\0'; //字元串末尾加 '\0' ,判斷結束字元} void TimeToStr(SYSTEMTIME *Time) //將時,分,秒數據轉換成液晶顯示字元放到數組 TimeString[];{ if(hide_hour<2) { Time->TimeString[0] = Time->Hour/10 + '0'; Time->TimeString[1] = Time->Hour%10 + '0'; } else { Time->TimeString[0] = ' '; Time->TimeString[1] = ' '; } Time->TimeString[2] = ':'; if(hide_min<2) { Time->TimeString[3] = Time->Minute/10 + '0'; Time->TimeString[4] = Time->Minute%10 + '0'; } else { Time->TimeString[3] = ' '; Time->TimeString[4] = ' '; } Time->TimeString[5] = ':'; if(hide_sec<2) { Time->TimeString[6] = Time->Second/10 + '0'; Time->TimeString[7] = Time->Second%10 + '0'; } else { Time->TimeString[6] = ' '; Time->TimeString[7] = ' '; } Time->DateString[8] = '\0';} void Initial_DS1302(void) //時鍾晶元初始化{ unsigned char Second=Read1302(DS1302_SECOND); if(Second&0x80) //判斷時鍾晶元是否關閉 { Write1302(0x8e,0x00); //寫入允許 Write1302(0x8c,0x07); //以下寫入初始化時間 日期:07/07/25.星期: 3. 時間: 23:59:55 Write1302(0x88,0x07); Write1302(0x86,0x25); Write1302(0x8a,0x07); Write1302(0x84,0x23); Write1302(0x82,0x59); Write1302(0x80,0x55); Write1302(0x8e,0x80); //禁止寫入 } } /***********ds18b20子程序*************************/ /***********ds18b20延遲子函數(晶振12MHz )*******/ void delay_18B20(unsigned int i){ while(i--);} /**********ds18b20初始化函數**********************/ void Init_DS18B20(void) { unsigned char x=0; DQ = 1; //DQ復位 delay_18B20(8); //稍做延時 DQ = 0; //單片機將DQ拉低 delay_18B20(80); //精確延時 大於 480us DQ = 1; //拉高匯流排 delay_18B20(14); x=DQ; //稍做延時後 如果x=0則初始化成功 x=1則初始化失敗 delay_18B20(20);} /***********ds18b20讀一個位元組**************/ unsigned char ReadOneChar(void){ uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 給脈沖信號 dat>>=1; DQ = 1; // 給脈沖信號 if(DQ) dat|=0x80; delay_18B20(4); } return(dat);} /*************ds18b20寫一個位元組****************/ void WriteOneChar(uchar dat){ unsigned char i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01; delay_18B20(5); DQ = 1; dat>>=1; }} /**************讀取ds18b20當前溫度************/ void ReadTemp(void){ unsigned char a=0; unsigned char b=0; unsigned char t=0; Init_DS18B20(); WriteOneChar(0xCC); // 跳過讀序號列號的操作 WriteOneChar(0x44); // 啟動溫度轉換 delay_18B20(100); // this message is wery important Init_DS18B20(); WriteOneChar(0xCC); //跳過讀序號列號的操作 WriteOneChar(0xBE); //讀取溫度寄存器等(共可讀9個寄存器) 前兩個就是溫度 delay_18B20(100); a=ReadOneChar(); //讀取溫度值低位 b=ReadOneChar(); //讀取溫度值高位 temp_value=b<<4; temp_value+=(a&0xf0)>>4; }void temp_to_str() //溫度數據轉換成液晶字元顯示{ TempBuffer[0]=temp_value/10+'0'; //十位 TempBuffer[1]=temp_value%10+'0'; //個位 TempBuffer[2]=0xdf; //溫度符號 TempBuffer[3]='C'; TempBuffer[4]='\0';}void Delay1ms(unsigned int count){ unsigned int i,j; for(i=0;i<count;i++) for(j=0;j<120;j++);} /*延時子程序*/void mdelay(uint delay){ uint i; for(;delay>0;delay--) {for(i=0;i<62;i++) //1ms延時. {;} }}

閱讀全文

與單片機數字時鍾程序相關的資料

熱點內容
基於單片機的光控路燈 瀏覽:33
為什麼說安卓平板適配的軟體少 瀏覽:676
三國志下載pdf 瀏覽:683
為什麼單片機c語言 瀏覽:423
演算法一定有一個或多個輸入 瀏覽:242
浪潮伺服器貴州銷售雲主機 瀏覽:844
amdlinux顯卡安裝 瀏覽:568
泰海科技雲伺服器如何卸載 瀏覽:122
有密碼打開excel加密 瀏覽:820
java生成重復字元 瀏覽:282
串口伺服器有什麼用 瀏覽:330
linux安裝red5 瀏覽:295
單片機中斷時入口地址作用 瀏覽:150
程序員的工作是重復性的嗎 瀏覽:68
照片怎麼轉換成pdf 瀏覽:133
女生學編程好嗎 瀏覽:240
目前絕地求生怎麼看伺服器地址大全 瀏覽:826
論人類不平等的起源pdf 瀏覽:438
壓縮機螺桿加工 瀏覽:370
怎麼把網站伺服器設置在境外 瀏覽:164