基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表
以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计的电子钟
实验目的:1、能够以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计一款电子钟2、熟悉DS1302芯片的工作过程3、熟悉CD1602芯片的工作过程4、可以进行必要的扩展,如用第三DS18B20新品进行温度采集和显示5、熟悉掌握51的c程序的编写6、掌握用Proteus进行系统设计仿真验证实验仪器、仪表目录1、DS1302实时时钟芯片1片2、LCD1602液晶显示屏1个,3、80C52芯片1片5、DS18B20芯片一片6、晶振、电容、电阻、开关各若干等7、proteus仿真软件8、Keil C51、PC机实验设计任务以DS1302实时时钟芯片和液晶显示屏LCD1602为基础设计一个电子钟,要求:时间和日期可调整,按键采用3个按键;至少在Proteus上调试通过。
扩展:闹钟和重要日期提醒功能(增加蜂鸣器),闹铃音乐功能实验步骤1、打开Keil软件,新建一个工程文件,选择好芯片,并记得在“Options for Target 1”的Output 选项中,将Create HEX Fil选项勾起来。
2、将编写的程序保存成“.C”的形式3、编译保存好的C文件,并根据提示修改程序中的错误,直到编译成功为止4、打开proteus软件,画出实验电路图5、在89C52中,载入原来已生成的HEX文档6、按下运行键,对Proteus进行软件仿真,观察运行结果原理、结果及分析一、设计方案原理与设计特点分析电子钟总的设计模块:各个模块电路原理分析:1、DS1302时钟采集模块:1.1电路原理图:1.2 DS1302分析:首先DS1302是DALLAS公司推出的涓流充电时钟芯片。
内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作。
DS1302芯片广脚介绍:X1、X2为32.768KHz晶振管脚。
GND 为地。
基于单片机和DS1302的电子万年历设计报告
基于单片机和DS1302的电子万年历设计报告一、设计意义随着科技的不断进步和发展,单片机的使用已经渗透到我们日常生活当中的各个领域,几乎很难找到有哪个领域没有使用单片机的踪迹。
导弹的导航装置,飞机上各种仪表的控制,计算机的网络通讯与数据传输,工业自动化过程的实时控制和数据处理,广泛使用的各种智能IC卡,以及程控玩具、电子宠物等等,这些都离不开单片机,更不用说自动控制领域的机器人、智能仪表、医疗器械了。
本文设计的电子万年历属于小型智能家用电子产品。
利用单片机进行控制,实时时钟芯片进行记时,外加掉电存储电路和显示电路,可实现时间的调整和显示。
电子万年历既可广泛应用于家庭,也可应用于银行、邮电、宾馆、饭店、企业、商店等相关行业的大厅,以及单位会议室、门卫等场所。
因而,此设计具有相当重要的现实意义和实用价值。
二、设计方案本设计以AT89S52单片机为核心,构成单片机控制电路,结合DS1302时钟芯片和24C02 FLASH存储器,显示阳历的年、月、日、星期、时、分、秒和阴历的年、月、日,在显示阴历时间时,能标明是否闰月,同时完成对它们的自动调整和掉电保护,全部信息用液晶显示出来。
输入接口由三个按键来实现,用这三个按键可以对日期和时间进行调整,并可以对闹铃的开关和闹铃的时间进行设置。
闹铃功能通过蜂鸣器来实现。
软件控制程序实现所有的功能。
整机电路使用+5V稳压电源,可稳定工作。
系统框图如图2-1所示,其软硬件设计简单,时间记录准确,可广泛应用于长时间连续显示的系统中。
三、硬件电路设计按照系统设计功能的要求,初步确定设计系统由主控模块、时钟模块、存储模块、键盘接口模块、显示模块和闹铃模块共6个模块组成,电路系统构成框图如图3-1所示。
主控芯片使用52系列AT89S52单片机,时钟芯片使用美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟芯片DS1302,存储模块采用美国ATMEL公司生产的低功耗CMOS串行EEPROM存储芯片AT24C02。
基于51单片机DS1302LCD1602数字时钟显示
#include <intrins.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]="I LIKE MCU!";
sbit RS=P2^0;
dispaly_string(0x00,lcd_buffer1);
dispaly_string(0x40,lcd_buffer2);
}
}
delay(5);
}
void write_a_byte_tods1302(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
IO=x&0x01;
sclk=1;
sclk=0;
x=x>>1;
}
}
uchar get_a_byte_fromds1302()
{
uchar i,b=0x00;
for(i=0;i<8;i++)
uchar lcd_buffer2[]={"TIME 00:00:00 "};
uchar datetime[7];
void delay(uchar ms)
{
uchar i;
while(ms--)
for(i=0;i<120;i++);
}
//忙检测
uchar busy()
{
uchar test;
RW=1;
{
简析基于DS1302和LCD1602的万年历系统设计论文
简析基于DS1302和LCD1602的万年历系统设计论文简析基于DS1302和LCD1602的万年历系统设计论文0引言在日常生活中,无论哪一行业,哪一领域,时间授时都是不可或缺的。
从古老的钟表到现代的电子设备都提供时间授时的功能。
因此,对于单片机学习者来说,设计并实现一款低成本的,有操作性的,提供年,月,日,小时,分,秒,星期等基本计时功能的万年历系统,显得特别实用,特别有意义。
1总体设计及原理图万年历的基本功能一是要提供年月日等基本时间项的授时;二是可以修改时间项。
基于以上两个功能,我们万年历总体设计方案。
万年历有时钟计时模块,显示模块,调整时钟模块和控制器4部分组成。
接下来的任务就是对以上模块进行选型。
低成本,可操作是选型的标准。
对于控制器,选择最常用的C51系列单片机STC89C52。
STC89C52是由宏品科技生产的是一种低功耗8位基于经典C51内核的微处理器,具有8 KhyteFLASH存储器,512 byte RAM , 4 KByte EEPROM , 32位通用IO接口,可以直接用串口下载程序。
时钟模块选择由dallas公司生产的时钟芯片DS1302,DS1302是一款支持年月日,小时分秒,星期,闰年补偿的实时时钟芯片;其简单三线结构可以很方便地与单片机通用IO相连,进行串行总线读写传输。
显示模块选择16x2的字符点阵模块LCD 16020LC D 1602的控制器以Hitachi公司生产的HD44780芯片最为常见。
LC D 1602引脚主要包括3类,第1类是电源。
第2类是8位数据I/0通道,用于读写LC D 1602。
第3类是3根控制线,RS,R/W和E,其中,RS和R/W是用于实现LCD不同操作的。
E是作为读写的启动信号,有点类似一个时钟信号,数据要写人LC D 1602或从LCD 1602读出数据均需要首先置E信号为高至少1 s,然后置低。
调整时钟模块设计了4个轻触开关,用于设定和修改时间项。
基于51单片机与DS1302时钟芯片和LCD1602液晶显示的数字时钟
unsigned char DS1302OutputByte(void) {
unsigned char i; for(i=8; i>0; i--) {
ACC = ACC >>1; ACC7 = DS1302_IO; DS1302_CLK = 1; DS1302_CLK = 0; } return(ACC); }
P3.0/RXD P3.1/TXD P3.2/INT0 P3.3/INT1
P3.4/T0 P3.5/T1 P3.6/WR P3.7/RD
D1 LC
SD E
S V
VD
E V
S R
RW E
0 1 2 3 4 5 67 D D D D D D DD
D N +5V G 39 38
37
36 35
34
33 32
GotoXY(0,0); Print(" tian ma dian zi"); GotoXY(0,1); Print("Time: ");
Word 文档
.
while(1) {
DS1302_GetTime(&CurrentTime); TimeToStr(&CurrentTime); GotoXY(6,1); Print(CurrentTime.TimeString);
unsigned char i; ACC = d; for(i=8; i>0; i--) {
DS1302_IO = ACC0; DS1302_CLK = 1;
// 实时时钟写入一字节 (部函数 ) // 相当于汇编中的 RRC
Word 文档
.
DS1302_CLK = 0; ACC = ACC >> 1; } }
基于51单片机DS1302LCD1602数字时钟显示
dispaly_string(0x40,lcd_buffer2);
}
}
sbit RW=P2^1;
sbit EN=P2^2;
sbit IO=P1^0;
sbit sclk=P1^1;
sbit rst=P1^2;
uchar *week[]={"SUN","****","MON","TUS","WEN","THU","FRI","SAT"};
uchar lcd_buffer1[]={"DATE 00-00-00 "};
delay(5);
}
void write_a_byte_tods1302(uchar x)
{
uchar i;
for(i=0;i<8;i++)
{
IO=x&0x01;
sclk=1;
sclk=0;
x=x>>1;
}
}
uchar get_a_byte_fromds1302()
{
uchar i,b=0x00;
for(i=0;i<8;i++)
a[1]=d%10+'0';
}
void main()
{
init();
while(1)
{
gettime();
zhuanhuan(datetime[6],lcd_buffer1+5);
zhuanhuan(datetime[4],lcd_buffer1+8);
基于ds1302的51单片机简易实时时钟-1602显示-源程序
==================主程序================= #include <reg51.h>。
#include "ds1302.h"#include "LCD1602.h"void change();uchar times[9];uchar date[9];main(){LCD_init();//LCD初始化init_1302(time_1302);gotoxy(1,1);LCD_display("Time:");gotoxy(1,2);LCD_display("Date:");times[8]='\0';//date[8]='\0';while(1){get_1302(time_1302);change();gotoxy(7,1);LCD_display(times);gotoxy(7,2);LCD_display(date);}}/*=========================== 转换子程序===========================*/void change(){// 时间的转换times[0]=time_1302[2]/10+'0';times[1]=time_1302[2]%10+'0';times[2]=':';times[3]=time_1302[1]/10+'0';times[4]=time_1302[1]%10+'0';times[5]=':';times[6]=time_1302[0]/10+'0';times[7]=time_1302[0]%10+'0';// 日期的转换date[0]=time_1302[6]/10+'0';date[1]=time_1302[6]%10+'0';date[2]='-';date[3]=time_1302[4]/10+'0';date[4]=time_1302[4]%10+'0';date[5]='-';date[6]=time_1302[3]/10+'0';date[7]=time_1302[3]%10+'0';}======================================================DS1302驱动程序=============#define uchar unsigned charuchar time_1302[7]={0x00,0x00,0x00,0x03,0x07,0x03,0x08};//设置时间初始值数组// 秒分时号月份星期年sbit T_IO=P1^0; //与硬件相关的连线clk为DS1302的时钟信号线sbit T_CLK=P1^1; //DAT为DS1302的I/O数据线sbit T_RST=P1^2; //RST为DS1302的RST信号线uchar bdata datbyte;sbit datbyte0=datbyte^0;sbit datbyte7=datbyte^7;void get_1302(uchar time[]);void write_ds1302(uchar dat);uchar r_1302(uchar add);void w_1302(uchar add,uchar dat);uchar read_ds1302(void);void init_1302(uchar *time);/*==========================================D S 1 3 0 2 初始化===========================================*/void init_1302(uchar *time){uchar i, add;//uchar time_bcd[7];add=0x80;//0写入,1读出w_1302(0x8e,0x00);for(i=0;i<7;i++){w_1302(add,*time);add+=2;time++;}w_1302(0x8e,0x80);}//===========================// 读取当前时间//===========================void get_1302(uchar time[]){uchar i;uchar add=0x81;w_1302(0x8e,0x00);for(i=0;i<7;i++){time[i]=r_1302(add);add+=2;}w_1302(0x8e,0x80);}/*================================= DS1302写入一个字节(上升沿有效)=================================*/void write_ds1302(uchar dat){uchar i;datbyte=dat;for(i=0;i<8;i++){T_IO=datbyte0;T_CLK=1;T_CLK=0;datbyte=datbyte>>1;}}/*======================================= DS1302读取一个字节(下降沿有效)=======================================*/uchar read_ds1302(void){uchar i;for(i=0;i<8;i++){datbyte=datbyte>>1;datbyte7=T_IO;T_CLK=1;T_CLK=0;}return(datbyte);}/*========================================= 指定位置读取数据=========================================*/uchar r_1302(uchar add){uchar temp,dat1,dat2;T_RST=0;T_CLK=0;T_RST=1;write_ds1302(add);temp=read_ds1302();T_CLK=1;T_RST=0;dat1=temp/16;dat2=temp%16;temp=dat1*10+dat2;return(temp);}/*========================================== 指定位置写入数据==========================================*/void w_1302(uchar add,uchar dat){T_RST=0;T_CLK=0;T_RST=1;write_ds1302(add);write_ds1302(dat/10<<4|dat%10);T_CLK=1;T_RST=0;}=========================================== =============LCD1602驱动程序================#define LCD_DB P0//定义LCD的数据端口sbit LCD_RS=P2^0;sbit LCD_RW=P2^1;sbit LCD_E=P2^2;#define uchar unsigned char#define uint unsigned int//===========延时子函数======================== void delay_lcd(uint x){uint i,j;for(i=x;i>0;i--)for(j=0;j<2;j++);}//==================写指令函数================= void LCD_write_command(uchar command){LCD_DB=command;LCD_RS=0;//指令LCD_RW=0;//写入LCD_E=1;LCD_E=0;delay_lcd(1);//等待执行完毕。
用DS1302与LCD1602设计可调数字万年历课程设计
数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:年月日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表电子设计大赛培训第二时期第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG** 学号:******成员姓名:*** 学号:*******一、要紧功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,同时实时更新显示;2、通过按键随时调剂各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时刻显现乱码的情形下,具有一键初始化时刻的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,因此遇到的问题也比较的多,专门是往常没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了许多的困难,在同学的关心才逐一克服了难题,学习到了许多的专业知识。
在整个设计过程之前,我差不多在网上找了相关方面的资料,万事开始难,一开始不明白从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块能够在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的生活里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触确实是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52 一块LCD 一个排阻 3个DS1302 一个DS18B20 一个开关 5个晶振 2个瓷片电容 2个, 30PF电解电容一个, 33Uf插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;charhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbit Down = P2^2; //减法按钮sbit out = P2^3; //赶忙跳出调整模式按钮sbit DQ = P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; //温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///PortDefinitions********************************************************* *sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数******************************************************************** ******unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_();LcdEn=0;return DBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}//设置输入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[11];unsigned char TimeString[9];}SYSTEMTIME; //定义的时刻类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时刻#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的 RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的 RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time) //猎取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时刻年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //那个地点的if,else语句差不多上判定位闪耀,<2显示数据,>2就不显示,输出字符串为 2007/07/22{Time->DateString[0] = '2';Time->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{Time->DateString[0] = ' ';Time->DateString[1] = ' ';Time->DateString[2] = ' ';Time->DateString[3] = ' ';}Time->DateString[4] = '/';if(hide_month<2){Time->DateString[5] = Time->Month/10 + '0';Time->DateString[6] = Time->Month%10 + '0';}else{Time->DateString[5] = ' ';Time->DateString[6] = ' ';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10 + '0';Time->DateString[9] = Time->Day%10 + '0';}else{Time->DateString[8] = ' ';Time->DateString[9] = ' ';}if(hide_week<2){week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示}else{week_value[0] = ' ';}week_value[1] = '\0';Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判定终止字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';}else{Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2){Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';}else{Time->TimeString[3] = ' ';Time->TimeString[4] = ' ';}Time->TimeString[5] = ':';if(hide_sec<2){Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //判定时钟芯片是否关闭{Write1302(0x8e,0x00); //写入承诺Write1302(0x8c,0x07); //以下写入初始化时刻日期:07/07/25.星期: 3. 时刻: 23:59:55Write1302(0x88,0x07);Write1302(0x86,0x25);Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);Write1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********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); //精确延时大于 480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后假如x=0则初始化成功 x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for (i=8; i>0; i--){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 importantInit_DS18B20();WriteOneChar(0xCC); //跃过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个确实是温度delay_18B20(100);a=ReadOneChar(); //读取温度值低位b=ReadOneChar(); //读取温度值高位temp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned int count){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<62;i++) //1ms延时.{;}}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_mon th=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入承诺Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;while(out==0);while(wireless_1==1);}}//////////////////////////////////////////////////////////////////// ////////////////////////////////////////void Upkey()//升序按键{Up=1;if(Up==0||wireless_2==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_flag=1;if(temp>0x85)temp=0;break;default:break;}while(Up==0);while(wireless_2==1);}}//////////////////////////////////////////////////////////////////// ////////////////////////////////////////void Downkey()//降序按键{Down=1;if(Down==0||wireless_3==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_flag=1;if(temp==-1)temp=0x85;break;default:break;}while(Down==0);while(wireless_3==1);}}void Setkey()//模式选择按键{Set=1;if(Set==0||wireless_4==1){mdelay(8);count=count+1; //Setkey按一次,count就加1done=1; //进入调整模式while(Set==0);while(wireless_4==1);}}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入承诺temp=Read1302(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); //扫描模式切换按键 switch(count){case 1:do //count=1,调整秒{outkey(); //扫描跳出按钮Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入承诺Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据}while(count==2);break;case 2:do //count=2,调整分{hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp=0;if(up_flag==1||down_flag==1)Write1302(0x8e,0x00); //写入承诺Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入承诺Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break;}}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime); //猎取时钟芯片的时刻数据TimeToStr(&CurrentTime); //时刻数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时刻GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; //进入默认液晶显示wireless_1=0;wireless_2=0;wireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0){show_time(); //液晶显示数据 flag=0;Setkey(); //扫描各功能键}}}。
基于单片机DS1302的时钟万年历
{
uint i;
uchar j;
bit testb;
for(j=1;j<=8;j++)
sbit key3=P1A5;//功能键定义
sbit key4=P1A6;//增大键定义
sbit key5=P1A7;//减小键定义
uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week;
uchar s1num=0,s1num2=0,temp;
bit flag;
{
write_1302 (0x8e,0x00);//write_1302 (0x80,0x56);
write_1302 (0x82,0x58);//write_1302 (0x84,0x23);//
write_1302 (0x86,0x30);//
write_1302 (0x88,0x09);//
write_1302 (0x8c,0x10);//write_1302 (0x8a,0x01);//write_1302 (0x8e,0x80);
{
lcdrs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
写命令
delay(5);
lcden=0;
void write_data(uchar date)//1602写数据
{
lcdrs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;}
SCLK= 0;}CE=0;
dat1=ACC;
dat2=dat1/16;//
DS1302实时时钟模块,1602显示
/*******************说明:**************************将实时时钟数据通过LCD1602显示--------------------------------------------------基于51单片机**************************************************/#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intuchar dis_time_buf[16]={0};//LCD1602引脚定义//采用8位并行方式,DB0~DB7连接至LCDDATA0~LCDDATA7 sbit RS=P2^0;sbit RW=P2^1;sbit CS=P2^2;#define LCDDATA P0//DS1302引脚定义sbit RST=P1^3;sbit IO=P1^2;sbit SCK=P1^1;//DS1302地址定义#define ds1302_sec_add 0x80 //秒数据地址#define ds1302_min_add 0x82 //分数据地址#define ds1302_hr_add 0x84 //时数据地址#define ds1302_date_add 0x86 //日数据地址#define ds1302_month_add 0x88 //月数据地址#define ds1302_day_add 0x8a //星期数据地址#define ds1302_year_add 0x8c //年数据地址#define ds1302_control_add 0x8e //控制数据地址#define ds1302_charger_add 0x90#define ds1302_clkburst_add 0xbe//初始时间定义uchar time_buf[8] = {0x20,0x10,0x06,0x01,0x23,0x59,0x55,0x02};//初始时间2010年6月1号23点59分55秒星期二//功能:延时1毫秒//入口参数:x//出口参数:无//说明:当晶振为12M时,j<112;当晶振为11.0592M时,j<122void Delay_xms(uint x){uint i,j;for(i=0;i<x;i++)for(j=0;j<112;j++);}//功能:12us延时//STC89C52为1T单片机,即1个时钟/机器周期,速度为AT89C52的12倍void Delay_xus(uint t){for(;t>0;t--){_nop_();}}//控制LCD写时序void LCD_en_write(void){CS=1;Delay_xus(20);CS=0;Delay_xus(20);}//写指令函数void Write_Instruction(uchar command){RS=0;CS=1;LCDDATA=command;LCD_en_write();//写入指令数据}//写数据函数void Write_Data(uchar Wdata){RS=1;RW=0;CS=1;LCDDATA=Wdata;LCD_en_write();//写入数据}//字符显示初始地址设置void LCD_SET_XY(uchar X,uchar Y){uchar address;if(Y==0)address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0xC0 Write_Instruction(address);//写指令,设置显示初始地址}//在第X行Y列开始显示Wdata所对应的单个字符void LCD_write_char(uchar X,uchar Y,uchar Wdata){LCD_SET_XY(X,Y);//写地址Write_Data(Wdata);//写入当前字符并显示}//清屏函数void LCD_clear(void){Write_Instruction(0x01);Delay_xms(5);}//显示屏初始化函数void LCD_init(void){Write_Instruction(0x38); //8bit interface,2line,5*7dots Delay_xms(5);Write_Instruction(0x38);Delay_xms(5);Write_Instruction(0x38);Write_Instruction(0x08); //关显示,不显光标,光标不闪烁Write_Instruction(0x01); //清屏Delay_xms(5);Write_Instruction(0x04); //写一字符,整屏显示不移动//Write_Instruction(0x05); //写一字符,整屏右移//Write_Instruction(0x06); //写一字符,整屏显示不移动//Write_Instruction(0x07); //写一字符,整屏左移Delay_xms(5);//Write_Instruction(0x0B); //关闭显示(不显示字符,只有背光亮)Write_Instruction(0x0C); //开显示,光标、闪烁都关闭//Write_Instruction(0x0D); //开显示,不显示光标,但光标闪烁//Write_Instruction(0x0E); //开显示,显示光标,但光标不闪烁//Write_Instruction(0x0F); //开显示,光标、闪烁均显示}//DS1302初始化函数void ds1302_init(void){RST=0; //RST脚置低SCK=0; //SCK脚置低}//向DS1302写入一字节数据void ds1302_write_byte(uchar addr, uchar d){uchar i;RST=1; //启动DS1302总线//写入目标地址:addraddr = addr & 0xFE; //最低位置零,寄存器0位为0时写,为1时读for (i = 0; i < 8; i ++) {if (addr & 0x01) {IO=1;}else {IO=0;}SCK=1; //产生时钟SCK=0;addr = addr >> 1;}//写入数据:dfor (i = 0; i < 8; i ++) {if (d & 0x01) {IO=1;}else {IO=0;}SCK=1; //产生时钟SCK=0;d = d >> 1;}RST=0; //停止DS1302总线}//从DS1302读出一字节数据uchar ds1302_read_byte(uchar addr) {uchar i,temp;RST=1; //启动DS1302总线//写入目标地址:addraddr = addr | 0x01; //最低位置高,寄存器0位为0时写,为1时读for (i = 0; i < 8; i ++) {if (addr & 0x01) {IO=1;}else {IO=0;}SCK=1;SCK=0;addr = addr >> 1;}//输出数据:tempfor (i = 0; i < 8; i ++) { temp = temp >> 1;if (IO) {temp |= 0x80;}else {temp &= 0x7F;}SCK=1;SCK=0;}RST=0; //停止DS1302总线return temp;}//向DS302写入时钟数据void ds1302_write_time(void){ds1302_write_byte(ds1302_control_add,0x00); //关闭写保护ds1302_write_byte(ds1302_sec_add,0x80); //暂停时钟//ds1302_write_byte(ds1302_charger_add,0xa9); //涓流充电ds1302_write_byte(ds1302_year_add,time_buf[1]); //年ds1302_write_byte(ds1302_month_add,time_buf[2]); //月ds1302_write_byte(ds1302_date_add,time_buf[3]); //日ds1302_write_byte(ds1302_hr_add,time_buf[4]); //时ds1302_write_byte(ds1302_min_add,time_buf[5]); //分ds1302_write_byte(ds1302_sec_add,time_buf[6]); //秒ds1302_write_byte(ds1302_day_add,time_buf[7]); //周ds1302_write_byte(ds1302_control_add,0x80); //打开写保护}//从DS302读出时钟数据void ds1302_read_time(void){time_buf[1]=ds1302_read_byte(ds1302_year_add); //年time_buf[2]=ds1302_read_byte(ds1302_month_add); //月time_buf[3]=ds1302_read_byte(ds1302_date_add); //日time_buf[4]=ds1302_read_byte(ds1302_hr_add); //时time_buf[5]=ds1302_read_byte(ds1302_min_add); //分time_buf[6]=(ds1302_read_byte(ds1302_sec_add))&0x7f;//秒,屏蔽秒的第7位,避免超出59time_buf[7]=ds1302_read_byte(ds1302_day_add); //周}void Display(void){LCD_write_char(3,0,dis_time_buf[0]+'0');LCD_write_char(4,0,dis_time_buf[1]+'0');LCD_write_char(5,0,dis_time_buf[2]+'0');LCD_write_char(6,0,dis_time_buf[3]+'0');LCD_write_char(7,0,'/');LCD_write_char(9,0,dis_time_buf[5]+'0'); LCD_write_char(10,0,'/');LCD_write_char(11,0,dis_time_buf[6]+'0');LCD_write_char(12,0,dis_time_buf[7]+'0');LCD_write_char(15,0,dis_time_buf[14]+'0'); //第2行显示LCD_write_char(3,1,dis_time_buf[8]+'0'); LCD_write_char(4,1,dis_time_buf[9]+'0'); LCD_write_char(5,1,':');LCD_write_char(7,1,dis_time_buf[11]+'0');LCD_write_char(8,1,':');LCD_write_char(9,1,dis_time_buf[12]+'0');LCD_write_char(10,1,dis_time_buf[13]+'0');}//定时器中断函数void Timer2() interrupt 5 //定时器2是5号中断{static uchar t;TF2=0;t++;if(t==4) //间隔200ms(50ms*4)读取一次时间{t=0;ds1302_read_time(); //读取时间dis_time_buf[0]=(time_buf[0]>>4); //年dis_time_buf[1]=(time_buf[0]&0x0f);dis_time_buf[2]=(time_buf[1]>>4);dis_time_buf[3]=(time_buf[1]&0x0f);dis_time_buf[4]=(time_buf[2]>>4); //月dis_time_buf[5]=(time_buf[2]&0x0f);dis_time_buf[6]=(time_buf[3]>>4); //日dis_time_buf[7]=(time_buf[3]&0x0f);dis_time_buf[14]=(time_buf[7]&0x07); //星期//第2行显示dis_time_buf[8]=(time_buf[4]>>4); //时dis_time_buf[9]=(time_buf[4]&0x0f);dis_time_buf[10]=(time_buf[5]>>4); //分dis_time_buf[11]=(time_buf[5]&0x0f);dis_time_buf[12]=(time_buf[6]>>4); //秒dis_time_buf[13]=(time_buf[6]&0x0f);}}//定时器2初始化void Init_timer2(void){RCAP2H=0x3c;//赋T2初始值0x3cb0,溢出20次为1秒,每次溢出时间为50ms RCAP2L=0xb0;TR2=1; //启动定时器2ET2=1; //打开定时器2中断EA=1; //打开总中断}//主函数void main(void)Delay_xms(50);//等待系统稳定LCD_init(); //LCD初始化LCD_clear(); //清屏ds1302_init(); //DS1302初始化Delay_xms(10);ds1302_write_time(); //写入初始值Init_timer2(); //定时器2初始化while(1){Display();}}。
ATmega16、DS1302、LCD1602组成的可设置万年历电子表
ATmega16、DS1302、LCD1602组成的可设置万年历电子表一、简要说明我看了很多人做这个经典的项目,不少人在网上到处求索资料,找人解答疑问。
奈何现在很多的网站,动不动就要你注册,很多的解答也只有只言片语。
我就把这个项目直接做出来,所有的都公布在网上的,希望对新手有所帮助。
这其中有个小知识点,我这边有一段程序可以用年月日信息来计算星期。
具体是怎么样的个原理就不多说了,直接把代码贴在了本文的第三部分,有需要的可以直接拿去。
虽然DS1302带有星期功能,但是本身的星期功能在设置日期的时候不能自动跟随着变化,故不建议使用。
关于DS1302使用的石英晶振,标称频率为32.768kHz,无需任何外接电阻或电容,许多地方说要接外部电容,这是错误的。
DS1302归根结底有以下几种操作:1.初始化操作:DS1302可以通过工作电源(VCC2)对后备电源(VCC1)进行充电,初始化的时候需要指定导通二极管的个数、限流电阻的规格。
一般来说在初始化完成后,就可以直接打开DS1302。
2.读取内存数据:0XC1~0XFD,可以当做掉电保持寄存器使用,每个寄存器间隔1个地址读。
3.写入内存数据:0XC0~0XFC,可以当做掉电保持寄存器使用,每个寄存器间隔1个地址写。
4.设置日期:设置年月日1/ 85.设置时间:设置时分秒6.读取日期:读取年月日7.读取时间:读取时分秒程序思路简要说明,上电对进入初始化阶段、首先是MCU初始化、关闭总中断开关。
再对DS1302作初始化,并启用它。
然后对LM1602作初始化。
随后程序进入主循环。
主循环内有个模式控制函数,分为0~6共计七种模式。
模式0为正常显示模式,1~6分别对应年、月、日、时、分、秒设置模式。
进入对应的设置模式时,相关显示在LCD上出现闪烁。
按下M键可以依次在0~7模式之间循环切换。
本项目中,还设计有分钟脉冲对时操作,在某些场合下,本装置可接收卫星时钟装置发送的分钟脉冲对时信号。
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表
电子设计大赛培训第二阶段第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG**学号:******成员姓名:*** 学号:*******一、主要功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,并且实时更新显示;2、通过按键随时调节各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时间出现乱码的情况下,具有一键初始化时间的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,所以遇到的问题也比较的多,尤其是以前没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了不少的困难,在同学的帮助才逐一克服了难题,学习到了不少的专业知识。
在整个设计过程之前,我已经在网上找了相关方面的资料,万事开始难,一开始不知道从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块可以在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的日子里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触就是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52一块LCD 一个排阻 3个DS1302一个DS18B20一个开关 5个晶振2个瓷片电容2个, 30PF电解电容一个,33Uf插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST=P1^5; //实时时钟复位线引脚sbitwireless_1 = P3^0;sbit wireless_2=P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbitDown = P2^2;//减法按钮sbit out = P2^3; //立刻跳出调整模式按钮sbit DQ =P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value;//温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///Port Definitions**********************************************************sbitLcdRsﻩ= P2^5;sbit LcdRwﻩ= P2^6;sbitLcdEn = P2^7;sfr DBPort = 0x80;ﻩ//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数**************************************************************************unsignedchar LCD_Wait(void){ﻩLcdRs=0;ﻩLcdRw=1;ﻩ_nop_();LcdEn=1; _nop_();ﻩﻩﻩﻩLcdEn=0;ﻩreturnDBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND ﻩﻩ0 // Command#define LCD_DATAﻩ 1 //Data#defineLCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING ﻩ0x02// 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;ﻩLcdRs=style;LcdRw=0; ﻩ_nop_();DBPort=input;ﻩ_nop_();//注意顺序LcdEn=1; ﻩ_nop_();//注意顺序ﻩLcdEn=0; ﻩ_nop_();ﻩLCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW ﻩﻩ0x04 //显示开#defineLCD_HIDEﻩ0x00 //显示关#define LCD_CURSORﻩ0x02 ﻩ//显示光标#define LCD_NO_CURSORﻩﻩ0x00 //无光标#define LCD_FLASH ﻩ0x01//光标闪动#define LCD_NO_FLASH ﻩ0x00 //光标不闪动void LCD_SetDisplay(unsignedchar DisplayMode){ﻩLCD_Write(LCD_COMMAND, 0x08|DisplayMode);ﻩ}//设置输入模式************************************************************#define LCD_AC_UP ﻩ0x02#define LCD_AC_DOWNﻩﻩ0x00 // default#define LCD_MOVEﻩﻩ0x01 // 画面可平移#define LCD_NO_MOVE ﻩ0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){ﻩLCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;ﻩLCD_Write(LCD_COMMAND,0x38);//8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏ﻩLCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x,unsigned char y){ﻩif(y==0)ﻩﻩLCD_Write(LCD_COMMAND,0x80|x);ﻩif(y==1)ﻩLCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0')ﻩ{ﻩLCD_Write(LCD_DATA,*str);ﻩstr++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{ﻩunsigned char Second;ﻩunsigned char Minute;ﻩunsigned char Hour;unsigned char Week;ﻩunsigned char Day;ﻩunsigned char Month;ﻩunsigned char Year;ﻩunsigned char DateString[11];unsigned charTimeString[9];}SYSTEMTIME;//定义的时间类型SYSTEMTIME CurrentTime;#defineAM(X)ﻩX#define PM(X)ﻩ(X+12) // 转成24小时制#define DS1302_SECONDﻩ0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTEﻩ0x82#define DS1302_HOUR ﻩ0x84#define DS1302_WEEKﻩ0x8A0x86#define DS1302_DAYﻩﻩ#define DS1302_MONTH 0x88#define DS1302_YEARﻩ 0x8Cvoid DS1302InputByte(unsigned char d) ﻩ//实时时钟写入一字节(内部函数){unsigned char i;ACC = d;for(i=8; i>0;i--){DS1302_IO = ACC0; ﻩ//相当于汇编中的RRC DS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsignedchar DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8;i>0; i--){ACC = ACC>>1; ﻩﻩ//相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa)//ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); ﻩ// 地址,命令DS1302InputByte(ucDa); ﻩ//写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsignedchar Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsignedchar ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST =0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time)//获取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ﻩReadValue = Read1302(DS1302_SECOND);ﻩTime->Second = ((ReadValue&0x70)>>4)*10+ (ReadVal ue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10+ (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour= ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day =((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue &0x0F);ReadValue = Read1302(DS1302_MONTH);ﻩTime->Month = ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);ﻩReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 +(ReadValu e&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22 {ﻩ Time->DateString[0]= '2';ﻩTime->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{ﻩ Time->DateString[0] = ' ';Time->DateString[1] = ' ';ﻩﻩﻩ Time->DateString[2] = ' ';ﻩTime->DateString[3] = ' ';ﻩ}ﻩTime->DateString[4]= '/';ﻩif(hide_month<2)ﻩ{ﻩ Time->DateString[5] =Time->Month/10+ '0';Time->DateString[6] =Time->Month%10 + '0';ﻩ}else{ﻩ Time->DateString[5] = ' ';Time->DateString[6] = '';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10+'0';Time->DateString[9] =Time->Day%10 +'0';}ﻩelse{ﻩTime->DateString[8]= ' ';ﻩTime->DateString[9]= ' ';}if(hide_week<2)ﻩ{week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示ﻩ}ﻩelseﻩ {week_value[0] = ' ';ﻩ}week_value[1] = '\0';ﻩTime->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){ﻩ Time->TimeString[0] = Time->Hour/10 + '0';ﻩ Time->TimeString[1]= Time->Hour%10 + '0';ﻩ}else{ﻩ Time->TimeString[0] = ' ';ﻩ Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2)ﻩ{Time->TimeString[3]= Time->Minute/10 + '0';Time->TimeString[4] =Time->Minute%10 + '0';}ﻩ elseﻩ{Time->TimeString[3] = ' ';ﻩTime->TimeString[4] =' ';ﻩ }ﻩTime->TimeString[5] = ':';if(hide_sec<2){ﻩTime->TimeString[6] = Time->Second/10 + '0';ﻩ Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';ﻩTime->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);ﻩif(Second&0x80)//判断时钟芯片是否关闭{ﻩWrite1302(0x8e,0x00); //写入允许Write1302(0x8c,0x07);//以下写入初始化时间日期:07/07/25.星期: 3. 时间: 23:59:55ﻩWrite1302(0x88,0x07);ﻩWrite1302(0x86,0x25);Write1302(0x8a,0x07);ﻩWrite1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);ﻩWrite1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsignedint i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){ﻩ unsigned char x=0;DQ=1;//DQ复位ﻩdelay_18B20(8); //稍做延时ﻩDQ = 0; //单片机将DQ拉低ﻩ delay_18B20(80); //精确延时大于 480usDQ = 1; //拉高总线delay_18B20(14);ﻩ x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;ﻩuchardat = 0;for (i=8;i>0;i--){DQ = 0;// 给脉冲信号dat>>=1;ﻩDQ=1; //给脉冲信号ﻩ if(DQ)ﻩ dat|=0x80;ﻩ delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for(i=8; i>0; i--){ﻩDQ = 0;ﻩDQ= dat&0x01;ﻩdelay_18B20(5);ﻩﻩDQ = 1;ﻩdat>>=1;}}/**************读取ds18b20当前温度************/void ReadTemp(void){unsigned char a=0;ﻩunsignedchar b=0;ﻩunsigned char t=0;ﻩInit_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); ﻩ//启动温度转换ﻩdelay_18B20(100); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); ﻩ//跳过读序号列号的操作ﻩWriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度ﻩdelay_18B20(100);a=ReadOneChar();//读取温度值低位ﻩb=ReadOneChar();ﻩﻩ//读取温度值高位ﻩtemp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned intcount){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ﻩuint i;for(;delay>0;delay--)ﻩﻩ{for(i=0;i<62;i++) //1ms延时.ﻩ{;}ﻩ}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);ﻩcount=0;ﻩhide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;ﻩwhile(out==0);while(wireless_1==1);}}//////////////////////////////////////////////////////////////////////////////////////////////////////////// void Upkey()//升序按键{ﻩUp=1;if(Up==0||wireless_2==1)ﻩﻩ {ﻩﻩﻩ mdelay(8);ﻩ switch(count)ﻩﻩﻩ{case1:temp=Read1302(DS1302_SECOND); //读取秒数ﻩﻩﻩﻩﻩﻩtemp=temp+1; //秒数加1up_flag=1;//数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0; ﻩﻩﻩﻩﻩﻩ break;ﻩﻩ case 2:temp=Read1302(DS1302_MINUTE); //读取分数ﻩﻩﻩﻩﻩ temp=temp+1;//分数加1up_flag=1;ﻩﻩﻩﻩ if(temp>0x59) //超过59分,清零ﻩﻩtemp=0;ﻩﻩﻩbreak;ﻩﻩﻩcase 3:temp=Read1302(DS1302_HOUR); //读取小时数ﻩﻩﻩ temp=temp+1; //小时数加1up_flag=1;ﻩﻩﻩﻩﻩﻩif(temp>0x23) //超过23小时,清零ﻩﻩﻩﻩﻩﻩtemp=0;ﻩﻩﻩﻩbreak;ﻩﻩﻩﻩcase 4:temp=Read1302(DS1302_WEEK); //读取星期数ﻩﻩﻩﻩ temp=temp+1; //星期数加1up_flag=1;ﻩﻩﻩ if(temp>0x7)ﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩﻩﻩ break;ﻩcase 5:temp=Read1302(DS1302_DAY); //读取日数ﻩﻩﻩ temp=temp+1; //日数加1up_flag=1;ﻩﻩﻩﻩ if(temp>0x31)ﻩﻩﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩ break;ﻩﻩcase 6:temp=Read1302(DS1302_MONTH); //读取月数ﻩﻩﻩﻩtemp=temp+1; //月数加1up_flag=1;ﻩﻩﻩﻩﻩﻩﻩif(temp>0x12)ﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩ break;ﻩcase 7:temp=Read1302(DS1302_YEAR);//读取年数ﻩﻩﻩﻩﻩﻩﻩ temp=temp+1; //年数加1up_flag=1;ﻩﻩﻩﻩif(temp>0x85)ﻩﻩﻩﻩﻩ temp=0;ﻩﻩ break;ﻩﻩﻩﻩdefault:break;ﻩ }ﻩﻩﻩ while(Up==0);ﻩ while(wireless_2==1);}}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Downkey()//降序按键{ﻩﻩﻩDown=1;if(Down==0||wireless_3==1)ﻩ {ﻩﻩﻩmdelay(8);ﻩﻩ switch(count)ﻩﻩ {case 1:temp=Read1302(DS1302_SECOND); //读取秒数ﻩﻩﻩﻩﻩtemp=temp-1;ﻩ//秒数减1down_flag=1; //数据调整后更新标志ﻩﻩﻩﻩ if(temp==0x7f) //小于0秒,返回59秒ﻩﻩtemp=0x59;ﻩﻩbreak;ﻩﻩﻩ case2:temp=Read1302(DS1302_MINUTE); //读取分数ﻩﻩﻩtemp=temp-1; //分数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩﻩﻩﻩﻩﻩ temp=0x59; //小于0秒,返回59秒ﻩﻩﻩﻩﻩ break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数ﻩﻩﻩtemp=temp-1; //小时数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩtemp=0x23;ﻩﻩ break;ﻩ case 4:temp=Read1302(DS1302_WEEK);//读取星期数ﻩﻩﻩﻩ temp=temp-1; //星期数减1down_flag=1;ﻩﻩﻩﻩ if(temp==0)ﻩﻩﻩﻩﻩ temp=0x7;;ﻩﻩﻩ break;ﻩ case 5:temp=Read1302(DS1302_DAY); //读取日数ﻩﻩﻩﻩﻩ temp=temp-1; //日数减1down_flag=1;ﻩﻩﻩﻩ if(temp==0)ﻩﻩﻩtemp=31;ﻩﻩ break;ﻩﻩﻩ case 6:temp=Read1302(DS1302_MONTH); //读取月数ﻩﻩﻩﻩﻩﻩ temp=temp-1; //月数减1down_flag=1;ﻩif(temp==0)ﻩﻩﻩﻩﻩ temp=12;ﻩﻩﻩﻩﻩﻩ break;ﻩﻩcase 7:temp=Read1302(DS1302_YEAR);//读取年数ﻩﻩﻩﻩ temp=temp-1; //年数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩﻩﻩtemp=0x85;ﻩﻩﻩﻩﻩﻩﻩ break;ﻩﻩ default:break;ﻩ}ﻩﻩﻩﻩwhile(Down==0);ﻩﻩwhile(wireless_3==1);ﻩ}}void Setkey()//模式选择按键{ﻩSet=1;ﻩif(Set==0||wireless_4==1)ﻩ{mdelay(8);count=count+1; //Setkey按一次,count就加1 done=1; ﻩﻩ//进入调整模式while(Set==0);while(wireless_4==1);ﻩ }}void keydone()//按键功能执行{ uchar Second;ﻩ if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp=Read1302(0x80);Write1302(0x80,temp|0x80);ﻩWrite1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); ﻩ//扫描模式切换按键ﻩswitch(count)ﻩﻩ {case 1:do ﻩ //count=1,调整秒{outkey();ﻩﻩ //扫描跳出按钮ﻩﻩﻩUpkey(); //扫描加按钮ﻩﻩ Downkey(); //扫描减按钮ﻩﻩﻩﻩif(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{ﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩﻩWrite1302(0x80,temp|0x80); //写入新的秒数ﻩﻩﻩWrite1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩﻩﻩﻩ down_flag=0;ﻩﻩ}ﻩhide_sec++; //位闪计数ﻩﻩif(hide_sec>3)ﻩﻩ hide_sec=0;show_time(); //液晶显示数据ﻩﻩﻩﻩ}while(count==2);break;ﻩ case 2:doﻩﻩ//count=2,调整分ﻩ {ﻩﻩhide_sec=0;ﻩ outkey();ﻩﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩ if(temp>0x60)ﻩﻩ temp=0;ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩWrite1302(0x8e,0x00); //写入允许ﻩﻩﻩ Write1302(0x82,temp); //写入新的分数ﻩWrite1302(0x8e,0x80);//禁止写入ﻩ up_flag=0;ﻩ down_flag=0;ﻩﻩﻩ }ﻩﻩ hide_min++;ﻩﻩ if(hide_min>3)ﻩﻩﻩhide_min=0;show_time();ﻩﻩ }while(count==3);break;ﻩ case 3:doﻩﻩﻩﻩ//count=3,调整小时ﻩﻩ{hide_min=0;ﻩoutkey();ﻩUpkey();ﻩ Downkey();ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩ Write1302(0x84,temp); //写入新的小时数ﻩﻩ Write1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩ down_flag=0;ﻩ}hide_hour++;ﻩﻩif(hide_hour>3)hide_hour=0;show_time();ﻩﻩ }while(count==4);break;case 4:doﻩﻩﻩﻩ //count=4,调整星期ﻩ {hide_hour=0;outkey();Upkey();ﻩﻩDownkey();ﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩﻩﻩ Write1302(0x8a,temp); //写入新的星期数ﻩﻩWrite1302(0x8e,0x80); //禁止写入ﻩﻩ up_flag=0;ﻩﻩ down_flag=0;ﻩﻩ}ﻩhide_week++;ﻩﻩ if(hide_week>3)ﻩﻩﻩ hide_week=0;show_time();ﻩﻩﻩ }while(count==5);break;ﻩ case 5:doﻩﻩﻩﻩﻩ//count=5,调整日ﻩ {ﻩﻩﻩﻩ hide_week=0;ﻩoutkey();ﻩﻩﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩ Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数ﻩﻩﻩ Write1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩ down_flag=0;ﻩ}ﻩﻩﻩ hide_day++;ﻩﻩﻩif(hide_day>3)ﻩ hide_day=0;show_time();ﻩﻩ }while(count==6);break;ﻩﻩcase 6:doﻩﻩﻩﻩﻩ//count=6,调整月{hide_day=0;ﻩﻩﻩﻩ outkey();ﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩ Write1302(0x88,temp); //写入新的月数ﻩ Write1302(0x8e,0x80); //禁止写入ﻩup_flag=0;ﻩﻩﻩ down_flag=0;ﻩﻩ}ﻩﻩ hide_month++;ﻩﻩif(hide_month>3)ﻩﻩﻩ hide_month=0;show_time();ﻩ }while(count==7);break;ﻩﻩ case 7:doﻩ//count=7,调整年{hide_month=0;ﻩﻩﻩ outkey();ﻩﻩUpkey();ﻩﻩDownkey();ﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩWrite1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入ﻩﻩ up_flag=0;ﻩﻩdown_flag=0;ﻩﻩﻩﻩ }ﻩﻩﻩhide_year++;ﻩif(hide_year>3)ﻩﻩﻩ hide_year=0;show_time();ﻩﻩ}while(count==8);break;ﻩ case 8: count=0;hide_year=0; //count8,跳出调整模式,返回默认显示状态ﻩSecond=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许ﻩ Write1302(0x80,Second&0x7f);ﻩ Write1302(0x8E,0x80); //禁止写入ﻩﻩﻩ done=0;ﻩﻩ break; //count=7,开启中断,标志位置0并退出ﻩ default:break;ﻩ }}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime);//获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时间GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week");ﻩ//在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;ﻩdone=0; //进入默认液晶显示ﻩwireless_1=0;wireless_2=0;ﻩwireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0)ﻩ{show_time(); //液晶显示数据flag=0;ﻩﻩ Setkey(); ﻩﻩ //扫描各功能键ﻩﻩ}}}。
基于DS1302和LCD1602的万年历,闹钟,时钟,用开发版直接显示的程序 - 副本
实时时钟芯片DS1302应用,DS18B20应用实例——可调时钟,LCD1602显示:(时间+温度)说明:需要按程序中定义的接口。
按自己接口,只要在程序中修改接口定义即可。
1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2:振荡源,外接32.768kHz 晶振。
3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
4)I/O为串行数据输入输出端(双向)。
5)SCLK为时钟输入端。
2、 DS1302的控制字节DS1302 的控制字如下图所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
如何实现DS1302实时时钟表显示在1602LCD液晶
如何实现DS1302实时时钟表显示在1602LCD液晶在1602LCD 液晶里显示实时时间:首先在DS1302 实时时钟芯片里写入一个时间,然后在这个芯片里读取这个时间,并显示在液晶里。
现在终于实现了...#include#include sbit SCLK=P3;sb it SDA=P3;sb it RST = P3 ;//unsigned char code Write_Address[]={0x80,0x82,0x84}; unsigned char code Read_Address[]={0x85,0x83,0x81}; unsigned char Time_Table[3];void Write_Byte(unsigned char Data)//写一个字节: 地址或数据{ unsigned char i;for(i=0; i>1;SCLK=1; } }void Write_RTC(unsigned char Address, unsigned char Data) { RST=0; _nop_(); SCLK=0; _nop_(); RST=1; Write_Byte(Address); Write_Byte(Data); RST=0;}unsigned char Read_Byte() //读一个字节: 数据{ unsigned char Data=0; unsigned char i; for(i=0; i>1; _nop_(); SCLK=1; } return Data;}unsigned char Read_RTC(unsigned char Address) //{ unsigned char Data=0; unsigned char Data1,Data2; RST=0; _nop_(); SCLK=0; _nop_(); RST=1; Write_Byte(Address); Data=Read_Byte(); RST=0; Data1=Data/16; Data2=Data%16; Data=Data2+Data1*10; return Data;}void Init_RTC() //初始化实时时钟表RTC{ Write_RTC(0x8e, 0x00); Write_RTC(0x80, 0x56); Write_RTC(0x82, 0x48); Write_RTC(0x84, 0x12); Write_RTC(0x8e, 0x80) }void DisplayTime() //把时间显示1602 液晶{ unsigned char i; InitLCD(); Write_Command(0x80+0x03); for(i=0; i<3; i++) { Time_Table[i]=Read_RTC(Read_Address[i]);Write_Data(0x30+Time_Table[i]/10); Write_Data(0x30+Time_Table[i]%10);if(i!=2) Write_Data(:); } }void main(){Init_RTC(); DisplayTime(); while(1);}其实,写这个程序,也是比较简单的,比在24C02 芯片里读写容易了。
基于DS1302与LCD1602的电子日历时钟的设计与实现
武汉纺织大学高职学院毕业设计(论文)2014— 2015学年第1 学期题目:基于DS1302与LCD1602的电子日历时钟的设计与实现学生姓名曹强学号 1218092183指导教师王骏评阅教师时间 2014年10月武汉纺织大学高职学院毕业设计(论文)开题报告课题名称(来源、类型):基于DS1302与1602LCD电子日历时钟的设计与实现指导教师:王骏学生姓名:曹强开题报告内容:(调研资料的准备,设计/论文的目的、要求、思路与预期成果;任务完成的阶段内容及时间安排;完成设计(论文)所具备的条件因素等.)1.目的:实现日历和时钟的显示并且能够调整2.要求:完成电子日历和时钟的软件和硬件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,控制程序的编写等。
3.预期成果:仿真成功,做出实物。
(1)显示初始值日历时钟初始值;4.时间安排:第3周:熟悉课题的基本要求,查阅相关资料,初步拟定设计的整体方案,完成开题报告。
第4—5周:自学这次课题所涉及的相关内容,包括器件基础知识、单片机,DS1302时钟芯片工作原理和相关软件的使用以及LCD1602液晶显示屏的相关内容。
并设计一些简单的实际电路,熟练所学内容并加以巩固。
第6—8周:设计DS1302时钟模块的控制电路、LCD1602液晶显示电路、电源电路等硬件电路,并用Proteus仿真第8—10周:焊接调试电路,根据个部分的作用对硬件进行调试,最后联机调试。
第10—12周:写毕业设计论文,作品展示,完成全部毕业设计指导教师签名:日期: 2014年目录摘要 0关键词 0Abstract (1)Key Words (1)第一章设计要求与方案论证 (2)1.1 设计要求: (2)1。
2 系统基本方案选择和论证 (2)1.2。
1 单片机芯片的选择方案和论证 (2)1.2.2 显示模块选择方案和论证 (2)1.2。
3 时钟芯片的选择方案和论证 (2)1。
用DS1302与LCD1602可调数字万年历课程设计
数字开发与实践课程设计题目:用DS1302与LCD1602设计可调式电子日历时钟班级:姓名:学号:学院:二O一二年六月五日用DS1302与LCD1602设计的可调式电子日历时钟一、总体设计1.1、设计目的为巩固所学的单片机知识,把所学理论运用到实践中,用LCD1602与DS1302 设计可调式电子日历时钟。
1.2、设计要求(1)显示:年、月、日、时、分、秒和星期;(2)设置年、月、日、时、分、秒和星期的初始状态;(3)能够用4个按键调整日历时钟的年、月、日、时、分、秒和星期;完成可调式电子日历时钟的硬件和软件的设计,包括单片机的相关内容;日历时钟模块的设计,液晶显示模块的设计,按键模块的设计。
控制程序的编写等。
备注:本程序另外添加了每到上午8:10和下午2:10的闹钟提醒功能。
1.3、系统基本方案选择和论证1.3.1、单片机芯片的选择方案方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容。
方案二:采用STC12C5A60S2系列单片机是宏晶科技生产的单时钟/机器周期(1T)的单片机,是高速/低功耗/超强抗干扰的新一代8051单片机,指令代码完全兼容传统8051,但速度快8-12倍。
内部集成MAX810专用复位电路,2路PWM,8路高速10位A/D转换(250K/S),针对电机控制,强干扰场合。
但造价较高。
1.3.2 、显示模块选择方案和论证:方案一:采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用显示数字显得太浪费,且价格也相对较高。
所以不用此种作为显示。
方案二:采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,显示出来的只是拼音,而不是汉字。
所以也不用此种作为显示。
方案三:采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量字符,且视觉效果较好,外形美观。
基于DS1302和LCD1602的万年历系统设计
基于DS1302和LCD1602的万年历系统设计
任志敏
【期刊名称】《电脑开发与应用》
【年(卷),期】2015(000)003
【摘要】This paper introduces the design of a calendar system that contained C51 single-chip, calendar chip DS1302, display module LCD1602 and touch switches. The system is low cost, universal, and easy to implement. The system scheme, hardware scheme, software are also designed.%以低成本、通用性、可操作性为原则,设计了以C51单片机为控制器,集时钟芯片DS1302,显示屏LCD1602,轻触开关为一体的万年历系统。
在设计
该系统总体方案的基础上,完成了该系统的原理图、软件和实物设计。
【总页数】3页(P28-30)
【作者】任志敏
【作者单位】常州纺织服装职业技术学院机电工程系,江苏常州 213164
【正文语种】中文
【中图分类】N945.23
【相关文献】
1.LCD1602汉字显示技术在万年历中的应用及Proteus仿真 [J], 李建波
2.基于CPLD的LCD1602显示系统设计与实现 [J], 陈海峰;丁丽丽
3.基于STM32的电子万年历系统设计 [J], 刘磊
4.基于时钟芯片DS1302的万年历的设计 [J], 李伟跃
5.万年历芯片DS1302功能测试方法研究 [J], 张春宇
因版权原因,仅展示原文概要,查看原文内容请购买。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
电子设计大赛培训第二阶段第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG** 学号:******成员姓名:*** 学号:*******一、主要功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,并且实时更新显示;2、通过按键随时调节各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时间出现乱码的情况下,具有一键初始化时间的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,所以遇到的问题也比较的多,尤其是以前没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了不少的困难,在同学的帮助才逐一克服了难题,学习到了不少的专业知识。
在整个设计过程之前,我已经在网上找了相关方面的资料,万事开始难,一开始不知道从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块可以在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的日子里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触就是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52 一块LCD 一个排阻 3个DS1302 一个DS18B20 一个开关 5个晶振 2个瓷片电容 2个, 30PF 电解电容一个, 33Uf 插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbit Down = P2^2; //减法按钮sbit out = P2^3; //立刻跳出调整模式按钮sbit DQ = P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; //温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///Port Definitions**********************************************************sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数**************************************************************************unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_();LcdEn=0;return DBPort;}//向LCD写入命令或数据************************************************************ #define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************ #define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}//设置输入模式************************************************************ #define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************ void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/***********DS1302时钟部分子程序******************/ typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[11];unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为2007/07/22{Time->DateString[0] = '2';Time->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{Time->DateString[0] = ' ';Time->DateString[1] = ' ';Time->DateString[2] = ' ';Time->DateString[3] = ' ';}Time->DateString[4] = '/';if(hide_month<2){Time->DateString[5] = Time->Month/10 + '0';Time->DateString[6] = Time->Month%10 + '0';}else{Time->DateString[5] = ' ';Time->DateString[6] = ' ';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10 + '0';Time->DateString[9] = Time->Day%10 + '0';}else{Time->DateString[8] = ' ';Time->DateString[9] = ' ';}if(hide_week<2){week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示}else{week_value[0] = ' ';}week_value[1] = '\0';Time->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组TimeString[];{ if(hide_hour<2){Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';}else{Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2){Time->TimeString[3] = Time->Minute/10 + '0'; Time->TimeString[4] = Time->Minute%10 + '0'; }else{Time->TimeString[3] = ' ';Time->TimeString[4] = ' ';}Time->TimeString[5] = ':';if(hide_sec<2){Time->TimeString[6] = Time->Second/10 + '0'; Time->TimeString[7] = Time->Second%10 + '0'; }else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //判断时钟芯片是否关闭{Write1302(0x8e,0x00); //写入允许Write1302(0x8c,0x07); //以下写入初始化时间日期:07/07/25.星期: 3. 时间: 23:59:55Write1302(0x88,0x07);Write1302(0x86,0x25);Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);Write1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********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); //精确延时大于480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for (i=8; i>0; i--){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 importantInit_DS18B20();WriteOneChar(0xCC); //跳过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个就是温度delay_18B20(100);a=ReadOneChar(); //读取温度值低位b=ReadOneChar(); //读取温度值高位temp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned int count){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<62;i++) //1ms延时.{;}}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_mont h=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;while(out==0);while(wireless_1==1);}}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Upkey()//升序按键{Up=1;if(Up==0||wireless_2==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_flag=1;if(temp>0x85)temp=0;break;default:break;}while(Up==0);while(wireless_2==1);}}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Downkey()//降序按键{Down=1;if(Down==0||wireless_3==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_flag=1;if(temp==-1)temp=0x85;break;default:break;}while(Down==0);while(wireless_3==1);}}void Setkey()//模式选择按键{Set=1;if(Set==0||wireless_4==1){mdelay(8);count=count+1; //Setkey按一次,count就加1done=1; //进入调整模式while(Set==0);while(wireless_4==1);}}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp=Read1302(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); //扫描模式切换按键switch(count){case 1:do //count=1,调整秒{outkey(); //扫描跳出按钮Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入允许Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入down_flag=0;}hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据}while(count==2);break;case 2:do //count=2,调整分{hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp=0;if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入down_flag=0;}hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入允许Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break;}}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime); //获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时间GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母week Delay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; //进入默认液晶显示wireless_1=0;wireless_2=0;wireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0){show_time(); //液晶显示数据flag=0;Setkey(); //扫描各功能键}}}。