新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 一個51單片機實現(xiàn)數(shù)字時鐘(1602顯示)

一個51單片機實現(xiàn)數(shù)字時鐘(1602顯示)

作者: 時間:2016-11-17 來源:網(wǎng)絡(luò) 收藏
單片機實現(xiàn)數(shù)字時鐘,關(guān)于時間顯示,是用的1602液晶,C51單片機,然后再加一個定時器,每到一秒就動態(tài)的更新一下液晶的時間顯示,在更新的時候也要計算相應(yīng)的分針和時針的變化,還要注意邊界問題.為了能夠達到一個最好的效果,我還加了一個鍵盤掃描,用到了3個鍵,分別為功能鍵,增1,減1來實現(xiàn)用戶自定義時間.

在實現(xiàn)過程中,用到了單片機的中斷系統(tǒng)的相關(guān)知識,還有定時器,液晶顯示,鍵盤的動態(tài)掃描,都是以前的知識,沒什么難度.
程序如下,可以正常運行.

本文引用地址:http://butianyuan.cn/article/201611/315485.htm

C代碼
#i nclude
#define uint unsigned int
#define uchar unsigned char

sbit lcdrs = P1^0;
sbit lcdrw = P1^1;
sbit lcden = P1^2;

sbit key0 = P2^0;//功能鍵,選擇時分秒
sbit key1 = P2^1;//加1鍵
sbit key2 = P2^2;//減1鍵
sbit key4 = P2^4;

uchar key0_count;//按鍵0被按的次數(shù)(0~3)

char hour,minute,second; //時分秒
uint timer_count; //定時器中斷計數(shù)

uchar table_date[] = "2009-4-12 Mon";
uchar table_time[] = "00:00:00";

/****** 函數(shù)申明 ********/
void write_cmd_1602(uchar cmd);
void write_data_1602(uchar dat);
void write_add(uchar add,uchar dat);
void init1602();
void delay(uint z);
uchar reverse(uchar c);
void keyscan();
void init();
/****** 主函數(shù) ********/
void main()
{
init();
//init1602();
//while(1);
while(1)
{
keyscan();
delay(5);
}
}
//1602液晶初始化
void init1602()
{
lcdrw = 0; //本程序只讀不寫,故將其置低
lcden = 0; //關(guān)閉1602
delay(5);
write_cmd_1602(0x01); //清屏
write_cmd_1602(0x38); //顯示模式
write_cmd_1602(0x0c); //開顯示,不顯示光標(biāo),不閃爍
write_cmd_1602(0x06); //地址指針自動加1
write_cmd_1602(0x80+1);//將光標(biāo)指向第一行第二個位置
delay(5);
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/** 將發(fā)送的數(shù)據(jù)進行翻轉(zhuǎn),高位到低位,低位轉(zhuǎn)到高位 **/
uchar reverse(uchar c)
{
uchar chbuff=0;
if (c&0x01) chbuff=chbuff|0x80;
if (c&0x02) chbuff=chbuff|0x40;
if (c&0x04) chbuff=chbuff|0x20;
if (c&0x08) chbuff=chbuff|0x10;
if (c&0x10) chbuff=chbuff|0x08;
if (c&0x20) chbuff=chbuff|0x04;
if (c&0x40) chbuff=chbuff|0x02;
if (c&0x80) chbuff=chbuff|0x01;
return chbuff;
}
//向液晶寫命令
void write_cmd_1602(uchar cmd)
{
lcdrs = 0; //低表示寫命令,高表示寫數(shù)據(jù)
delay(5);
P0 = reverse(cmd);
delay(5);
lcden = 1; //給一個高脈沖
delay(5);
lcden = 0;
delay(5);
}
//向液晶寫數(shù)據(jù)
void write_data_1602(uchar dat)
{
lcdrs = 1; //低表示寫命令,高表示寫數(shù)據(jù)
delay(5);
P0 = reverse(dat);
delay(5);
lcden = 1; //給一個高脈沖
delay(5);
lcden = 0;
delay(5);
}
//根據(jù)地址向液晶寫數(shù)據(jù)
void write_add(uchar add,uchar dat)
{
uchar shi,ge;
shi = dat/10;
ge = dat%10;
delay(5);
write_cmd_1602(0x80+add);
write_data_1602(shi+0x30);
delay(5);
write_data_1602(ge+0x30);
}
//鍵盤掃描函數(shù)
void keyscan()
{
key4 = 0;
if(0==key0) //第一個鍵被按下
{
delay(5); //消抖
if(0==key0)
{
key0_count ++;
if(4==key0_count)
key0_count = 0;
while(!key0); //松手檢測
if(0==key0_count)
{
TR0 = 1; //重新開始計時
write_cmd_1602(0x0c); //禁止顯示光標(biāo)并不讓其閃爍
}
if(1==key0_count)
{
TR0 = 0; //暫停計時
write_cmd_1602(0x80+0x40+11);//將地址指針指向秒的位置
write_cmd_1602(0x0f); //顯示光標(biāo)并閃爍
delay(5);
}
if(2==key0_count)
{
TR0 = 0; //暫停計時
write_cmd_1602(0x80+0x40+8);//將地址指針指向分的位置
write_cmd_1602(0x0f); //顯示光標(biāo)并閃爍
delay(5);
}
if(3==key0_count)
{
TR0 = 0; //暫停計時
write_cmd_1602(0x80+0x40+5);//將地址指針指向小時的位置
write_cmd_1602(0x0f); //顯示光標(biāo)并閃爍
delay(5);
}
}
}
if(0==key1) //第二個鍵被按下
{
delay(5); //消抖
if(0==key1)
{
while(!key1); //松手檢測
if(key0_count==1)
{
second ++;
if(60==second)
second = 0;
write_add(0x40+10,second);
}
if(key0_count==2)
{
minute ++;
if(60==minute)
minute = 0;
write_add(0x40+7,minute);
}
if(key0_count==3)
{
hour ++;
if(24==hour)
hour = 0;
write_add(0x40+4,hour);
}
}
}
if(0==key2) //第三個鍵被按下
{
delay(5); //消抖
if(0==key2)
{
while(!key2); //松手檢測
if(key0_count==1)
{
second --;
if(-1==second)
second = 59;
write_add(0x40+10,second);
}
if(key0_count==2)
{
minute --;
if(-1==minute)
minute = 59;
write_add(0x40+7,minute);
}
if(key0_count==3)
{
hour --;
if(-1==hour)
hour = 23;
write_add(0x40+4,hour);
}
}
}

}
//程序初始化函數(shù)
void init()
{
uchar i;
hour = 0;
minute = 0;
second = 0;
key0_count = 0;
init1602();
delay(20); //延長時間,確保液晶處于非忙狀態(tài)
for(i=0;i<14;i++)
{
write_data_1602(table_date[i]);
delay(5);
}
write_cmd_1602(0x80+0x40+4); //調(diào)整地址指針
for(i=0;i<8;i++)
{
write_data_1602(table_time[i]);
delay(5);
}
//初始化定時器
TMOD = 0x01; //定時器模式
TH0 = (65536-50000)/256; //裝初值
TL0 = (65536-50000)%256;
EA = 1;//開總中斷
ET0 = 1;//開定時器0中斷
TR0 = 1; //啟動定時器,此時開始計時
}
void timer0() interrupt 1 //定時器0的中斷處理函數(shù)
{
TH0 = (65536-50000)/256; //裝初值
TL0 = (65536-50000)%256;
timer_count ++;
if(20==timer_count) //到了1秒更新時分秒的顯示
{
timer_count = 0; //中斷次數(shù)清0,重新計數(shù)
second ++; //秒針加1
if(second==60)
{
second = 0;
minute ++; //分針加1
if(60==minute)
{
minute = 0;
hour ++; //小時加1
if(24==hour)
{
hour = 0;
}
write_add(0x40+4,hour);
}
write_add(0x40+7,minute); //更新分針的顯示
}
write_add(0x40+10,second); //更新秒針
}
}



評論


技術(shù)專區(qū)

關(guān)閉