📄 万年历.c
字号:
/********************************************/
/*****************万年历*********************/
//功能描述:采用时钟芯片DS12CR887计时,DS18B20
// 测量温度,LCD1602显示时间。可从2000
// 年至2099年随意调节,显示包括年、月、
// 日、时、分、秒、星期和温度。
//键盘说明:key_1键为设置键
// key_2键为时间加一键
// key_3键为时间减一键
// key_4键位定时设置键
//调时方法:按下key_1键为设置时间
// 按键次数 功能
// 1 设置秒
// 2 设置分
// 3 设置时
// 4 设置日
// 5 设置月
// 6 设置年
// 7 设置星期
// 8 调节结束
// 按键次数 功能
// 1 设置秒
// 2 设置分
// 3 设置时
// 4 设置结束
/********************************************/
#include <REGX51.H>
#include "1602.h"
#include"ds12cr887.h"
/**************键盘引脚定义******************/
sbit key_1 = P3^0; //设置格式
sbit key_2 = P3^1; //+
sbit key_3 = P3^2; //-
sbit buzzer= P1^4; //蜂鸣器
sbit DQ = P1^3; //定义DS18B20
/******************全局变量********************/
uchar t0=0,second=0, min=0, hour=0,day=0,month=0,year=0,weekday=0,flag=0,temp=0,flag1=0;
/******************初始化时间******************/
uchar code table1[]=" 2013-06-01 SAT ";
uchar code table2[]="00:00:00 0000";
uchar code table3[]="Jin Yaxue";
uchar code table4[]="I Love You !";
/*******************字符表*********************/
uchar code word[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x20,0x2d};
uchar code week[][3]={"SUN","MON","TUE","WED","THU","FRI","SAT"};
/************数据缓冲与键盘计数变量************/
uchar databuffer[14],TempBuffer[4],count,t_value;
uint num=0;
/******************函数声明********************/
void init();
void lcd_write_com(uchar command); //1602液晶写命令
void lcd_write_data(uchar date); //1602液晶写数据
void delay(uint a);
void newbuf(); //数据转换
void keyboard(); //键盘子程序
void disp(); //显示程序
void write_ds(uchar add,uchar date);
uchar read_ds(uchar add);
void Init_DS18B20( );
void delay_18B20(unsigned int i);
uchar ReadOneChar(void );
void WriteOneChar(uchar dat);
void ReadTemp(void);
void temp_to_str();
/***********************主函数**********************/
void main()
{
init(); //初始化
Init_DS18B20( ); //DS18B20初始化
lcd_write_com(0x80+3);
for(num=0;num<9;num++) //将table字符串写入
{
lcd_write_data(table3[num]);
delay(200);
}
lcd_write_com(0x80+0x40+2);
for(num=0;num<12;num++) //将table字符串写入
{
lcd_write_data(table4[num]);
delay(200);
}
delay(2000);
lcd_write_com(0x01); //清屏
lcd_write_com(0x80+0x00); //设置指针地址为首行
for(num=0;num<15;num++) //将table字符串写入
{
lcd_write_data(table1[num]);
delay(20);
}
lcd_write_com(0x80+0x40); //设置指针地址为第二行
for(num=0;num<13;num++) //将table1字符串写入
{
lcd_write_data(table2[num]);
delay(20);
}
while(1)
{
uchar b;
keyboard(); //调整时间
ReadTemp(); //开启温度采集程序
temp_to_str(); //温度数据转换成液晶字符
lcd_write_com(0x80+0x40+9);
delay(20);
for(b=0;b<4;b++)
{
lcd_write_data(TempBuffer[b]);
delay(20);
}
if(flag==0)
{
second=read_ds(0x00);
min=read_ds(0x02);
hour=read_ds(0x04);
weekday=read_ds(0x06);
day=read_ds(0x07);
month=read_ds(0x08);
year=read_ds(0x09);
}
newbuf();
{
databuffer[2]=10;
databuffer[5]=10;
}
disp();
}
}
/*************************初始化*************************/
void init()
{
lcd_write_com(0x38); //设置显示模式
lcd_write_com(0x0c); //光标闪烁
lcd_write_com(0x06);
lcd_write_com(0x01); //清屏
write_ds(0x0a,0x20);
write_ds(0x0b,0x26);
read_ds(0x0c);
buzzer=1;
EA=1;
EX1=1;;
IT0=1;
}
/***********************LCD1602写命令************************/
void lcd_write_com(uchar command)
{ //液晶1602写命令
lcdrs=0;
lcdrw=0;
P0=command;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/*************************LCD1602写数据************************/
void lcd_write_data(uchar date)
{
lcdrs=1; //液晶1602写数据
lcdrw=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/***************************延时函数****************************/
void delay(uint a)
{
uint x,y;
for(x=a;x>0;x--)
for(y=110;y>0;y--);
}
/******************************缓冲数据处理*************************/
void newbuf() //更新缓冲区子程序
{
databuffer[0]=second%10;
databuffer[1]=second/10;
databuffer[3]=min%10;
databuffer[4]=min/10;
databuffer[6]=hour%10;
databuffer[7]=hour/10;
databuffer[8]=day%10;
databuffer[9]=day/10;
databuffer[10]=month%10;
databuffer[11]=month/10;
databuffer[12]=year%10;
databuffer[13]=year/10;
}
/**************************液晶数据显示**************************/
void disp() //显示程序
{
uchar j=0;
lcd_write_com(0x80+0x40); //设置指针地址为第二行
lcd_write_data(word[databuffer[7]]); //小时十位
lcd_write_data(word[databuffer[6]]); //小时个位
lcd_write_data(word[databuffer[5]]);
lcd_write_data(word[databuffer[4]]); //分十位
lcd_write_data(word[databuffer[3]]); //分个位
lcd_write_data(word[databuffer[2]]);
lcd_write_data(word[databuffer[1]]); //秒十位
lcd_write_data(word[databuffer[0]]); //秒个位
lcd_write_com(0x80+0x03); //设置指针地址为第一行
lcd_write_data(word[databuffer[13]]); //年十位
lcd_write_data(word[databuffer[12]]); //年个位
lcd_write_data(word[12]);
lcd_write_data(word[databuffer[11]]); //月十位
lcd_write_data(word[databuffer[10]]); //月个位
lcd_write_data(word[12]);
lcd_write_data(word[databuffer[9]]); //日十位
lcd_write_data(word[databuffer[8]]); //日个位
lcd_write_com(0x80+0x0c);
for(j=0;j<3;j++)
{
lcd_write_data( week[weekday-1][j]);
}
}
/******************************键盘扫描*****************************/
void keyboard()
{
if(key_1==0)
{
delay(10);
if(key_1==0)
{
count++; //按键计数,设置模式
while(!key_1);
flag=1;
flag1=0;
read_ds(0x0c);
while(!key_1);
if(count==1) //key_1键摁一次
{
lcd_write_com(0xc0+7); //设置光标为秒位置
lcd_write_com(0x0e);
}
if(count==2) //key_1键摁两次
{
lcd_write_com(0xc0+4); //设置光标为分位置
}
if(count==3) //key_1键摁三次
{
lcd_write_com(0xc0+1); //设置光标为时位置
}
if(count==4) //key_1键摁三次
{
lcd_write_com(0x80+0x09); //设置光标为日位置
}
if(count==5) //key_1键摁三次
{
lcd_write_com(0x80+0x06); //设置光标为月位置
}
if(count==6) //key_1键摁三次
{
lcd_write_com(0x80+0x03); //设置光标为年位置
}
if(count==7) //key_1键摁三次
{
lcd_write_com(0x80+0x01); //设置光标为年位置
}
if(count==8) //key_1键摁四次
{
count=0; //摁键次数清零
lcd_write_com(0x0f); //光标不显示
write_ds(0x00,second);
write_ds(0x02,min);
write_ds(0x04,hour);
write_ds(0x06,weekday);
write_ds(0x07,day);
write_ds(0x08,month);
write_ds(0x09,year);
flag=0;
delay(200);
}
}
}
if(count!=0) //key_1键摁后处理
{
if(key_2==0) //key_2键摁下处理
{
delay(10);
if(key_2==0)
{
while(!key_2);
if(count==1) //key_1键摁一次
{
second++; //秒加一
if(second==60)
second=0;
newbuf();
disp();
lcd_write_com(0xc0+7);
}
if(count==2) //key_1键摁两次
{
min++; //分加一
if(min==60)
min=0;
newbuf();
disp();
lcd_write_com(0xc0+4);
}
if(count==3) //key_1键摁三次
{
hour++; //时加一
if(hour==24)
hour=0;
newbuf();
disp();
lcd_write_com(0xc0+1);
}
if(count==4) //key_1键摁四次
{
day++; //日加一
if(day==32)
day=1;
newbuf();
disp();
lcd_write_com(0x80+0x09);
}
if(count==5) //key_1键摁五次
{
month++; //月加一
if(month==13)
month=1;
newbuf();
disp();
lcd_write_com(0x80+0x06);
}
if(count==6) //key_1键摁六次
{
year++; //年加一
if(year==100)
year=0;
newbuf();
disp();
lcd_write_com(0x80+0x03);
}
if(count==7) //key_1键摁六次
{
weekday++; //年加一
if(weekday==8)
weekday=1;
disp();
lcd_write_com(0x80+0x0c);
delay(200);
}
}
}
if(key_3==0) //key_3键摁下处理
{
delay(10);
if(key_3==0)
{
while(!key_3);
if(count==1) //key_1键摁一次
{
second--; //秒减一
if(second==-1)
second=59;
newbuf();
disp();
lcd_write_com(0xc0+7);
}
if(count==2) //key_1键摁两次
{
min--; //分减一
if(min==-1)
min=59;
newbuf();
disp();
lcd_write_com(0xc0+4);
}
if(count==3) //key_1键摁三次
{
hour--; //时减一
if(hour==-1)
hour=23;
newbuf();
disp();
lcd_write_com(0xc0+1);
}
if(count==4) //key_1键摁四次
{
day--; //日减一
if(day==-1)
day=31;
newbuf();
disp();
lcd_write_com(0x80+0x09);
}
if(count==5) //key_1键摁五次
{
month--; //月减一
if(month==-1)
month=12;
newbuf();
disp();
lcd_write_com(0x80+0x06);
}
if(count==6) //key_1键摁六次
{
year--; //年减一
if(year==-1)
year=99;
newbuf();
disp();
lcd_write_com(0x80+0x03);
}
if(count==7) //key_1键摁六次
{
weekday--; //年减一
if(weekday==0)
weekday=7;
disp();
lcd_write_com(0x80+0x0c);
}
}
}
}
}
/**********************DS12887写数据*****************/
void write_ds(uchar add,uchar date) //ds12887写数据
{
dscs=0;
dsas=1;
dsds=1;
dsrw=1;
P2=add;
dsas=0;
dsrw=0;
P2=date;
dsrw=1;
dsas=1;
dscs=1;
}
/*************************DS12887读数据********************/
uchar read_ds(uchar add) //ds12887读数据
{
uchar ds_date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P2=add;
dsas=0;
dsds=0;
P2=0xff;
ds_date=P2;
dsds=1;
dsas=1;
dscs=1;
return ds_date;
}
/*****************定时中断********************/
void timealarm() interrupt 2
{
uchar c;
buzzer=0;
c=read_ds(0x0c);
}
/***********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读一个字节**************/
uchar ReadOneChar(void)
{
uchar y=0;
uchar dat = 0;
for (y=8;y>0;y--)
{
DQ = 0; // 给脉冲信号
dat>>=1;
DQ = 1; // 给脉冲信号
if(DQ)
dat|=0x80;
delay_18B20(4);
}
return(dat);
}
/*************ds18b20写一个字节****************/
void WriteOneChar(uchar dat)
{
unsigned char z=0;
for (z=8; z>0; z--)
{
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(); //读取温度值高位
t_value=b<<4;
t_value+=(a&0xf0)>>4;
}
void temp_to_str() //温度数据转换成液晶字符显示
{
TempBuffer[0]=t_value/10+'0'; //十位
TempBuffer[1]=t_value%10+'0'; //个位
TempBuffer[2]=0xdf; //温度符号
TempBuffer[3]='C';
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -