基于AT89C51单片机的万年历。。。求大神,求指导 10
电子万年历原理图大师啊能不能帮我做一个基于AT89C51单片,机时钟芯片DS1302,LCD的万年历啊,要求不高只要呢能显示年月日,星期就OL。。。万分感谢...
电子万年历原理图
大师啊能不能帮我做一个基于AT89C51单片,机时钟芯片DS1302,LCD的万年历啊,要求不高只要呢能显示年月日,星期就OL。。。万分感谢 展开
大师啊能不能帮我做一个基于AT89C51单片,机时钟芯片DS1302,LCD的万年历啊,要求不高只要呢能显示年月日,星期就OL。。。万分感谢 展开
2个回答
展开全部
/*****************************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的地址码
}
}
这个是带年月日,星期,温度显示,小时分秒,可调,你可以参考一下噢!
#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的地址码
}
}
这个是带年月日,星期,温度显示,小时分秒,可调,你可以参考一下噢!
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
深圳市兴威帆电子技术有限公司
2023-08-24 广告
2023-08-24 广告
实时时钟模块可以选择许多不同的制造商和型号,具体选择取决于您的应用需求和预算。一些流行的实时时钟模块品牌包括DS1302、MA电商平台6925和MCP7941。这些模块都具有精度高、稳定性好、功耗低等优点,并具有不同的功能和特性,可以满足各...
点击进入详情页
本回答由深圳市兴威帆电子技术有限公司提供
展开全部
#include <reg51.h> #include <string.h> #define uchar unsigned char #define uint unsigned int sbit SDA=P1^0; //DS1302数据线 sbit CLK = P1^1; //DS1302时钟线 sbit RST = P1^2; //DS1302复位线 sbit RS = P2^0; //LCD寄存器选择 sbit RW = P2^1; //LCD读/写控制 sbit EN = P2^2; //LCD启用 sbit K1 = P3^4; //按键选择 sbit K2 = P3^5; //按键加 sbit K3 = P3^6; //按键减 sbit K4 = P3^7; //按键确定 uchar tCount =0; //一年中的每个月的天数,2月的天数有年份决定 uchar MonthsDays[] = {0,31,0,31,30,31,30,31,31,30,31,30,31}; //周日,周一到周六(0,1-6)[读取DS1302时分别是1-7] uchar *WEEK[] = {"SUN","MON","TUS","WEN","THU","FRI","SAT"};
23//LCD显示缓冲 uchar LCD_DSY_BUFFER1[] = {"DATE 00-00-00 "}; uchar LCD_DSY_BUFFER2[] = {"TIME 00-00-00 "}; uchar DateTime[7]; //所读取的日期时间 char Adjust_Index = -1; //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,5,6) uchar Change_Flag[] = "-MHDM-Y"; //(分,时,日,月,年) void Write_A_Byte_TO_DS1302(uchar x) //向DS1302写入一字节 { uchar i; for ( i = 0; i <8; i++ ) { SDA = x & 1; CLK = 1;CLK = 0;x >>=1; } } void Write_DS1302 (uchar addr,uchar dat) //向DS1302某地址写入数据 { CLK = 0; RST = 1; Write_A_Byte_TO_DS1302(addr); Write_A_Byte_TO_DS1302(dat); CLK = 0; RST =0 ; } //设置时间 void SET_DS1302 () { uchar i; //写控制字,取消写保护 Write_DS1302 (0x8E,0x00); //分时日月年依次写入 for(i = 1; i < 7; i++) { //分的起始地址10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递减2 Write_DS1302(0x80 + 2*i,(DateTime[i]/10<<4) | (DateTime[i]%10)); } Write_DS1302(0x8E,0x80); //加保护 } uchar Get_A_Byte_FROM_DS1302() //从DS1302读取一字节 {uchar i,b,t; for (i = 0;i < 8;i++) { b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0; } return b/16*10+b%16; }
unchar Read_Data (uchar addr) //从DS1302指定位置读数据 { uchar dat; RST = 0;CLK = 0;RST = 1; Write_A_Byte_TO_DS1302(addr); dat = Get_A_Byte_FROM_DS1302(); CLK=1;RST=0; return dat; } //读取当前日期时间 void GetTime() { uchar i; for (i = 0; i < 7; i++) { DateTime[i] = Read_Date(0x81 + 2*i); } } //在LCD上显示字符串 viod 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); } } //日期与时间值转换成为数字字符 void Format_DateTime(uchar d, uchar *a) { a[0] = d/10+'0'; a[1] = d%10 + '0'; } //判断是否为闰年 uchar isLeapYear(uint y) { return (y % 4 = =&&y % 100!=0)||(y%400 = = 0); } //求自2000.1.1开始的任何一天是星期几 //函数没有通过,求出总天数后再求星期几 //因为求总天数可能会越出uint的范围 viod RefreshWeekDay() { uint i,d,w=5; //1999.12.31是星期五 for (i = 2000; i < 2000+DateTime[6];i++)
{ d = isLeapYear(i) ? 366 :365; w = (w + d) % 7; } d = 0; for (i = 1; i < DateTime[4] ; i++ ) d += MonthsDays[i]; d += DateTime[3]; //保存星期,0~6表示星期日,星期一,二…,六,为了与DS1302的星期格式匹配,返回值需加1 DateTime[5] = (w + d) % 7 + 1; } //年月日时分++/-- void DateTime_Adjust(char x) { switch ( Adjust_Index ) { case 6: if (x = =1 && DateTime[6] < 99) DateTime[6]++; if (x = = -1 && DateTime[6] > 0) DateTime[6]--; //获取2月天数 MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28; //如果年份变化后当前月份的天数大于上限则设为上限 if ( DateTime[3] > MonthsDays[DateTime[4]] ) DateTime3] = MonthsDays[DateTime[4]]; RefreshWeekDay(); //刷新星期 break; case 4: if (x = =1 && DateTime[4] < 12) DateTime[4]++; if (x = =-1 && DateTime[4] >1) DateTime[4]--; //获取2月天数 MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28; //如果年份变化后当前月份的天数大于上限则设为上限 if ( DateTime[3] > MonthsDays[DateTime[4]] ) DateTime3] = MonthsDays[DateTime[4]]; RefreshWeekDay(); //刷新星期 break; case 3: //日00-28/29/30/31;调节之前首先根据年份得出该年中2月份的天数 MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28; //如果年份变化后当前月份的天数大于上限则设为上限 if (x = =1 && DateTime[3] < MonthsDays[DateTime[4]]) DateTime[3]++; if (x = =-1 && DateTime[3] >0) DateTime[3]--; RefreshWeekDay(); //刷新星期 break; case 2: //时 if (x = =1 && DateTime[2] < 23) DateTime[2]++; if (x = =-1 && DateTime[2] >0) DateTime[2]--;
break; case 1: //分 if (x = =1 && DateTime[1] < 59) DateTime[1]++; if (x = =-1 && DateTime[1] >0) DateTime[1]--; break; } } //定时器0每秒刷新LCD显示 void T0_INT() interrupt 1 { TH0 = -50000 / 256; TL0 = -50000 % 256; if (++tCount != 2) return; tCount = 0; Format_DateTime(DateTime[6],LCD_DSY_BUFFR1 + 5); Format_DateTime(DateTime[4],LCD_DSY_BUFFR1 + 8); Format_DateTime(DateTime[3],LCD_DSY_BUFFR1 + 11); strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5] - 1] ); Format_DateTime(DateTime[2],LCD_DSY_BUFFR1 + 5); Format_DateTime(DateTime[1],LCD_DSY_BUFFR1 + 8); Format_DateTime(DateTime[0],LCD_DSY_BUFFR1 + 11); Display_LCD-String(0x00, LCD-DSY_BUFFER1); Display_LCD-String(0x40, LCD-DSY_BUFFER2); } //键盘中断(INT0) void EX_INT0 () interrupt 0 { if (K1 = =0) //选择调整对象 { while (K1 = = 0); if (Adjust_Index = = -1 || Adjust_Index = =1) Adjust_Index = 7;0 Adjust_Index--; if (Adjust_Index = = 5 ) Adjust_Index = 4; LCD_DSY_BUFFER2[13] = '[' ; LCD_DSY_BUFFER2[14] = Change_Flag[Adjust_Index]; LCD_DSY_BUFFER2[15] = ']' ; } else if (K2 = = 0) //加 { while (K2 = =0); DateTime_Adjust(1);
} else if (K3 = =0 ) //减 { while (K3 = =0); DateTime_Adjust(-1); } else if (K4 = =0) //确定 { while (K4 = =0); SET_DS1302(); LCD_DSY_BUFFER2[13] = ' '; LCD_DSY_BUFFER2[14] = ' '; LCD_DSY_BUFFER2[15] = ' '; Adjust_Index = -1; } } 主程序 void main () { Init_LCD (); //液晶初始化 IE = 0x83; //允许INT0,T0中断 IP =0x01; IT0 =0x01; TMOD = 0x01; TH0 = -50000 / 256; TL0 = -50000 % 256 ; TR0 = 1; while(1) { //如果未执行调整操作则正常读取当前时间 if (Adjust_Index = = -1) GetTime (); } }
23//LCD显示缓冲 uchar LCD_DSY_BUFFER1[] = {"DATE 00-00-00 "}; uchar LCD_DSY_BUFFER2[] = {"TIME 00-00-00 "}; uchar DateTime[7]; //所读取的日期时间 char Adjust_Index = -1; //当前调节的时间对象:秒,分,时,日,月,年(0,1,2,3,4,5,6) uchar Change_Flag[] = "-MHDM-Y"; //(分,时,日,月,年) void Write_A_Byte_TO_DS1302(uchar x) //向DS1302写入一字节 { uchar i; for ( i = 0; i <8; i++ ) { SDA = x & 1; CLK = 1;CLK = 0;x >>=1; } } void Write_DS1302 (uchar addr,uchar dat) //向DS1302某地址写入数据 { CLK = 0; RST = 1; Write_A_Byte_TO_DS1302(addr); Write_A_Byte_TO_DS1302(dat); CLK = 0; RST =0 ; } //设置时间 void SET_DS1302 () { uchar i; //写控制字,取消写保护 Write_DS1302 (0x8E,0x00); //分时日月年依次写入 for(i = 1; i < 7; i++) { //分的起始地址10000010(0x82),后面依次是时,日,月,周,年,写入地址每次递减2 Write_DS1302(0x80 + 2*i,(DateTime[i]/10<<4) | (DateTime[i]%10)); } Write_DS1302(0x8E,0x80); //加保护 } uchar Get_A_Byte_FROM_DS1302() //从DS1302读取一字节 {uchar i,b,t; for (i = 0;i < 8;i++) { b>>=1;t=SDA;b|=t<<7;CLK=1;CLK=0; } return b/16*10+b%16; }
unchar Read_Data (uchar addr) //从DS1302指定位置读数据 { uchar dat; RST = 0;CLK = 0;RST = 1; Write_A_Byte_TO_DS1302(addr); dat = Get_A_Byte_FROM_DS1302(); CLK=1;RST=0; return dat; } //读取当前日期时间 void GetTime() { uchar i; for (i = 0; i < 7; i++) { DateTime[i] = Read_Date(0x81 + 2*i); } } //在LCD上显示字符串 viod 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); } } //日期与时间值转换成为数字字符 void Format_DateTime(uchar d, uchar *a) { a[0] = d/10+'0'; a[1] = d%10 + '0'; } //判断是否为闰年 uchar isLeapYear(uint y) { return (y % 4 = =&&y % 100!=0)||(y%400 = = 0); } //求自2000.1.1开始的任何一天是星期几 //函数没有通过,求出总天数后再求星期几 //因为求总天数可能会越出uint的范围 viod RefreshWeekDay() { uint i,d,w=5; //1999.12.31是星期五 for (i = 2000; i < 2000+DateTime[6];i++)
{ d = isLeapYear(i) ? 366 :365; w = (w + d) % 7; } d = 0; for (i = 1; i < DateTime[4] ; i++ ) d += MonthsDays[i]; d += DateTime[3]; //保存星期,0~6表示星期日,星期一,二…,六,为了与DS1302的星期格式匹配,返回值需加1 DateTime[5] = (w + d) % 7 + 1; } //年月日时分++/-- void DateTime_Adjust(char x) { switch ( Adjust_Index ) { case 6: if (x = =1 && DateTime[6] < 99) DateTime[6]++; if (x = = -1 && DateTime[6] > 0) DateTime[6]--; //获取2月天数 MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28; //如果年份变化后当前月份的天数大于上限则设为上限 if ( DateTime[3] > MonthsDays[DateTime[4]] ) DateTime3] = MonthsDays[DateTime[4]]; RefreshWeekDay(); //刷新星期 break; case 4: if (x = =1 && DateTime[4] < 12) DateTime[4]++; if (x = =-1 && DateTime[4] >1) DateTime[4]--; //获取2月天数 MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28; //如果年份变化后当前月份的天数大于上限则设为上限 if ( DateTime[3] > MonthsDays[DateTime[4]] ) DateTime3] = MonthsDays[DateTime[4]]; RefreshWeekDay(); //刷新星期 break; case 3: //日00-28/29/30/31;调节之前首先根据年份得出该年中2月份的天数 MonthsDays[2] = isLeapYear(2000 + DateTime[6]) ? 29 : 28; //如果年份变化后当前月份的天数大于上限则设为上限 if (x = =1 && DateTime[3] < MonthsDays[DateTime[4]]) DateTime[3]++; if (x = =-1 && DateTime[3] >0) DateTime[3]--; RefreshWeekDay(); //刷新星期 break; case 2: //时 if (x = =1 && DateTime[2] < 23) DateTime[2]++; if (x = =-1 && DateTime[2] >0) DateTime[2]--;
break; case 1: //分 if (x = =1 && DateTime[1] < 59) DateTime[1]++; if (x = =-1 && DateTime[1] >0) DateTime[1]--; break; } } //定时器0每秒刷新LCD显示 void T0_INT() interrupt 1 { TH0 = -50000 / 256; TL0 = -50000 % 256; if (++tCount != 2) return; tCount = 0; Format_DateTime(DateTime[6],LCD_DSY_BUFFR1 + 5); Format_DateTime(DateTime[4],LCD_DSY_BUFFR1 + 8); Format_DateTime(DateTime[3],LCD_DSY_BUFFR1 + 11); strcpy(LCD_DSY_BUFFER1 + 13,WEEK[DateTime[5] - 1] ); Format_DateTime(DateTime[2],LCD_DSY_BUFFR1 + 5); Format_DateTime(DateTime[1],LCD_DSY_BUFFR1 + 8); Format_DateTime(DateTime[0],LCD_DSY_BUFFR1 + 11); Display_LCD-String(0x00, LCD-DSY_BUFFER1); Display_LCD-String(0x40, LCD-DSY_BUFFER2); } //键盘中断(INT0) void EX_INT0 () interrupt 0 { if (K1 = =0) //选择调整对象 { while (K1 = = 0); if (Adjust_Index = = -1 || Adjust_Index = =1) Adjust_Index = 7;0 Adjust_Index--; if (Adjust_Index = = 5 ) Adjust_Index = 4; LCD_DSY_BUFFER2[13] = '[' ; LCD_DSY_BUFFER2[14] = Change_Flag[Adjust_Index]; LCD_DSY_BUFFER2[15] = ']' ; } else if (K2 = = 0) //加 { while (K2 = =0); DateTime_Adjust(1);
} else if (K3 = =0 ) //减 { while (K3 = =0); DateTime_Adjust(-1); } else if (K4 = =0) //确定 { while (K4 = =0); SET_DS1302(); LCD_DSY_BUFFER2[13] = ' '; LCD_DSY_BUFFER2[14] = ' '; LCD_DSY_BUFFER2[15] = ' '; Adjust_Index = -1; } } 主程序 void main () { Init_LCD (); //液晶初始化 IE = 0x83; //允许INT0,T0中断 IP =0x01; IT0 =0x01; TMOD = 0x01; TH0 = -50000 / 256; TL0 = -50000 % 256 ; TR0 = 1; while(1) { //如果未执行调整操作则正常读取当前时间 if (Adjust_Index = = -1) GetTime (); } }
来自:求助得到的回答
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询