/*名稱:DS1302實時時鐘---液晶顯示
說明:向DS1302中寫入初始時間,再從DS1302中讀取時鐘數(shù)據(jù),時間可以調(diào)節(jié) ,并 在LCD上顯示出來。
*/
#include <reg52.h>
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
#define datport P0
sbit IO = P1^1; //DS1302數(shù)據(jù)線
sbit SCLK = P1^0; //DS1302時鐘線
sbit RST = P1^2; //DS1302復(fù)位線
sbit RS = P2^2; //LCD寄存器選擇
sbit RW = P2^3; //LCD讀寫控制
sbit EN = P2^4; //LCD啟用
sbit f1 = P3^0;
sbit f2 = P3^1;
sbit f3 = P3^2;
sbit f4 = P3^3;
uchar temp1,temp2;
uchar key();
uchar hour_flag,min_flag,second_flag,flag_key=0;
uchar year_flag,month_flag,day_flag,day_up,day_down;
uchar week_flag;
uchar timecount = 0;
uchar month_table[] = {0,32,29,32,31,32,31,32,32,31,32,31,32};
bit flag;
//1、2、3、4、5、6、7分別對應(yīng)周一至周日
uchar *WEEK[]=
{
"***","MON","TUS","WEN","THU","FRI","SAT","SUN"
};
//LCD顯示緩沖
uchar LCD_DSY_BUFFER1[]={"DATE 00-00-00 "};
uchar LCD_DSY_BUFFER2[]={"TIME 00:00:00 "};
//存放日期和時間
uchar DateTime[7];
//延時函數(shù)
void DelayMS(uint ms)
{
uchar i;
while(ms--)
{
for(i = 0;i < 120;i ++);
}
}
//向DS1302寫入一字節(jié),根據(jù)時序圖寫函數(shù)
//上升沿鎖存數(shù)據(jù),先發(fā)送最低位
void Write_A_Byte_TO_DS1302(uchar x)
{
uchar i;
for(i = 0;i < 8;i ++)
{
IO = x & 0x01;SCLK = 1;SCLK = 0;x >>= 1;
}
}
//從DS1302讀取一字節(jié),看時序圖寫函數(shù)
//下降沿鎖存數(shù)據(jù),先發(fā)送最低位
///DS1302中的數(shù)據(jù)是BCD碼存放的,所以將寄存器中的數(shù)據(jù)轉(zhuǎn)換成十六進制返回
uchar Get_A_Byte_FROM_DS1302()
{
uchar i,b = 0x00;
for(i = 0;i < 8;i ++)
{
b |= _crol_((uchar)IO,i);//先將最低位存放在b的最低位
//再將下一位左移一位存放在b的第二位
//同樣的道理可以將要讀取的數(shù)據(jù)存放在b中
SCLK = 1;SCLK = 0; //下降沿鎖存數(shù)據(jù)
}
return b / 16 * 10 + b % 16; //將BCD碼轉(zhuǎn)換成十六進制返回
}
//從指定地址讀取一個數(shù)據(jù)
uchar Read_Data(uchar addr)
{
uchar dat;
RST = 0;SCLK = 0;RST = 1;
Write_A_Byte_TO_DS1302(addr); //寫入地址
dat = Get_A_Byte_FROM_DS1302();//讀取數(shù)據(jù)
SCLK = 1;RST = 0;
return dat;
}
//向指定地址寫入數(shù)據(jù)
void Write_DS1302(uchar addr,uchar dat)
{
SCLK = 0;RST = 1; //高電平使能,SCLK信號線在閑置時為0
Write_A_Byte_TO_DS1302(addr);
Write_A_Byte_TO_DS1302(dat);
SCLK = 0;RST = 0; //低電平關(guān)使能
}
//設(shè)置初始時間
void Set_InitTime()
{
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x80,0x58); //設(shè)置秒
Write_DS1302(0x82,0x59); //設(shè)置分
Write_DS1302(0x84,0x23); //設(shè)置時
Write_DS1302(0x86,0x31); //設(shè)置日
Write_DS1302(0x88,0x12); //設(shè)置月
Write_DS1302(0x8a,0x07); //設(shè)置星期
Write_DS1302(0x8c,0x05); //設(shè)置年
Write_DS1302(0x8e,0x80); //開啟寫保護
}
//獲取當(dāng)前時間
void GetTime()
{
uchar i,addr = 0x81;
for(i = 0;i<7;i++)
{
DateTime[i] = Read_Data(addr);addr += 2;
}
}
/*
//液晶模塊的忙碌狀態(tài)
uchar Read_LCD_State()
{
uchar state;
RS = 0;RW = 1;EN = 1;DelayMS(1); //根據(jù)規(guī)定,RS為低電平
//RW為高電平時,可以讀狀態(tài)
//EN使能后,才能進行讀寫
//延時一會,給硬件反應(yīng)時間
state = datport; //讀P0口的值
EN = 0;DelayMS(1);
return state; //返回狀態(tài)值
}
*/
//LCD忙檢測
void LCD_Busy_Wait()
{
// // while((Read_LCD_State()&0x80) == 0x80); //忙,則等待
//當(dāng)P0口最高位為1則說明忙
DelayMS(5);
}
//向LCD寫入一個字節(jié)數(shù)據(jù)
void Write_LCD_Data(uchar dat)
{
LCD_Busy_Wait();
RS = 1;RW = 0;EN = 0;datport = dat;EN = 1;DelayMS(1);EN = 0;
}
//向LCD寫入一個字節(jié)命令
void Write_LCD_Command(uchar cmd)
{
LCD_Busy_Wait();
RS = 0;RW = 0;EN = 0;datport = cmd;EN = 1;DelayMS(1);EN = 0;
}
//初始化LCD
void Init_LCD()
{
Write_LCD_Command(0x38);
DelayMS(1);
Write_LCD_Command(0x01);
DelayMS(1);
Write_LCD_Command(0x06);
DelayMS(1);
Write_LCD_Command(0x0c);
DelayMS(1);
}
//設(shè)置顯示位置
void Set_LCD_POS(uchar p)
{
Write_LCD_Command(p|0x80);
}
//在指定位置顯示字符串
void Display_LCD_String(uchar p,uchar *s)
{
uchar i;
Set_LCD_POS(p);
for(i = 0;i < 16;i ++)
{
Write_LCD_Data(s[i]);
DelayMS(1);
}
}
//日期與時間值轉(zhuǎn)換成數(shù)字字符
void Format_DateTime(uchar d,uchar *a)
{
a[0] = d / 10 + '0';
a[1] = d % 10 + '0';
}
//將獲取的時間轉(zhuǎn)換成數(shù)字后存放在緩沖區(qū)
void Format_Changer()
{
//Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5);//將年轉(zhuǎn)換成數(shù)字字符
if(1 == year_flag)
if(flag == 1)
{
LCD_DSY_BUFFER1[5] = ' ';
LCD_DSY_BUFFER1[6] = 0x20;
}
else
{
Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5); //將時轉(zhuǎn)換成數(shù)字字符
}
else
{
Format_DateTime(DateTime[6],LCD_DSY_BUFFER1 + 5); //將時轉(zhuǎn)換成數(shù)字字符
}
//Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8);//將月轉(zhuǎn)換成數(shù)字字符
if(1 == month_flag)
if(flag == 1)
{
LCD_DSY_BUFFER1[8] = 0x20;
LCD_DSY_BUFFER1[9] = 0x20;
}
else
{
Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8); //將時轉(zhuǎn)換成數(shù)字字符
}
else
{
Format_DateTime(DateTime[4],LCD_DSY_BUFFER1 + 8); //將時轉(zhuǎn)換成數(shù)字字符
}
//Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11); //將日轉(zhuǎn)換成數(shù)字字符
if(1 == day_flag)
if(flag == 1)
{
LCD_DSY_BUFFER1[11] = 0x20;
LCD_DSY_BUFFER1[12] = 0x20;
}
else
{
Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11); //將時轉(zhuǎn)換成數(shù)字字符
}
else
{
Format_DateTime(DateTime[3],LCD_DSY_BUFFER1 + 11); //將時轉(zhuǎn)換成數(shù)字字符
}
// strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5]]); //將星期轉(zhuǎn)換成數(shù)字字符
if(1 == week_flag)
if(flag == 1)
{
LCD_DSY_BUFFER1[13] = 0x20;
LCD_DSY_BUFFER1[14] = 0x20;
LCD_DSY_BUFFER1[15] = 0x20;
}
else
{
strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5]]); //將星期轉(zhuǎn)換成數(shù)字字符
}
else
{
strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5]]); //將星期轉(zhuǎn)換成數(shù)字字符
}
if(1 == hour_flag)
if(flag == 1)
{
LCD_DSY_BUFFER2[5] = ' ';
LCD_DSY_BUFFER2[6] = 0x20;
}
else
{
Format_DateTime(DateTime[2],LCD_DSY_BUFFER2 + 5); //將時轉(zhuǎn)換成數(shù)字字符
}
else
{
Format_DateTime(DateTime[2],LCD_DSY_BUFFER2 + 5); //將時轉(zhuǎn)換成數(shù)字字符
}
if(1 == min_flag)
if(flag == 1)
{
LCD_DSY_BUFFER2[8] = 0x20;
LCD_DSY_BUFFER2[9] = 0x20;
}
else
{
Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8); //將時轉(zhuǎn)換成數(shù)字字符
}
else
{
Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8); //將時轉(zhuǎn)換成數(shù)字字符
}
if(1 == second_flag)
if(flag == 1)
{
LCD_DSY_BUFFER2[11] = 0x20;
LCD_DSY_BUFFER2[12] = 0x20;
}
else
{
Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11); //將時轉(zhuǎn)換成數(shù)字字符
}
else
{
Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11); //將時轉(zhuǎn)換成數(shù)字字符
}
// LCD_DSY_BUFFER2[15] = '0' + flag_key;
// Format_DateTime(DateTime[1],LCD_DSY_BUFFER2 + 8); //將分鐘轉(zhuǎn)換成數(shù)字字符
// Format_DateTime(DateTime[0],LCD_DSY_BUFFER2 + 11); //將秒轉(zhuǎn)換成數(shù)字字符
}
//主函數(shù)
void main()
{
Init_LCD(); //初始化LCD
Set_InitTime();//設(shè)置初始時間
TMOD=0x01;
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
EA=1;
TR0=1;
ET0=1;
while(1)
{
//GetTime(); //獲取當(dāng)前時間
//Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
//Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
//Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
temp2 = key();
switch(temp1)
{
case 0: //day_flag = 0;
week_flag = 0;
// second_flag = 0;
flag_key = 0;
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
case 1: hour_flag = 1; flag_key = 1;
GetTime(); //hour
if(10 == temp2)
{
DateTime[2]++;
if(24 == DateTime[2]) DateTime[2] = 0;
DateTime[2] = DateTime[2] / 10 * 16 + DateTime[2] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x84,DateTime[2]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
if(20 == temp2)
{
if(0 == DateTime[2])
DateTime[2] = 24;
DateTime[2]--;
DateTime[2] = DateTime[2] / 10 * 16 + DateTime[2] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x84,DateTime[2]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
/*{
uchar i,addr = 0x81;
for(i = 0;i<7;i++)
{
DateTime[i] = Read_Data(addr);addr += 2;
}
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x80,0x58); //設(shè)置秒
Write_DS1302(0x82,0x59); //設(shè)置分
Write_DS1302(0x84,0x23); //設(shè)置時
Write_DS1302(0x86,0x31); //設(shè)置日
Write_DS1302(0x88,0x12); //設(shè)置月
Write_DS1302(0x8a,0x07); //設(shè)置星期
Write_DS1302(0x8c,0x05); //設(shè)置年
Write_DS1302(0x8e,0x80); //開啟寫保護 */
break;
case 2:hour_flag = 0; min_flag = 1; flag_key = 2;
GetTime(); //min
if(10 == temp2)
{
DateTime[1]++;
if(60 == DateTime[1]) DateTime[1] = 0;
DateTime[1] = DateTime[1] / 10 * 16 + DateTime[1] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x82,DateTime[1]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
if(20 == temp2)
{
if(0 == DateTime[1])
DateTime[1] = 60;
DateTime[1]--;
DateTime[1] = DateTime[1] / 10 * 16 + DateTime[1] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x82,DateTime[1]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
case 3: min_flag = 0;second_flag = 1; flag_key = 3;
GetTime(); //second
if((10 == temp2) || (20 == temp2))
{
DateTime[0] = 0;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x80,DateTime[0]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
case 4: second_flag = 0;year_flag = 1;
GetTime(); //min
if(10 == temp2)
{
DateTime[6]++;
if(100 == DateTime[6]) DateTime[6] = 0;
DateTime[6] = DateTime[6] / 10 * 16 + DateTime[6] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x8c,DateTime[6]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護
}
if(20 == temp2)
{
if(0 == DateTime[6])
DateTime[6] = 100;
DateTime[6]--;
DateTime[6] = DateTime[6] / 10 * 16 + DateTime[6] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x8c,DateTime[6]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
case 5: year_flag = 0;month_flag = 1;
GetTime(); //min
if(10 == temp2)
{
DateTime[4]++;
if(13 == DateTime[4]) DateTime[4] = 1;
DateTime[4] = DateTime[4] / 10 * 16 + DateTime[4] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x88,DateTime[4]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護
}
if(20 == temp2)
{
if(1 == DateTime[4])
DateTime[4] = 13;
DateTime[4]--;
DateTime[4] = DateTime[4] / 10 * 16 + DateTime[4] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x88,DateTime[4]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
case 6: month_flag = 0;day_flag = 1;
GetTime(); //min
day_up = month_table[DateTime[4]];
if((DateTime[4] == 2)&& (DateTime[6] % 4 == 0))
day_up = 30;
day_down = 1;
if(10 == temp2)
{
DateTime[3]++;
if(day_up == DateTime[3]) DateTime[3] = day_down;
DateTime[3] = DateTime[3] / 10 * 16 + DateTime[3] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x86,DateTime[3]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護
}
if(20 == temp2)
{
if(day_down == DateTime[3])
DateTime[3] = day_up;
DateTime[3]--;
DateTime[3] = DateTime[3] / 10 * 16 + DateTime[3] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x86,DateTime[3]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
case 7: day_flag = 0;week_flag = 1;
GetTime(); //min
if(10 == temp2)
{
DateTime[5]++;
if(8 == DateTime[5]) DateTime[5] = 1;
DateTime[5] = DateTime[5] / 10 * 16 + DateTime[5] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x8a,DateTime[5]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護
}
if(20 == temp2)
{
if(1 == DateTime[5])
DateTime[5] = 8;
DateTime[5]--;
DateTime[5] = DateTime[5] / 10 * 16 + DateTime[5] % 10;
Write_DS1302(0x8e,0x00); //關(guān)閉寫保護
Write_DS1302(0x8a,DateTime[5]); //設(shè)置時
Write_DS1302(0x8e,0x80); //開啟寫保護 */
}
GetTime(); //獲取當(dāng)前時間
Format_Changer(); //轉(zhuǎn)換后送給緩沖區(qū)
Display_LCD_String(0x00,LCD_DSY_BUFFER1); //顯示年月日和星期
Display_LCD_String(0x40,LCD_DSY_BUFFER2); //顯示時分秒
break;
}
}
}
uchar key()
{
if(!f1)
{
DelayMS(5);
if(!f1)
{
temp1++;
temp1 = temp1 % 8;
while(!f1);
}
}
if(!f2)
{
DelayMS(5);
if(!f2)
{
return 10;//+
}
}
if(!f3)
{
DelayMS(5);
if(!f3)
{
return 20; //-
}
}
return temp1;
}
void t0(void) interrupt 1 using 0
{
TH0=(65535-50000)/256; //50ms定時
TL0=(65535-50000)%256;
timecount++;
if(timecount>9)
{
timecount=0;
flag=~flag;
}
}