基于AT89C+1602+DS1302+DS18B20的电子时钟带按键调整.docx
- 文档编号:7188826
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:22
- 大小:21.98KB
基于AT89C+1602+DS1302+DS18B20的电子时钟带按键调整.docx
《基于AT89C+1602+DS1302+DS18B20的电子时钟带按键调整.docx》由会员分享,可在线阅读,更多相关《基于AT89C+1602+DS1302+DS18B20的电子时钟带按键调整.docx(22页珍藏版)》请在冰豆网上搜索。
基于AT89C+1602+DS1302+DS18B20的电子时钟带按键调整
网上很多类似的电子时钟的单片机采用的是89C51或89C52,而用2051的时钟功能又较少,基本只用于显示时间,不带温度显示和按键调整,原因可能2051的I/O口较少。
其中LCD1602正常需要RS、RW、EN、D0~D7,共11个接口与单片机相连,于是本人通过将LCD1602用四线传输数据的方法节省出4个I/O口,并将RW端口直接接地再节省出1个I/O口。
由此可节省出5个I/O口作为按键接口和温度数据传输接口。
本人接触单片机不久,所以从网上搜索了一些89C51时钟的程序,再原有基础上进行改写和整合得到了控制程序。
本时钟具有日期、星期、时间和温度的显示,并可以通过按键来调整。
另外,硬件上还留有一个P3.5端口,可作它用,如添加闹钟功能等。
以下是原理图
以下是C程序
#include
#include
#include"ds18b20_3.h"//头文件总设置ds18b20的DQ端
#defineucharunsignedchar
#defineuintunsignedint
/*------------------寄存器地址定义------------*/
#defineWRITE_SECOND0x80
#defineWRITE_MINUTE0x82
#defineWRITE_HOUR0x84
#defineWRITE_DAY0x86
#defineWRITE_MONTH0x88
#defineWRITE_YEAR0x8C
#defineWRITE_PROTECT0x8E
#defineWRITE_WEEK0x8A
//#defineWRITE_CURRENT0x90
#defineREAD_SECOND0x81
#defineREAD_MINUTE0x83
#defineREAD_HOUR0x85
#defineREAD_DAY0x87
#defineREAD_MONTH0x89
#defineREAD_WEEK0x8B
#defineREAD_YEAR0x8D
sbitLCD_E=P1^3;//液晶使能端
sbitLCD_RS=P1^2;//液晶数据命令选择端
//sbitLCD_RW=P2^5;//液晶读写选择端,直接接地,不需要
sbitRST=P3^7;//DS1302片选
sbitDIO=P3^1;//DS1302数据信号
sbitSCLK=P3^0;//DS1302时钟信号
sbitkey0=P3^2;//功能键
sbitkey1=P3^3;//增大键
sbitkey2=P3^4;//减小键
sbitbeep=P1^0;//蜂鸣器
sbitACC7=ACC^7;
sbitACC0=ACC^0;
unsignedcharREAD_1302(unsignedcharaddr);
charhour,minute,second,week,day,month,year,tem;
unsignedcharnum,flag,count,wendu;
unsignedcharstr1[]="20--";
unsignedcharstr2[]=":
:
";
voiddelay(unsignedcharz);
voidINITIAL_1302();
voidWRITE_1302(unsignedcharaddr,unsignedchardate);
voidLCD_WRITE_COM(unsignedcharcom);
voidLCD_WRITE_DATA(unsignedchardate);
voidLCD_WRITE_SFM(unsignedcharaddr,unsignedchardate);
voidLCD_WRITE_NYR(unsignedcharaddr,unsignedchardate);
voidLCD_WRITE_WEEK(unsignedcharweek);
voidLCD_INITIAL();
voidkeyscan();
voidINITIAL_TEMER0();
voidw1602c(ucharcom);
voidw1602d(uchardata01);
voidwrite_temp(ucharadd,uchardate);
voidmain()
{
LCD_INITIAL();//液晶初始化
INITIAL_1302();//DS1302初始化
INITIAL_TEMER0();//定时器初始化
beep=0;//蜂鸣器长响一次
delay(1000);
beep=1;
while
(1)
{
keyscan();//按键扫描
if(flag==0)//当标志位为0,允许读取DS1302数据,将数据送入液晶显示
{
second=READ_1302(0x81);
LCD_WRITE_SFM(8,second);
minute=READ_1302(0x83);
LCD_WRITE_SFM(5,minute);
hour=READ_1302(0x85);
LCD_WRITE_SFM(2,hour);
week=READ_1302(0x8b);
LCD_WRITE_WEEK(week);
day=READ_1302(0x87);
LCD_WRITE_NYR(9,day);
month=READ_1302(0x89);
LCD_WRITE_NYR(6,month);
year=READ_1302(0x8d);
LCD_WRITE_NYR(3,year);
wendu=ReadTemperature();//将18b2头文件运行返回的函数结果送到变量wendu中,用于显示
write_temp(11,wendu);//显示温度,从第二行第12个字符后开始显示
}
}
}
/**********************1602部份************************************/
voiddelay(unsignedcharz)//1602de延时函数
{
unsignedcharx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voidLCD_WRITE_COM(unsignedcharcom)//1602四线控制,将数据高四位和低四位分两次写入
{
LCD_RS=0;
LCD_E=1;
delay
(1);
P1=(P1&0x0f)|(com&0xf0);//将com的高四位送到P1的高四位,并保持P1的低四位不变
delay
(2);
LCD_E=0;
delay(5);
LCD_E=0;
com<<=4;//将com的原低四位移到高四位,准备送到P1的高四位
delay
(1);
LCD_E=1;
delay
(1);
P1=(P1&0x0f)|(com&0xf0);
delay
(2);
LCD_E=0;
}
voidLCD_WRITE_DATA(unsignedchardate)
{
LCD_RS=1;
LCD_E=1;
delay
(1);
P1=(P1&0x0f)|(date&0xf0);
delay
(2);
LCD_E=0;
delay(5);
LCD_E=0;
date<<=4;
delay
(1);
LCD_E=1;
delay
(1);
P1=(P1&0x0f)|(date&0xf0);
delay
(2);
LCD_E=0;
}
voidLCD_WRITE_SFM(unsignedcharaddr,unsignedchardate)
{
unsignedcharshi,ge;
shi=date/10;
ge=date%10;
LCD_WRITE_COM(0x80+0x40+addr);
LCD_WRITE_DATA(0x30+shi);
LCD_WRITE_DATA(0x30+ge);
}
voidLCD_WRITE_NYR(unsignedcharaddr,unsignedchardate)
{
charshi,ge;
shi=date/10;
ge=date%10;
LCD_WRITE_COM(0x80+addr);
LCD_WRITE_DATA(0x30+shi);
LCD_WRITE_DATA(0x30+ge);
}
voidLCD_WRITE_WEEK(unsignedcharweek)
{
LCD_WRITE_COM(0x80+12);
switch(week)
{
case1:
LCD_WRITE_DATA('M');delay(5);
LCD_WRITE_DATA('O');delay(5);
LCD_WRITE_DATA('N');
LCD_WRITE_DATA('1');break;
case2:
LCD_WRITE_DATA('T');delay(5);
LCD_WRITE_DATA('U');delay(5);
LCD_WRITE_DATA('E');
LCD_WRITE_DATA('2');break;
case3:
LCD_WRITE_DATA('W');delay(5);
LCD_WRITE_DATA('E');delay(5);
LCD_WRITE_DATA('D');
LCD_WRITE_DATA('3');break;
case4:
LCD_WRITE_DATA('T');delay(5);
LCD_WRITE_DATA('H');delay(5);
LCD_WRITE_DATA('U');
LCD_WRITE_DATA('4');break;
case5:
LCD_WRITE_DATA('F');delay(5);
LCD_WRITE_DATA('R');delay(5);
LCD_WRITE_DATA('I');
LCD_WRITE_DATA('5');break;
case6:
LCD_WRITE_DATA('S');delay(5);
LCD_WRITE_DATA('A');delay(5);
LCD_WRITE_DATA('T');
LCD_WRITE_DATA('6');break;
case7:
LCD_WRITE_DATA('S');delay(5);
LCD_WRITE_DATA('U');delay(5);
LCD_WRITE_DATA('N');
LCD_WRITE_DATA('7');break;
}
}
voidLCD_INITIAL()
{
unsignedchari;
LCD_WRITE_COM(0x28);//0x28=00101000,将液晶设置为16*2显示,5*7点阵,4位数据口
delay(5);
LCD_E=1;
LCD_E=0;
LCD_WRITE_COM(0x28);//显示方式设置
LCD_WRITE_COM(0x0c);//设置开显示,不显光标
LCD_WRITE_COM(0x06);//默认(0x06)写入新数据后光标右移屏幕不移动
LCD_WRITE_COM(0x01);//显示清0,数据指针清0
LCD_WRITE_COM(0x80);
for(i=0;i<16;i++)
{
LCD_WRITE_DATA(str1[i]);
delay(5);
}
LCD_WRITE_COM(0x80+0x40);//液晶第二行显示
for(i=0;i<9;i++)
{
LCD_WRITE_DATA(str2[i]);
delay(5);
}
}
/***************************1302部分*****************************************/
voidWRITE_1302(unsignedcharaddr,unsignedchardate)
{
unsignedchari;
RST=0;
SCLK=0;
RST=1;
for(i=8;i>0;i--)
{
SCLK=0;
ACC=addr;
DIO=ACC0;
addr>>=1;
SCLK=1;
}
for(i=8;i>0;i--)
{
SCLK=0;
ACC=date;
DIO=ACC0;
date>>=1;
SCLK=1;
}
RST=0;
}
unsignedcharREAD_1302(unsignedcharaddr)
{
unsignedchari,date1,date2;
RST=0;
SCLK=0;
RST=1;
for(i=8;i>0;i--)
{
SCLK=0;
ACC=addr;
DIO=ACC0;
addr>>=1;
SCLK=1;
}
for(i=8;i>0;i--)
{
ACC7=DIO;
SCLK=1;
ACC>>=1;
SCLK=0;
}
RST=0;
date1=ACC;
date2=date1/16;
date1=date1%16;
date1=date1+date2*10;
return(date1);
}
voidINITIAL_1302()
{
WRITE_1302(WRITE_SECOND,READ_1302(READ_SECOND)&0x7f);//启动DS1302
}
/**************************键盘扫描部分***********************************/
voidkeyscan()
{
if(key0==0)//确认功能键按下
{
delay(20);
if(key0==0)//去抖
{beep=0;
delay(200);
beep=1;
while(!
key0);//释放
num++;
switch(num)
{
case1:
flag=1;//修改时间,禁止从DS1302读数据
TR0=0;//定时器关
LCD_WRITE_COM(0x0f);//光标开始闪烁
LCD_WRITE_COM(0x80+3);//第一次按下,光标定位到年位置
break;
case2:
LCD_WRITE_COM(0x80+6);//第二次按下,光标定位到月位置
break;
case3:
LCD_WRITE_COM(0x80+9);//第三次按下,光标定位到日位置
break;
case4:
LCD_WRITE_COM(0x80+12);//第四次按下,光标定位到星期位置
break;
case5:
LCD_WRITE_COM(0x80+0x40+2);//第五次按下,光标定位到时位置
break;
case6:
LCD_WRITE_COM(0x80+0x40+5);//第六次按下,光标定位到分位置
break;
case7:
LCD_WRITE_COM(0x80+0x40+8);//第七次按下,光标定位到秒位置
break;
case8:
num=0;//第八次按下,记录清零
LCD_WRITE_COM(0x0c);//不显示光标
WRITE_1302(WRITE_PROTECT,0x00);//允许写操作
WRITE_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302
WRITE_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302
WRITE_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302
WRITE_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302
WRITE_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302
WRITE_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302
WRITE_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302
WRITE_1302(WRITE_PROTECT,0x80);//开写保护
flag=0;//时间修改完毕,允许液晶从DS1302读数据
TR0=1;
break;
}
}
}
if(num!
=0)
{
if(key1==0)//确认增大键按下
{
delay(20);
if(key1==0)//增大键确实按下
{
beep=0;
delay(200);
beep=1;
while(!
key1);
switch(num)
{
case1:
year++;//调节年
if(year==100)year=0;
LCD_WRITE_NYR(3,year);//将调节后的年送入液晶显示
LCD_WRITE_COM(0x80+3);//光标回到指定处
break;
case2:
month++;//调节月
if(month==13)month=0;
LCD_WRITE_NYR(6,month);//将调节后的月送入液晶显示
LCD_WRITE_COM(0x80+6);//光标回到指定处
break;
case3:
day++;//调节日
if(day==32)day=0;
LCD_WRITE_NYR(9,day);//将调节后的日送入液晶显示
LCD_WRITE_COM(0x80+9);//光标回到指定处
break;
case4:
week++;
if(week==8)week=0;
LCD_WRITE_WEEK(week);//将调节后的星期送入液晶显示
LCD_WRITE_COM(0x80+12);//光标回到指定处
break;
case5:
hour++;
if(hour==24)hour=0;
LCD_WRITE_SFM(2,hour);//将调节后的小时送入液晶显示
LCD_WRITE_COM(0x80+0x40+2);//光标回到指定处
break;
case6:
minute++;
if(minute==60)minute=0;
LCD_WRITE_SFM(5,minute);//将调节后的分送入液晶显示
LCD_WRITE_COM(0x80+0x40+5);//光标回到指定处
break;
case7:
second++;
if(second==60)second=0;
LCD_WRITE_SFM(8,second);//将调节后的秒送入液晶显示
LCD_WRITE_COM(0x80+0x40+8);//光标回到指定处
break;
default:
break;
}
}
}
if(key2==0)//确认减小键按下
{
delay(20);
if(key2==0)//减小键确实按下
{
beep=0;
delay(200);
beep=1;
while(!
key2);
switch(num)
{
case1:
year--;//调节年
if(year==-1)year=99;
LCD_WRITE_NYR(3,year);
LCD_WRITE_COM(0x80+3);
break;
case2:
month--;//调节月
if(month==-1)month=12;
LCD_WRITE_NYR(6,month);
LCD_WRITE_COM(0x80+6);
break;
case3:
day--;//调节日
if(day==-1)day=31;
LCD_WRITE_NYR(9,day);
LCD_WRITE_COM(0x80+9);
break;
case4:
week--;//调节星期
if(week==0)week=7;
LCD_WRITE_WEEK(week);
LCD_WRITE_COM(0x80+12);
break;
case5:
hour--;//调节时
if(hour==-1)hour=23;
LCD_WRITE_SFM(2,hour);
LCD_WRITE_COM(0x80+0x40+2);
break;
case6:
minute--;//调节分
if(minute==-1)minute=59;
LCD_WRITE_SFM(5,minute);
LCD_WRITE_COM(0x80+0x40+5);
break;
case7:
second--;//调节秒
if(second==-1)second=59;
LCD_WRITE_SFM(8,second);
LCD_WRITE_COM(0x80+0x40+8);
break;
default:
break;
}
}
}
}
}
/*********
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 AT89C 1602 DS1302 DS18B20 电子 时钟 按键 调整
![提示](https://static.bdocx.com/images/bang_tan.gif)