基于AT89C51单片机的万年历。。。求大神,求指导

电子万年历原理图
大师啊能不能帮我做一个基于AT89C51单片,机时钟芯片DS1302,LCD的万年历啊,要求不高只要呢能显示年月日,星期就OL。。。万分感谢

第1个回答  2012-11-21
/*****************************ds18b20.H*******************************/
#ifndef DS_18B20_H
#define DS_18B20_H
sbit DQ=P2^4; //定义端口temp
uchar tt;
//uchar code tab1[]={"Temp:"};
uchar code tab2[]={0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
/*延时函数us*/
void Delay(uchar num)
{
while( num-- );
}
void DS18B20_Init(void)//初始化ds1820
{
uchar x = 0;
DQ = 1; //temp复位
Delay(16);
DQ = 0; //单片机将temp拉低
Delay(100); //精确延时 大于 480us
DQ = 1; //拉高总线
Delay(4);
x = DQ; //检测存在脉冲,在此未使用x,自己玩没加
Delay(60);
// return x;
}
uchar DS18B20_ReadOneChar(void)//读一个字节
{
uchar i = 0;
uchar dat = 0;
for (i = 8; i > 0; i--)
{
DQ=1;
_nop_();
DQ = 0; // 给脉冲信号
dat >>= 1;
DQ = 1; // 给脉冲信号
if(DQ)
dat |= 0x80;
Delay(4);
}
return (dat);
}
void DS18B20_WriteOneChar(unsigned char dat)//写一个字节
{
unsigned char i = 0;
for (i = 8; i > 0; i--)
{
DQ=1;
_nop_();_nop_();_nop_();_nop_();
DQ = 0;
Delay(1);//注意
DQ = dat&0x01;
Delay(5);
DQ = 1;
dat>>=1;
}
}
uint DS18B20_Read_Disp_Temperature(void)//读取并显示温度
{
uint th,tl,t = 0;
DS18B20_Init();
DS18B20_WriteOneChar(0xCC); // 跳过读序号列号的操作
DS18B20_WriteOneChar(0x44); // 启动温度转换
Delayms(50);
DS18B20_Init();
DS18B20_WriteOneChar(0xCC); //跳过读序号列号的操作
DS18B20_WriteOneChar(0xBE);
tl = DS18B20_ReadOneChar(); //读取温度寄存器
th = DS18B20_ReadOneChar();
t=th<<4; //转化成字节温度
t +=(tl&0xf0)>>4; //整数部分
tt=tab2[tl&0x0f]; //小数部分(查表对照,获取小数位)
return t;
}
/*void main()
{
Initialization_LCD_1602();
while(1)
{
uchar Gw,Sw;
Gw=DS18B20_Read_Disp_Temperature()%10;//取得个位数字
Sw=DS18B20_Read_Disp_Temperature()/10;//取得十位数字
Pos(2);
Show_String(tab1);
Pos(7);//er是头文件规定的值0x80+0x40
Write_LCD_1602_Data(0x30+Sw);//数字+30得到该数字的LCD1602显示码
Write_LCD_1602_Data(0x30+Gw);//数字+30得到该数字的LCD1602显示码
Write_LCD_1602_Data(0x2e);
Write_LCD_1602_Data(tt+0x30);
Write_LCD_1602_Data(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码
Write_LCD_1602_Data(0x43);//显示"C"符号,0x43是液晶屏字符库里大写C的地址码
}
}*/
#endif
/************************************LCD1602.H*****************************************/
#ifndef LCD_1602_H
#define LCD_1602_H
//#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P2^7;
sbit LCD_RW=P2^6;
sbit LCD_EN=P2^5;
void Delayms(uint x)
{
uchar i;
while(x--)for(i=0;i<110;i++);//at:125;stc:600
}
/*write command*/
void Write_LCD_1602_Command(uchar com)
{
LCD_RS=0;//write lcd1602 command
LCD_RW=0;//write
P0=com;//data
Delayms(1);
LCD_EN=1;
Delayms(1);
LCD_EN=0;
}
/*write data*/
void Write_LCD_1602_Data(uchar dat)
{
LCD_RS=1;
LCD_RW=0;
P0=dat;
LCD_EN=1;
Delayms(1);
LCD_EN=0;
Delayms(1);
}
/*Initialization LCD_1602*/
void Initialization_LCD_1602()
{
Write_LCD_1602_Command(0x38);
Delayms(1);
Write_LCD_1602_Command(0x0c);
Delayms(1);
Write_LCD_1602_Command(0x06);
Delayms(1);
Write_LCD_1602_Command(0x01);
Delayms(1);
}
void Pos(uchar pos)
{
Write_LCD_1602_Command(0x80+pos);
//return 0;
}
void Show_String(uchar *str)
{
while(*str!='\0')
{
Write_LCD_1602_Data(*str);
str++;
}
}
#endif
/**************************************MAIN.C**********************************/
#include <reg52.h>
#include <intrins.h>
#include "lcd1602.h"
#include "ds18B20.h"
#define uint unsigned int
#define uchar unsigned char

/*DS1302IO定义*/
sbit SCK=P1^2;
sbit SDA=P1^3;
sbit RST=P1^4;
/*设定时间键*/
sbit key0=P1^0;//设定
sbit key1=P1^1; //分+
sbit key2=P1^5;//时+
sbit key3=P1^6;//确认
uchar key1m;
uchar Second, Minute,Hour,Week,Day,Month,Year;//DateString[9],TimeString[9];
uchar Data_String[13];
uchar Time_String[12];
/*延时*/
/*void DelayUs(uint x)
{
while(x--);
}*/
/*写一字节*/
void Write_One_Char(uchar dat)
{
uchar i;
//RST=1;
for(i=0;i<8;i++)
{
SDA = dat & 0x01;
SCK = 1;
SCK = 0;
dat >>= 1;
SCK = 0;
}
}
/*读一字节*/
uchar Read_One_Char()
{
uchar i,dat=0;
for(i=0;i<8;i++)
{
dat >>= 1;
if (SDA)
dat |= 0x80;
SCK = 1;
SCK = 0;
}
return dat;
}
/*复位DS1302*/
void Rest_Ds1302()
{
RST = 0;
SCK = 0;
RST = 1;
}
/*写入数据*/
void Write_Ds1302(uchar addr, uchar dat)
{
Rest_Ds1302();
//RST = 1;
Write_One_Char(addr);
Write_One_Char(dat);
SCK=1;
//SDA = 0;
RST = 0;
}
/*读取数据*/
uchar Read_Ds1302(uchar addr)
{
uchar temp=0;
Rest_Ds1302();
//RST = 1;
Write_One_Char(addr);
temp = Read_One_Char();
SCK=1;
//SDA = 0;
RST = 0;
return (temp);
}
uchar BCD_To_Decimal(uchar bcd)
{
uchar Decimal;
Decimal=bcd/16;
return(Decimal=Decimal*10+(bcd%16));
}
void Get_Time()
{
Second=BCD_To_Decimal(Read_Ds1302(0x81));
Minute=BCD_To_Decimal(Read_Ds1302(0x83));
Hour=BCD_To_Decimal(Read_Ds1302(0x85));
Week=BCD_To_Decimal(Read_Ds1302(0x8b));
Day=BCD_To_Decimal(Read_Ds1302(0x87));
Month=BCD_To_Decimal(Read_Ds1302(0x89));
Year=BCD_To_Decimal(Read_Ds1302(0x8d));
Data_String[0]='D';
Data_String[1]=':';
Data_String[2]='2';
Data_String[3]='0';
Data_String[4]=(Year/10)+0x30;
Data_String[5]=(Year%10)+0x30;
Data_String[6]=0x2f;
Data_String[7]=(Month/10)+0x30;
Data_String[8]=(Month%10)+0x30;
Data_String[9]=0x2f;
Data_String[10]=(Day/10)+0x30;
Data_String[11]=(Day%10)+0x30;
Data_String[12]=' ';
Time_String[0]='T';
Time_String[1]=':';
Time_String[2]=(Hour/10)+0x30;
Time_String[3]=(Hour%10)+0x30;
Time_String[4]=0x3a;
Time_String[5]=(Minute/10)+0x30;
Time_String[6]=(Minute%10)+0x30;
Time_String[7]=0x3a;
Time_String[8]=(Second/10)+0x30;
Time_String[9]=(Second%10)+0x30;
}
void Key_Scan()
{
uchar m1,m2;
Write_Ds1302(0x8e,0x00);
Write_Ds1302(0x80,0x80);
if((P1&0xf0)!=0)
Delayms(10);
if((P1&0xf0)!=0)
{
if(key1==0)
{
while(!key1);
Hour++;
if(Hour==24) Hour=0;
m1=Hour/10*16+Hour%10;
Write_Ds1302(0x84,m1);
}
if(key2==0)
{
while(!key2);
Minute++;
if(Minute==60) Minute=0;
m2=(Minute/10*16)+(Minute%10);
Write_Ds1302(0x82,m2);
}
if(key3==0)
{
while(!key3);
Write_Ds1302(0x80,0x00);
Write_Ds1302(0x8e,0x80);
key1m=0;
}
}
}
void Ds1302_Init() //1302芯片初始化子函数(2010-01-07,12:00:00,week4)
{
RST=0;
SCK=0;
Write_Ds1302(0x8e,0x00); //允许写,禁止写保护
Write_Ds1302(0x80,0x00); //向DS1302内写秒寄存器80H写入初始秒数据00
Write_Ds1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00
Write_Ds1302(0x84,0x09);//向DS1302内写小时寄存器84H写入初始小时数据12
Write_Ds1302(0x8a,0x05);//向DS1302内写周寄存器8aH写入初始周数据4
Write_Ds1302(0x86,0x05);//向DS1302内写日期寄存器86H写入初始日期数据07
Write_Ds1302(0x88,0x05);//向DS1302内写月份寄存器88H写入初始月份数据01
Write_Ds1302(0x8c,0x11);//向DS1302内写年份寄存器8cH写入初始年份数据10
Write_Ds1302(0x8e,0x80); //打开写保护
}
void Write_Week(uchar week)//写星期函数
{
Pos(0x0d);//星期字符的显示位置
switch(week)
{
case 1:Write_LCD_1602_Data('S');//星期数据为7时显示
Write_LCD_1602_Data('U');
Write_LCD_1602_Data('N');
break;
case 2:Write_LCD_1602_Data('M');//星期数为1时,显示
Write_LCD_1602_Data('O');
Write_LCD_1602_Data('N');
break;

case 3:Write_LCD_1602_Data('T');//星期数据为2时显示
Write_LCD_1602_Data('U');
Write_LCD_1602_Data('E');
break;
case 4:Write_LCD_1602_Data('W');//星期数据为3时显示
Write_LCD_1602_Data('E');
Write_LCD_1602_Data('D');
break;
case 5:Write_LCD_1602_Data('T');//星期数据为4是显示
Write_LCD_1602_Data('H');
Write_LCD_1602_Data('U');
break;
case 6:Write_LCD_1602_Data('F');//星期数据为5时显示
Write_LCD_1602_Data('R');
Write_LCD_1602_Data('I');
break;
case 7 :Write_LCD_1602_Data('S');//星期数据为6时显示
Write_LCD_1602_Data('T');
Write_LCD_1602_Data('A');
break;
}
}
void main()
{
Ds1302_Init();
Initialization_LCD_1602();
while(1)
{
Get_Time();
if(key0==0)
{
Delayms(10);
if(key0==0)
{
while(!key0)
key1m=1;
}
}
if(key1m==1)Key_Scan();
Pos(0);
Show_String(Data_String);
Write_Week(Week);
Pos(0x40);
Show_String(Time_String);
Pos(0x40+0x0b);//er是头文件规定的值0x80+0x40
Write_LCD_1602_Data('0'+(DS18B20_Read_Disp_Temperature()/10));//数字+30得到该数字的LCD1602显示码
Write_LCD_1602_Data('0'+(DS18B20_Read_Disp_Temperature()%10));//数字+30得到该数字的LCD1602显示码
Write_LCD_1602_Data(0x2e);
Write_LCD_1602_Data(tt+0x30);
//Write_LCD_1602_Data(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码
Write_LCD_1602_Data(0x43);//显示"C"符号,0x43是液晶屏字符库里大写C的地址码
}
}
这个是带年月日,星期,温度显示,小时分秒,可调,你可以参考一下噢!本回答被网友采纳