基于单片机的电子日历时钟设计
基于单片机的数字钟(电子日历)(转载)

基于单片机的数字钟(电子日历)(转载)基于单片机的数字钟(电子日历)(转载)2009-06-2412:03/********************************************** ******************************//* 电子日历,有时间显示、闹铃、日期、秒表及键盘设置功能*//* 功能键A: 设置位数字+1 闹钟模式下为闹钟开关秒表模式下为记时开关*//* 功能键B: 设置位数字-1 闹钟模式下为闹钟开关*//* 功能键C:设置模式及设置位选择秒表模式下为清零键*//* 功能键D:在四种工作模式下切换设置闹钟开关*//* 曹宇03电子0201029 *//* 2006.6.3 更新*//*************************************************** *************************/#include#include/***************这里设置程序初始化时显示的时间****************/#define SET_HOUR 12 /*设置初始化小时*/#define SET_MINUTE 00 /*设置初始化分钟*/#define SET_SECOND 00 /*设置初始化秒数*//*************************系统地址****************************/#define BASE_PORT 0x8000 /*选通基地址*/#define KEY_LINE BASE_PORT+1 /*键盘行线地址*/#define KEY_COLUMN BASE_PORT+2 /*键盘列线地址*/ #define LED_SEG BASE_PORT+4 /*数码管段选地址*/#define LED_BIT BASE_PORT+2 /*数码管位选地址*/#define LED_ON(x) XBYTE[LED_BIT]=(0x01/**************在设置模式下对秒分时的宏定义*****************/#define SECOND 0 /*对应数码管右边两位*/#define MINUTE 1 /*对应数码管中间两位*/#define HOUR 2 /*对应数码管左边两位*//********************定义四种工作模式***********************/#define CLOCK clockstr /*时钟模式*/#define ALART alartstr /*闹钟模式*/#define DATE datestr /*日期模式*/#define TIMER timerstr /*秒表模式*//****************以下是所有子函数的声明*********************/void sys_init(void); /*系统的初始化程序*/void display(void); /*动态刷新一次数码管子程序*/void clockplus(void); /*时间加1S的子程序*/void update_clockstr(void); /*更新时间显示编码*/void update_alartstr(void); /*更新闹钟时间的显示编码*/ void update_datestr(void); /*更新日期显示编码*/void update_timerstr(void); /*更新秒表时间的显示编码*/ void deley(int); /*延时子程序*/void update_dispbuf(unsigned char *); /*更新显示缓冲区*/ unsigned char getkeycode(void); /*获取键值子程序*/void keyprocess(unsigned char); /*键值处理子程序*/ unsigned char getmonthdays(unsigned int,unsigned char);/*计算某月的天数子程序*//*功能键功能子函数*/void Akey(void); /*当前设置位+1 开关闹钟开关秒表*/ void Bkey(void); /*当前设置位-1 开关闹钟*/void Ckey(void); /*设置位选择秒表清零*/void Dkey(void); /*切换四种工作模式*//**********************全局变量声明部分*********************/unsigned charled[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x 6F};/*从0~9的LED编码*/unsigned char ledchar[3]={0x5c,0x54,0x71};/*o n f*///unsigned char key[24]={ /* 键值代码数组对应键位:*/// 0x70,0x71,0x72,0x73,0x74,0x75, /* 7 8 9 A TRACE RESET*/// 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5, /* 4 5 6 B STEP MON */ // 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5, /* 1 2 3 C HERE LAST */ // 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5}; /* 0 F E D EXEC NEXT */ struct{ /*时间结构体变量*/unsigned char s;unsigned char m;unsigned char h;}clock={SET_SECOND,SET_MINUTE,SET_HOUR};struct{ /*闹铃时间结构体变量*/unsigned char m;unsigned char h;}alart={SET_MINUTE,SET_HOUR};struct{ /*日期结构体变量*/unsigned int year;unsigned char month;unsigned char day;}date={6,1,1};struct{ /*秒表时间结构体变量*/unsigned char ms;unsigned char s;unsigned char m;}timer={0,0,0};unsigned char dispbuf[6]; /*显示缓冲区数组*/unsigned char clockstr[6]; /*时间显示的数码管编码数组*/ unsigned char alartstr[6]; /*闹钟显示的数码管编码数组*/ unsigned char datestr[6]; /*日期显示的数码管编码数组*/ unsigned char timerstr[6]; /*秒表显示的数码管编码数组*/ unsigned int itime=0,idot; /*定时器0中断计数*/unsigned char itime1=0; /*定时器1中断计数*/sbit P3_1=P3^1; /*外接蜂鸣器的管脚*/bdata bit IsSet=0; /*设置模式标志位0:正常走时1:设置模式*/bdata bit Alart_EN=0; /*闹铃功能允许位0:禁止闹铃1:允许闹铃*/bdata bit IsBeep=0; /*响铃标志位0:未响铃1:正在响铃*/ unsigned char SetSelect=0; /*在设置模式IsSet=1时,正在被设置的位,对应上面的宏*/unsigned char *CurrentMode; /*标志当前正设置的功能,如CurrentMode=CLOCK或CurrentMode=ALART等*/void timerplus(void);/**************************函数部分*************************/void main(void){sys_init();while(1){XBYTE[KEY_COLUMN,0x00]; /*给键盘列线赋全零扫描码,判断是否有键按下*/while((XBYTE[KEY_LINE]&0x0f)==0x0f) /*检测是否有键按下,无则一直进行LED的刷新显示*/{if(Alart_EN&&(clock.h==alart.h)&&(clock.m==alart.m)) {IsBeep=1;}else{ IsBeep=0;P3_1=0;}display();}keyprocess(getkeycode()); /*有键按下时得到键值,并送入键值处理程序*/display(); /*可要可不要*/}}void sys_init(void){TMOD=0x22; /*定时器0和1都设置为工作方式2,基准定时250×2=500us=0.5ms*/TH0=6; /*定时器0中断服务用来产生1秒时钟定时及闹钟蜂鸣器蜂鸣脉冲*/TL0=6; /*定时器1中断服务留给秒表使用,产生1/100秒定时*/TH1=6;TL1=6;ET0=1;ET1=1;EA=1;TR0=1;update_clockstr(); /*初始化时钟显示编码数组*/update_alartstr(); /*初始化闹钟显示编码数组*/update_datestr(); /*初始化日期显示编码数组*/update_timerstr(); /*初始化秒表显示编码数组*/update_dispbuf(clockstr);/*初始化显示缓冲数组*/ CurrentMode=CLOCK; /*默认的显示摸式为时钟*/P3_1=0; /*蜂鸣器接线引脚复位*/}void timer0(void) interrupt 1 using 1 /*定时器0中断服务器,用来产生1秒定时*/{itime++;if(itime==1000){if(IsSet) /*在设置模式下,对正在设置的位闪烁显示*/{dispbuf[SetSelect*2]=0; /*对正在设置的位所对应的显示缓冲区元素赋0,使LED灭*/dispbuf[SetSelect*2+1]=0;}if(IsBeep) P3_1=!P3_1; /*闹钟模式时,产生峰鸣器响脉冲*/ if(CurrentMode==CLOCK){dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}if(itime==2000) /*两千次计数为1S 2000×0.5ms=1s*/{itime=0; /*定时1s时间到,软计数清零*/clockplus(); /*时间结构体变量秒数加1 */update_clockstr(); /* 更新时间显示编码数组*/if(CurrentMode!=TIMER) update_dispbuf(CurrentMode); /* 用时间编码数组更新显示缓冲区*/}}void timer1(void) interrupt 3 using 2 /*定时器1中断服务器,用来产生1/100秒定时*/{idot++;if(++itime1==20) /*20*0.5ms=10ms*/{itime1=0;timerplus();update_timerstr();if(CurrentMode==TIMER){update_dispbuf(timerstr);dispbuf[2]=dispbuf[2]&0x7f; /*关闭小数点的显示*/ dispbuf[4]=dispbuf[4]&0x7f;if(idot<1000) /*闪烁显示小数点*/{dispbuf[2]=dispbuf[2]|0x80;dispbuf[4]=dispbuf[4]|0x80;}else{dispbuf[2]=dispbuf[2]&0x7f;dispbuf[4]=dispbuf[4]&0x7f;}}}if(idot==2000) idot=0;}/*功能模块子函数*/void clockplus(void) /*时间加1s判断分,时子函数*/ {if(++clock.s==60) /*秒位判断*/{clock.s=0;if(++clock.m==60) /*分位判断*/{clock.m=0;if(++clock.h==24) /*时位判断*/{clock.h=0;if(++date.day==(getmonthdays(date.year,date.month)+1)){date.day=1;if(++date.month==13) date.month=1;}}}}}void timerplus() /*秒表1/100秒位加1,判断秒、分子程序*/ {if(++timer.ms==100){timer.ms=0;if(++timer.s==60){timer.s=0;if(++timer.m==60){timer.m=0;}}}}void update_clockstr(void) /*更新时钟显示代码数组clockstr*/ {clockstr[0]=led[clock.s%10]; /*给元素0赋相应数码管显示编码,编码序号是秒数的个位*/clockstr[1]=led[(int)(clock.s/10)]; /*给元素1赋相应数码管显示编码,编码序号是秒数的十位*/clockstr[2]=led[clock.m%10]; /*以下类推*/clockstr[3]=led[(int)(clock.m/10)];clockstr[4]=led[clock.h%10];clockstr[5]=led[(int)(clock.h/10)];}void update_alartstr(void) /*更新闹钟显示代码数组alartstr*/ { /*右边两位显示on:闹钟开启of:闹钟关闭*/if(Alart_EN) alartstr[0]=ledchar[1];/*显示字母n*/else alartstr[0]=ledchar[2]; /*显示字母f*/alartstr[1]=ledchar[0]; /*显示字母o*/alartstr[2]=led[alart.m%10];alartstr[3]=led[(int)(alart.m/10)];alartstr[4]=led[alart.h%10];alartstr[5]=led[(int)(alart.h/10)];}void update_datestr(void) /*更新日期显示代码数组datestr*/ {datestr[0]=led[date.day%10];datestr[1]=led[(int)(date.day/10)];datestr[2]=led[date.month%10];datestr[3]=led[(int)(date.month/10)];datestr[4]=led[date.year%10];datestr[5]=led[(int)(date.year/10)];}void update_timerstr(void) /*更新秒表显示代码数组timerstr*/ {timerstr[0]=led[timer.ms%10];timerstr[1]=led[(int)(timer.ms/10)];timerstr[2]=led[timer.s%10];timerstr[3]=led[(int)(timer.s/10)];timerstr[4]=led[timer.m%10];timerstr[5]=led[(int)(timer.m/10)];}void display(void) /*刷新显示六位LED一次*/{unsigned char i;for(i=0;i<6;i++){LED_ON(i); /*选通相应位*/XBYTE[LED_SEG]=dispbuf[i]; /*写显示段码*/deley(50); /*延时显示*/LED_OFF; /*写LED全灭段码*/}}void update_dispbuf(unsigned char *str) /*更新显示缓冲区子函数,参数为要用来更新缓冲区的源字符数组的首地址*/ {dispbuf[0]=str[0]; /*将要更新的源字符数组内容COPY至dispbuf数组,用作显示缓冲区*/dispbuf[1]=str[1];dispbuf[2]=str[2]|0x80; /*默认把时位和分位后面的小数点显示出来,根据需要再取舍*/dispbuf[3]=str[3];dispbuf[4]=str[4]|0x80;dispbuf[5]=str[5];}void deley(int i) /*延时子函数*/{while(i--);}unsigned char getkeycode(void) /*键盘扫描子程序,返回获得的键码*/{unsigned char keycode; /*键码变量,一开始存行码*/ unsigned char scancode=0x20; /*列扫描码*/unsigned char icolumn=0; /*键的列号*/display(); /*用刷新数码管显示的时间去抖*/XBYTE[KEY_COLUMN]=0x00;keycode=XBYTE[KEY_LINE]&0x0f; /*从行端口读入四位行码*/while((scancode&0x3f)!=0) /*取scancode的低六位,只要没变为全0,则执行循环*/{XBYTE[KEY_COLUMN]=(~scancode)&0x3f; /*给列赋扫描码,第一次为011111*/if((XBYTE[KEY_LINE]&0x0f)==keycode) break; /*检测按键所在的列跳出循环*/scancode=scancode>>1; /*列扫描码右移一位*/icolumn++; /*列号加1*/}keycode=keycode<<4; /*把行码移到高四位*/keycode=keycode|icolumn; /*由行码和列码组成键码*///等待按键放开XBYTE[KEY_COLUMN]=0x00;while((XBYTE[KEY_LINE]&0x0f)!=0x0f) display();return keycode;}void keyprocess(unsigned char keycode) /*键值处理函数*/ {switch (keycode){case 0x73: Akey();break;case 0xB3: Bkey();break;case 0xD3: Ckey();case 0xE3: Dkey();break;default: break;}update_dispbuf(CurrentMode);}unsigned char getmonthdays(unsigned int year,unsigned char month)/*得到某月的天数*/{unsigned char days;switch (month){case 4:case 6:case 9:case 11:days=30;break;case 2: if(year%4==0) days=29;else days=28;break;default:days=31;}return days;}/*功能键子函数部分*/void Akey(void) /*对当前设置位进行加一操作,如果设置秒位,则给秒位清零*/{if(CurrentMode==TIMER) /*秒表模式下启闭走时*/{ TR1=!TR1;return;}if(!IsSet) return; /*如果不是设置模式退出*/switch (SetSelect){case SECOND:if(CurrentMode==CLOCK){clock.s=0; /*如果当前被设置位是秒位,则清零秒位*/ update_clockstr();}if(CurrentMode==ALART){Alart_EN=!Alart_EN;update_alartstr();}if(CurrentMode==DATE){if(++date.day==(getmonthdays(date.year,date.month)+1)) date.day=1;update_datestr();}if(CurrentMode==TIMER){TR1=!TR1;}break;case MINUTE:if(CurrentMode==CLOCK){if(++clock.m==60) clock.m=0; /*如果当前被设置分位,则分位加1*/update_clockstr();}if(CurrentMode==ALART){if(++alart.m==60) alart.m=0;update_alartstr();}if(CurrentMode==DATE){if(++date.month==13) date.month=1;update_datestr();}break;case HOUR: if(CurrentMode==CLOCK){if(++clock.h==24) clock.h=0; /*如果当前被设置时位,则时位加1*/update_clockstr();}if(CurrentMode==ALART){if(++alart.h==24) alart.h=0;update_alartstr();}if(CurrentMode==DATE){if(++date.year==100) date.year=0;update_datestr();}break;default: break;}update_dispbuf(CurrentMode);}void Bkey(void) /*对当前设置位进行减一操作,如果设置秒分,则给秒位清零,类比Akey()函数*/{if(!IsSet) return;switch (SetSelect){case SECOND:if(CurrentMode==CLOCK){clock.s=0;update_clockstr();}if(CurrentMode==ALART){Alart_EN=!Alart_EN;}if(CurrentMode==DATE){if(--date.day==0x00)date.day=getmonthdays(date.year,date.month); update_datestr();}break;case MINUTE:if(CurrentMode==CLOCK) {if(--clock.m==0xff) clock.m=59;update_clockstr();}if(CurrentMode==ALART){if(--alart.m==0xff) alart.m=59;update_alartstr();}if(CurrentMode==DATE){if(--date.month==0x00) date.month=12;}break;case HOUR: if(CurrentMode==CLOCK) {if(--clock.h==0xff) clock.h=23;update_clockstr();}if(CurrentMode==ALART){if(--alart.h==0xff) alart.h=23;update_alartstr();}if(CurrentMode==DATE){if(--date.year==0xffff) date.year=99; update_datestr();}break;default: break;}update_dispbuf(CurrentMode);}void Ckey(void) /*正常走时模式和设置模式的切换*/{if(CurrentMode==TIMER){TR1=0; /*初始化定时器1设置,停止秒表记时*/TH1=6;TL1=6;timer.ms=0; /*初始化秒表数组*/timer.s=0;timer.m=0;update_timerstr();}else{if(IsSet==0) /*在非秒表模式下,第一次按下C键进入设置模式,设置时位*/{IsSet=1; /*置位标志位,进入设置模式*/SetSelect=HOUR;return;} /*第二次按C键设置分位,第三次按键设置秒位,第四次按键完成退出设置*/if(SetSelect==0) /*按到第四次,即设置完秒位后,将标志位IsSet置0,完成设置*/{IsSet=0; /*复位标志位,进入正常走时模式*/return;}if(SetSelect>0) SetSelect--; /*设置位的标志变量SetSelect=0:时位1:分位2:秒位*/}}void Dkey(void) /*工作状态切换:时钟、闹钟、日期、秒表*/{if(CurrentMode==CLOCK) /*切换至闹钟,同时开关闹钟*/ { CurrentMode=ALART;Alart_EN=!Alart_EN;update_alartstr();return;}if(CurrentMode==ALART) /*切换至日期*/{ CurrentMode=DATE;return;}if(CurrentMode==DATE) /*切换至秒表,同时关闭设置模式*/ {CurrentMode=TIMER;IsSet=0;return;}if(CurrentMode==TIMER) /*切换至时钟*/{CurrentMode=CLOCK;return;}}。
基于单片机的电子万年历设计

基于单片机的电子万年历设计一、概述随着科技的快速发展和人们对生活品质的追求,电子设备在日常生活中扮演着越来越重要的角色。
电子万年历作为一种集日期、时间显示于一体的实用电子产品,已经深入到人们的日常生活和工作中。
传统的机械式日历已经无法满足现代人对时间精确性和功能多样性的需求,基于单片机的电子万年历设计应运而生,成为了当前研究的热点之一。
基于单片机的电子万年历设计,旨在利用单片机(如STC89CAT89C51等)的强大计算和控制能力,结合液晶显示屏(LCD)、按键输入等外设,实现时间的准确显示、日期的自动更新、闹钟提醒、温度显示等多样化功能。
该设计不仅具有高度的集成性和可靠性,而且能够通过编程实现各种定制化的功能,满足不同用户的需求。
本文将对基于单片机的电子万年历设计进行详细的介绍和分析,包括设计思路、硬件组成、软件编程等方面。
通过本文的阅读,读者可以了解电子万年历的基本原理和设计方法,掌握单片机在电子万年历设计中的应用技巧,为实际的开发工作提供有益的参考和借鉴。
1.1 研究背景与意义随着科技的不断进步,人们日常生活和工作中对于时间的精度和便捷性的要求日益提高。
传统的机械式日历和简单的电子时钟已经无法满足现代生活的需求。
电子万年历作为一种集时间显示、日历查询、定时提醒等多功能于一体的电子装置,在日常生活、工作乃至科研领域都具有广泛的应用价值。
基于单片机的电子万年历设计,不仅可以提供准确的时间显示,还能实现复杂的日期计算、农历显示、节假日提示等功能,极大地提高了时间管理的效率和便捷性。
单片机作为一种集成度高、功耗低、价格适中的微型计算机,非常适合用于小型化、智能化的电子产品设计,如电子万年历。
本研究的意义在于,通过对基于单片机的电子万年历的设计研究,可以推动微型计算机技术和电子时钟技术的融合发展,提升电子产品的智能化水平,满足人们日益增长的生活和工作需求。
同时,该研究还可以为相关领域的技术人员提供参考和借鉴,推动电子万年历产品的不断创新和优化。
基于单片机的电子时钟万年历设计

(2)31 8 位暂存数据存储RAM(3)串行 I/O 口方式使得管脚数量最少(4)宽范围工作电压2.0 5.5V(5)工作电流 2.0V 时,小于300nA(6)读/写时钟或RAM 数据时有两种传送方式单字节传送和多字节传送字符组方式(7)8 脚DIP 封装或可选的8 脚SOIC 封装根据表面装配(8)简单 3 线接口(9)与 TTL 兼容Vcc=5V(10)可选工业级温度范围-40~+85优点:串行接口的日历时钟芯片,使用简单,接口容易,与微型计算机连线较少等特点,在单片机系统尤其是手持式信息设备中己得到了广泛的应用。
所以,最终选择串行时钟芯片DS1302,DS1302的管脚图如图2所示。
图2 DS1302管脚图1.2显示模块选择方案一:LED数码管显示数码管显示比较常用的是采用CD4511和74LS138实现数码转换,数码显示分动态显示和静态显示,静态显示具有锁存功能,可以使数据显示得很清楚,但浪费了一些资源。
目前单片机数码管普通采用动态显示。
编程简单,但只能显示数字,不能显示中文。
方案二:LCD1602能够显示英文和数字。
1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
所以最终选择LCD1602。
2.项目功能模块2.1 89C51模块Mcs-51单片机管脚图图如图3所示:单片机管脚图2.2 1602液晶显示模块1602液晶模块内部的字符发生存储器(CGROM)已经存储了160个不同的点阵字符图形,这些字符有:阿拉伯数字、英文字母的大小写、常用的符号、和日文假名等,每一个字符都有一个固定的代码,比如大写的英文字母“A”的代码是01000001B(41H),显示时模块把地址41H中的点阵字符图形显示出来,我们就能看到字母“A”。
基于单片机的日历设计方案

引言日历作为我们日常生活中必不可少的工具之一,是人们记录时间、安排活动以及管理生活的重要工具。
在现代科技的发展下,基于单片机的日历设计方案应运而生。
本文将介绍一种基于单片机的日历设计方案,该方案通过单片机的控制和显示功能,能够提供准确的日期和时间显示,具备一些常见的日历功能,并具备一定的扩展性和灵活性。
设计原理硬件设计单片机选择在本设计方案中,选择常见的8位单片机AT89C52作为核心控制芯片。
该单片机具备足够的IO口,能够方便地控制各个模块的输入和输出。
时钟模块为了确保日历的准确性,需要使用一个精确的时钟模块。
在本设计中,选择DS1302时钟模块用于提供稳定的时钟信号。
该模块具备低功耗、精准度高的特点,能够满足日历的需求。
显示模块为了方便用户查看日期和时间,选择一个适合的显示模块十分重要。
本设计方案中,选择TM1637四位数码管模块用于显示日期和时间。
该模块通过单片机的IO口能够方便地进行控制,并能够显示数字和一些常见的符号。
软件设计时钟控制通过单片机与DS1302时钟模块进行通信,获取当前的日期和时间信息。
通过设置注册器来读取年、月、日、时、分和秒的值,并将其保存在单片机内部的变量中。
显示控制通过单片机与TM1637数码管模块进行通信,将日期和时间的值显示在数码管上。
通过设置数码管的段选择和段数据,可以实现具体的数字和符号的显示。
日历功能在本设计方案中,实现了一些常见的日历功能,例如星期显示、日期调整、闹钟设置等。
通过单片机的按键输入,可以实现各种功能的切换和设置。
实现步骤1.连接硬件模块:将单片机、DS1302时钟模块和TM1637数码管模块按照原理图连接起来,并接上所需的电源。
2.编写主程序:使用C语言编写主程序,包括时钟控制、显示控制和日历功能的实现。
3.编译烧录:使用相应的编译器将主程序编译生成可执行文件,并将其烧录到单片机中。
4.测试调试:将单片机上电,通过按键输入进行各种功能的测试和调试,确保日历的正常工作。
基于单片机的电子日历时钟设计

#include<STC12C5A.h>#define uchar unsigned char#define uint unsigned int//----端口定义---sbit ACC_7=ACC^7;sbit RST1=P2^5;sbit IO=P2^6;sbit SCLK=P2^7;sbit k1=P3^2;sbit k2=P3^3;sbit k3=P2^2;sbit k4=P2^3;//uchar wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; // 数码的位选,左到右uchar tab_1302[7]={45,50,11,19,1,1,15};uchar tab_time[8]={0,0,10,0,0,10,0,0}; //时间uchar tab_day[8]={0,0,10,0,0,10,0,0,}; //年月日uchar tab_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//0 1 2 3 4 5 6 7 8 9 - {"0123456789-"}////////////=============函数声明============////////////////void display_time();void delayms(uint);void display_day();void ds1302(); //获取DS1302的时间void ds1302_init(); //DS1302的初始化void write1302(uchar,uchar); //指定地址向DS1302写数据uchar read1302(uchar); //指定地址向DS1302读数据void ds1302();void int0_init();/////////=======中断初始化=======///////////void int0_init(){EX0=1;IT0=1;EX1=1;IT1=1;EA=1;}///////////========时间显示======///////////// void display_time(){P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);P1=0xdf;P0=tab_num[tab_time[5]];delayms(10);P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0xfb;P0=tab_num[tab_time[2]];delayms(10);P1=0xfd;P0=tab_num[tab_time[1]];delayms(10);P1=0xfe;P0=tab_num[tab_time[0]];delayms(10);}//////////=========延时函数========//////////////// void delayms(uint x){int i,j;for(i=x;i>=0;i--)for(j=0;j<=110;j++);}//////////=======日期显示======///////////void display_day(){P1=0x7f;P0=tab_num[tab_day[7]];delayms(10);P1=0xbf;P0=tab_num[tab_day[6]];delayms(10);P1=0xdf;P0=tab_num[tab_day[5]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);P1=0xfb;P0=tab_num[tab_day[2]];delayms(10);P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}////////////=========DS1302初始化======//////////// void ds1302_init() //DS1302初始化,设置初始时间{uchar i,add;add=0x80;write1302(0x8e,0x00);for(i=0;i<7;i++){write1302(add,tab_1302[i]);add+=2;}/* write1302(0x80,0x50); // 秒...write1302(0x82,0x59); // 分write1302(0x84,0x23); // 时write1302(0x86,0x19); // 日write1302(0x88,0x01); // 月write1302(0x8a,0x01); // 周write1302(0x8c,0x15); // 年*/write1302(0x8e,0x80);}//////////============从DS1302获取数据============///////////// uchar read1302(uchar add){uchar i,temp,dat1,dat2;RST1=0;SCLK=0;RST1=1;for(i=8;i>0;i--) //发送地址{SCLK=0;temp=add;IO=(bit)(temp&0x01);add>>=1;SCLK=1;}for(i=8;i>0;i--) //读取数据{ACC_7=IO;SCLK=1;ACC>>=1;SCLK=0;}RST1=0;dat1=ACC;dat2=dat1/16;dat1=dat1%16;dat1=dat1+dat2*10;return(dat1);}/////////============向DS1302写入数据程序================//////////// void write1302(uchar add,uchar dat){uchar i,temp;RST1=0;SCLK=0;RST1=1;for(i=0;i<8;i++) //发送地址{SCLK=0;temp=add;IO=(bit)(temp&0x01);add>>=1;SCLK=1;}temp=(dat/10<<4)|(dat%10);for(i=0;i<8;i++) //发送数据{SCLK=0;IO=(bit)(temp&0x01);temp>>=1;SCLK=1;}RST1=0;}/////////-------------获取DS1302的时间-----------////////void ds1302(){uchar i,add=0x81;write1302(0x8e,0x00); //允许向DS1302写入数据for(i=0;i<7;i++){tab_1302[i]=read1302(add); //获得的数据已转换为十进制add+=2;}write1302(0x8e,0x80); //获取完一次时间,禁止向DS1302写入数据,提高可靠}///////////============转换函数============///////////void change(){tab_time[0]=tab_1302[2]/10; //小时十位tab_time[1]=tab_1302[2]%10; //小时个位tab_time[3]=tab_1302[1]/10; //分十位tab_time[4]=tab_1302[1]%10; //分个位tab_time[6]=tab_1302[0]/10; //秒十位tab_time[7]=tab_1302[0]%10; //秒个位tab_day[0]=tab_1302[6]/10; //年十位tab_day[1]=tab_1302[6]%10; //年个位tab_day[3]=tab_1302[4]/10; //月十位tab_day[4]=tab_1302[4]%10; //月个位tab_day[6]=tab_1302[3]/10; //日十位tab_day[7]=tab_1302[3]%10; //日个位}////////////========主函数=======///////////// void main(){P2M0=0xff;P2M1=0;ds1302_init();int0_init();while(1){ds1302();change();display_time();while(!k4){ds1302();change();display_day();}}}/////========time=========////////////void int0() interrupt 0{uchar ky=0,n1,n2,n3=1,flag=1;while(flag!=0){write1302(0x8e,0x00);write1302(0x80,0x80|tab_1302[0]);P1=0xdf;P0=tab_num[tab_time[5]];delayms(10);P1=0xfb;P0=tab_num[tab_time[2]];delayms(10);if(k3==0){delayms(50);if(k3==0){ky++;while(!k3);if(ky==5){ky=0;}}}//////////=======1========////////if(ky==1){n1=tab_1302[0];if(k4==0){delayms(30);if(k4==0){n1++;while(!k4);if(n1>=60)n1=0;}}tab_1302[0]=n1;change();P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}////////=======2======////////if(ky==2){n2=tab_1302[1];if(k4==0){delayms(30);if(k4==0){n2++;while(!k4);if(n2>=60)n2=0;}}tab_1302[1]=n2;change();P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}/////==3==///if(ky==3){n3=tab_1302[2];if(k4==0){delayms(10);if(k4==0){n3++;while(!k4);if(n3==24)n3=1;}}tab_1302[2]=n3;change();P1=0xfd;P0=tab_num[tab_time[1]];delayms(10);P1=0xfe;P0=tab_num[tab_time[0]];delayms(10);P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}//////===4====////if(ky==4){flag=0;ds1302_init();}}}/////////////=============day================///////////// void int1() interrupt 2{uchar ky=0,n1,n2=1,n3=1,flag=1;while(flag!=0){write1302(0x8e,0x00);write1302(0x80,0x80|tab_1302[0]);P1=0xdf;P0=tab_num[tab_day[5]];delayms(10);P1=0xfb;P0=tab_num[tab_day[2]];delayms(10);if(k3==0){delayms(50);if(k3==0){ky++;while(!k3);if(ky==5){ky=0;}}}//////////=======1========////////if(ky==1){n1=tab_1302[6];if(k4==0){delayms(30);if(k4==0){n1++;while(!k4);if(n1==50)n1=0;}}tab_1302[6]=n1;change();P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}////////=======2======////////if(ky==2){n2=tab_1302[4];if(k4==0){delayms(30);if(k4==0){n2++;while(!k4);if(n2==13)n2=1;}}tab_1302[4]=n2;change();P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);}/////==3==///if(ky==3){n3=tab_1302[3];if(k4==0){delayms(10);if(k4==0){n3++;while(!k4);if(n3==31)n3=1;}}tab_1302[3]=n3;change();P1=0x7f;P0=tab_num[tab_day[7]];delayms(10);P1=0xbf;P0=tab_num[tab_day[6]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}if(ky==4){flag=0;ds1302_init();}}}。
课程设计基于单片机的电子日历设计大学论文

基于单片机的电子日历设计一、设计目的和要求单片机应用技术飞速发展,纵观我们现在生活的各个领域,从导弹的导航装置,到飞机上各种仪表的控制,从计算机的网络通讯与数据传输,到工业自动化过程的实时控制和数据处理,以及我们生活中广泛使用的各种智能IC卡、电子宠物等,这些都离不开单片机。
单片机是集CPU ,RAM ,ROM ,定时,计数和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上。
而51系列单片机是各单片机中最为典型和最有代表性的一种。
这次课程设计通过对它的学习,应用,从而达到学习、设计、开发软、硬的能力。
通过对一个基于单片机的能实现电子日历功能电子时钟的设计,从而达到学习、了解单片机相关指令在各方面的应用。
系统由主控制器AT89C51、时钟电路DS1302、显示电路、和复位电路等部分构成,能实现时钟日历显示的功能,能进行时、分、秒的显示。
系统设计要求:电子日历能显示,能调整。
基于51系列的单片机进行的电子万年历设计可以显示年月日时分秒及周信息,具有可调整日期和时间功能。
在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。
具体实现功能:显示年月日时分秒及星期信息,具有可调整日期和时间功能,与即时时间同步。
主要使用到的工具和器件:✧Keilc51✧Protues✧DS1302✧AT89S52✧LCD12864二、方案设计每一系统都有几个核心的模块。
它对整个系统的性能有非常大的影响。
比如系统的主控。
2.1 主控芯片选择方案论证方案一:选择51系列的单片机;AT89S52 是一种低功耗、高性能CMOS8位微控制器,具有8K 在系统可编程Flash存储器。
使用Atmel 公司高密度非易失性存储器技术制造,与工业80C51 产品指令和引脚完全兼容。
片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得AT89S52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
毕业设计---基于单片机的多功能电子万年历的设计
基于单片机的多功能电子万年历的设计摘要随着科技的快速发展,自从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
本文主要介绍了基于单片机的智能电子万年历的研制,该万年历能够实时显示公历年、月、日、时、分、秒,以及对应的农历日期、24节气、天干地支、闹铃功能,同时还能够实时测取环境温度。
本系统的硬件部分主要由A VR单片机、时钟芯片、温度传感器等部件组成,文中给出了详细的硬件设计实现及相关电路图;软件部分主要包含公历转农历的算法设计模块、显示模块、时间的读取、温度的检测模块,按键的扫描输入模块等,文中给出了系统的软件程序流程图及各功能模块的软件程序清单,最后介绍了整体系统的设计实现、仿真及调试过程,给出了下一步的改进方案等。
关键词:单片机;液晶技术;万年历;时钟芯片Design of Multifunctional digital Perpetual Calendar Based on MCUAbstractWith the development of technology,Since the concept of the sun, Baizhong, andnow the electronic bell,human beings continue to study and constant innovation record。
This paper-based Microcontroller Development of Intelligent electronic calendar, The calendar can display real-time in the calendar year, month, day, hours, minutes and seconds,a nd the correspond ing date of the Lunar New Year, 24 Solar Terms,at the same time also to real-time measurement from the ambient temperature,In addition to the user through the keyboard input years of history,for the correspond ing period of the Lunar.The system hardware from some of the major A VR microcontroller, a number of digital control, decoder, the clock chip,temperature sensors and other components,the paper gives a detailed design and implementation of hardware and related circuit;Software contains some of the major Lunar calendar to the algorithm design module,dynamic digital display modules,time to read,temperature detection module,Press enter the scanning module.In this paper, the system software modules and flow chart of the list of software programs,Finally, the realization of the overall system design, simulation and debugging process, the next step is the improvement programmes.Keywords:MCU;crystal technology;Calendar;Clock chip目录引言 (1)第1章绪论 (2)1.1课题的背景与意义 (2)1.2 数字万年历的现状与发展 (2)1.3 论文的主要工作及章节安排 (3)1.4 本章小结 (3)第2章方案论证比较.............................................................................. (4)2.1 多功能数字万年历系统概述 (4)2.2计时方案 (4)2.3温度检测方案 (5)2.4显示方案 (5)2.5本章小结 (5)第3章系统硬件设计 (6)3.1 主控制器ATmega16 单片机介绍 (6)3.2 时钟电路DS1302 (6)3.3 温度检测DS18B20 (7)3.4 动态显示 (8)3.5 键盘接口 (8)3.6 语音闹铃模块 (8)3.7 电源设计 (9)3.8本章小结 (11)第4章系统软件设计 (12)4.1 公历计算显示程序设计 (13)4.1.1 DS1302 内部寄存器 (13)4.1.2 时间读取程序设计 (15)4.2 农历转换程序设计 (16)4.2.1 公历转农历算法研究 (16)4.2.2 干支纪年简介 (18)4.2.3 公历转农历程序 (18)4.3 温度测量程序设计 (20)4.3.1 DS18B20 的测温原理 (20)4.3.2 温度程序 (21)4.4 二十四节气算法研究 (23)4.5系统仿真 (24)4.6本章小结 (25)结论与展望 (26)致谢 (27)参考文献 (28)附录 A 电子万年历原理图 (29)附录 B 外文文献与译文 (30)英文原文: (30)中文译文: (33)附录 C 参考文献题录及摘要 (35)附录 D 电子万年历源程序 (37)插图清单图2-1 数字万年历系统框图 (4)图3-1 DS1302与ATmega16连接图 (7)图3-2 DS18B20与AtMEGA16连接图 (8)图3-3 报时电路 (9)图3-4 稳压电源原理图 (10)图3-5 电源电路 (10)图4-1 系统程序流程图 (13)图4-2 公历程序流程图 (14)图4-3 DS18B20测温原理 (21)表格清单表3-1 LCD12864显示内容 (8)表4-1 DS1302的寄存器及其控制字 (14)表4-2 RS位配置 (15)引言人类的日常生活离不开时间,任何具有周期性变化的自然现象都可以用来测量时间。
基于51单片机的电子日历的应用设计与实现
摘要摘要随着科技的快速发展,时间的流逝,从观太阳、摆钟到现在电子钟,人类不断研究,不断创新纪录。
美国DALLAS公司推出的具有涓细电流充电能的低功耗实时时钟电路DS1302。
它可以对年、月、日、周日、时、分、秒进行计时,还具有闰年补偿等多种功能,而且DS1302的使用寿命长,误差小。
对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒信息,还具有时间校准等功能。
本设计以数字集成电路技术为基础,单片机技术为核心。
软件设计采用模块化结构,C语言编程。
系统通过LCD显示数据,可以显示公历日期(年、月、日、时、分、秒)以及星期。
在内容安排上首先描述系统硬件工作原理,着重介绍了各硬件接口技术和各个接口模块;其次,详细的阐述了程序的各个模块和实现过程。
具体实现功能:(1)显示年月日时分秒及星期信息(2)具有可调整日期和时间功能关键词:万年历单片机DS1302目录目录摘要 (I)第一章方案论证 (1)1.1单片机芯片的选择方案和论证 (1)1.2显示模块选择方案和论证 (1)1.3时钟芯片的选择方案和论证 (1)1.4电路设计最终方案决定 (2)第二章系统的硬件设计与实现 (3)2.1 总体电路 (3)2.2单片机主控制模块的设计 (3)2.2.1 AT89S52的介绍 (3)2.2.2 单片机主控制模块介绍 (5)2.3 时钟模块设计 (5)2.3.1 DS1302的性能特性 (5)2.3.2 DS1302数据操作原理 (6)2.3.3 DS1302与AT89S52接口电路设计 (7)2.4显示模块的设计 (8)2.4.1 LCM1602介绍 (8)2.4.2 LCM1602与单片机的接口 (9)第三章系统的软件设计 (11)3.1程序总体描述 (11)3.2模块程序描述 (11)第四章PROTEUS仿真 (13)4.1 PROTEUS工作界面 (13)4.2 PROTEUS功能仿真 (13)第五章测试与结果分析 (15)5.1测试仪器 (15)5.2硬件测试 (15)5.3软件测试 (16)5.4 测试结果分析与结论 (16)5.4.1 测试结果分析 (16)5.4.2 测试结论 (16)第六章总结与展望 (17)致谢 (19)参考文献 (21)附录1 系统电路图 (23)附录2 系统程序 (24)第一章方案论证第一章方案论证1.1单片机芯片的选择方案和论证方案一:采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造成一定的损坏。
毕业设计(论文)-基于51单片机的电子日历的设计
3.3时钟模块设计
实时时钟电路DS1302是DALLAS公司的一种具有涓细电流充电能力的电路,主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。采用普通32.768kHz晶振。
它是一种一种高性能、低功耗、带RAM的实时时钟电路,可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。
当主电源Vcc发生故障而突然下降到一定低电压或断电时,第2功能Vpd将为片内RAM提供电源以保护片内RAM中的信息不丢失。
ALE/PROG:地址锁存允许信号输入端。在存取外存储器时,用于锁存低8位地址信号。当单片机正常工作后,ALE端就周期性地以时钟振荡频率的1/6固定频率向外输出正脉冲信号。此引脚的第2功能PROG是对片内带有4K字节EPROM的8751固外程序时,作为编程脉冲输入端。
Vcc:接+5V 电源
Vss:接地
XTAL1和XTAL2:时钟引脚,外接晶体引线端。当使用芯片内部时钟时,此两引脚端用于外接石英晶体和微调电容;当使用外部时钟时,用于接外部时钟脉冲信号。
RST/Vpq:RST是复位信号输入端,Vpd是备用电源输入端。当RST输入端保持2个机器周期以上高电平时,单片机完成复位初始化操作。
随着微电子技术的高速发展,人类用于计时的工具也在不断发展更新,单片机技术的出现使得万年历有了新的发展方向。
单片机以其体积小、功能全、性价比高等诸多优点,在工业控制、家用电器、通信设备、信息处理、尖端武器等各种测控领域的应用中独占鳌头,单片机开发技术已成为电子信息、电气、通信、自动化、机电一体化等专业技术人员必须掌握的技术。目前世界上单片机年产量已达十多亿片,通常是当年微处理器产量的4-5倍以上。用最少的芯片就能实现最强大的功能,这是将来电子产品的主流方向,它将无可置疑地一步步取代其它同类产品,其数量之大和应用面之广,是其它任何类型的计算机所无法比拟的。
基于51单片机 和 DS12C887的日历时钟显示系统设计
基于DS12C887的日历时钟显示系统设计在银行或者其他的公共场合中,经常会看到显示实时信息的显示屏,其中包括年、月、日、星期、时间等,本例子的功能是在51单片机系统中设置、获取、记录实时的日历时钟信息并通过数码管显示,选用日历时钟芯片DS12C887作为实时时钟芯片,为系统提供详细的时间信息,次款芯片内部有锂电池,可以带掉电的情况下保存10年以上。
主要器件:1、AT89C52单片机芯片,用于对时钟芯片的控制和初始化,并控制数码管显示。
2、日历时钟芯片DS12C887。
试验流程图;试验电路图:试验程序代码://CalendarClk.h程序#ifndef _CALENDARCLK_H // 防止CalendarClk.h被重复引用#define _CALENDARCLK_H#include <reg52.h>#include <absacc.h>#define uchar unsigned char#define uint unsigned int/* DS12C887 内部专用寄存器宏定义 */#define MIN XBYTE[0x0102]#define HOUR XBYTE[0x0104]#define DAYOFWEEK XBYTE[0x0106]#define DAYOFMONTH XBYTE[0x0107]#define MONTH XBYTE[0x0108]#define YEAR XBYTE[0x0109]#define REG_A XBYTE[0x010a]#define REG_B XBYTE[0x010b]/* 由串口获得的日历时钟信息变量,用于对芯片时间的设置 */uchar year1,month1,dayofweek1,dayofmonth1,hour1,min1;/* 芯片DS12C887提供的日历时钟信息变量 */uchar year2,month2,dayofweek2,dayofmonth2,hour2,min2;#endif//CalendarClk.c程序#include "CalendarClk.h"/* 从串行口获取数据函数,数据包括:year1,month1,dayofweek1, dayofmonth1,hour1,min1。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<STC12C5A.h>#define uchar unsigned char#define uint unsigned int//----端口定义---sbit ACC_7=ACC^7;sbit RST1=P2^5;sbit IO=P2^6;sbit SCLK=P2^7;sbit k1=P3^2;sbit k2=P3^3;sbit k3=P2^2;sbit k4=P2^3;//uchar wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; // 数码的位选,左到右uchar tab_1302[7]={45,50,11,19,1,1,15};uchar tab_time[8]={0,0,10,0,0,10,0,0}; //时间uchar tab_day[8]={0,0,10,0,0,10,0,0,}; //年月日uchar tab_num[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf};//0 1 2 3 4 5 6 7 8 9 - {"0123456789-"}////////////=============函数声明============////////////////void display_time();void delayms(uint);void display_day();void ds1302(); //获取DS1302的时间void ds1302_init(); //DS1302的初始化void write1302(uchar,uchar); //指定地址向DS1302写数据uchar read1302(uchar); //指定地址向DS1302读数据void ds1302();void int0_init();/////////=======中断初始化=======///////////void int0_init(){EX0=1;IT0=1;EX1=1;IT1=1;EA=1;}///////////========时间显示======///////////// void display_time(){P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);P1=0xdf;P0=tab_num[tab_time[5]];delayms(10);P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0xfb;P0=tab_num[tab_time[2]];delayms(10);P1=0xfd;P0=tab_num[tab_time[1]];delayms(10);P1=0xfe;P0=tab_num[tab_time[0]];delayms(10);}//////////=========延时函数========//////////////// void delayms(uint x){int i,j;for(i=x;i>=0;i--)for(j=0;j<=110;j++);}//////////=======日期显示======///////////void display_day(){P1=0x7f;P0=tab_num[tab_day[7]];delayms(10);P1=0xbf;P0=tab_num[tab_day[6]];delayms(10);P1=0xdf;P0=tab_num[tab_day[5]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);P1=0xfb;P0=tab_num[tab_day[2]];delayms(10);P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}////////////=========DS1302初始化======//////////// void ds1302_init() //DS1302初始化,设置初始时间{uchar i,add;add=0x80;write1302(0x8e,0x00);for(i=0;i<7;i++){write1302(add,tab_1302[i]);add+=2;}/* write1302(0x80,0x50); // 秒...write1302(0x82,0x59); // 分write1302(0x84,0x23); // 时write1302(0x86,0x19); // 日write1302(0x88,0x01); // 月write1302(0x8a,0x01); // 周write1302(0x8c,0x15); // 年*/write1302(0x8e,0x80);}//////////============从DS1302获取数据============///////////// uchar read1302(uchar add){uchar i,temp,dat1,dat2;RST1=0;SCLK=0;RST1=1;for(i=8;i>0;i--) //发送地址{SCLK=0;temp=add;IO=(bit)(temp&0x01);add>>=1;SCLK=1;}for(i=8;i>0;i--) //读取数据{ACC_7=IO;SCLK=1;ACC>>=1;SCLK=0;}RST1=0;dat1=ACC;dat2=dat1/16;dat1=dat1%16;dat1=dat1+dat2*10;return(dat1);}/////////============向DS1302写入数据程序================//////////// void write1302(uchar add,uchar dat){uchar i,temp;RST1=0;SCLK=0;RST1=1;for(i=0;i<8;i++) //发送地址{SCLK=0;temp=add;IO=(bit)(temp&0x01);add>>=1;SCLK=1;}temp=(dat/10<<4)|(dat%10);for(i=0;i<8;i++) //发送数据{SCLK=0;IO=(bit)(temp&0x01);temp>>=1;SCLK=1;}RST1=0;}/////////-------------获取DS1302的时间-----------////////void ds1302(){uchar i,add=0x81;write1302(0x8e,0x00); //允许向DS1302写入数据for(i=0;i<7;i++){tab_1302[i]=read1302(add); //获得的数据已转换为十进制add+=2;}write1302(0x8e,0x80); //获取完一次时间,禁止向DS1302写入数据,提高可靠}///////////============转换函数============///////////void change(){tab_time[0]=tab_1302[2]/10; //小时十位tab_time[1]=tab_1302[2]%10; //小时个位tab_time[3]=tab_1302[1]/10; //分十位tab_time[4]=tab_1302[1]%10; //分个位tab_time[6]=tab_1302[0]/10; //秒十位tab_time[7]=tab_1302[0]%10; //秒个位tab_day[0]=tab_1302[6]/10; //年十位tab_day[1]=tab_1302[6]%10; //年个位tab_day[3]=tab_1302[4]/10; //月十位tab_day[4]=tab_1302[4]%10; //月个位tab_day[6]=tab_1302[3]/10; //日十位tab_day[7]=tab_1302[3]%10; //日个位}////////////========主函数=======///////////// void main(){P2M0=0xff;P2M1=0;ds1302_init();int0_init();while(1){ds1302();change();display_time();while(!k4){ds1302();change();display_day();}}}/////========time=========////////////void int0() interrupt 0{uchar ky=0,n1,n2,n3=1,flag=1;while(flag!=0){write1302(0x8e,0x00);write1302(0x80,0x80|tab_1302[0]);P1=0xdf;P0=tab_num[tab_time[5]];delayms(10);P1=0xfb;P0=tab_num[tab_time[2]];delayms(10);if(k3==0){delayms(50);if(k3==0){ky++;while(!k3);if(ky==5){ky=0;}}}//////////=======1========////////if(ky==1){n1=tab_1302[0];if(k4==0){delayms(30);if(k4==0){n1++;while(!k4);if(n1>=60)n1=0;}}tab_1302[0]=n1;change();P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}////////=======2======////////if(ky==2){n2=tab_1302[1];if(k4==0){delayms(30);if(k4==0){n2++;while(!k4);if(n2>=60)n2=0;}}tab_1302[1]=n2;change();P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}/////==3==///if(ky==3){n3=tab_1302[2];if(k4==0){delayms(10);if(k4==0){n3++;while(!k4);if(n3==24)n3=1;}}tab_1302[2]=n3;change();P1=0xfd;P0=tab_num[tab_time[1]];delayms(10);P1=0xfe;P0=tab_num[tab_time[0]];delayms(10);P1=0xef;P0=tab_num[tab_time[4]];delayms(10);P1=0xf7;P0=tab_num[tab_time[3]];delayms(10);P1=0x7f;P0=tab_num[tab_time[7]];delayms(10);P1=0xbf;P0=tab_num[tab_time[6]];delayms(10);}//////===4====////if(ky==4){flag=0;ds1302_init();}}}/////////////=============day================///////////// void int1() interrupt 2{uchar ky=0,n1,n2=1,n3=1,flag=1;while(flag!=0){write1302(0x8e,0x00);write1302(0x80,0x80|tab_1302[0]);P1=0xdf;P0=tab_num[tab_day[5]];delayms(10);P1=0xfb;P0=tab_num[tab_day[2]];delayms(10);if(k3==0){delayms(50);if(k3==0){ky++;while(!k3);if(ky==5){ky=0;}}}//////////=======1========////////if(ky==1){n1=tab_1302[6];if(k4==0){delayms(30);if(k4==0){n1++;while(!k4);if(n1==50)n1=0;}}tab_1302[6]=n1;change();P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}////////=======2======////////if(ky==2){n2=tab_1302[4];if(k4==0){delayms(30);if(k4==0){n2++;while(!k4);if(n2==13)n2=1;}}tab_1302[4]=n2;change();P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);}/////==3==///if(ky==3){n3=tab_1302[3];if(k4==0){delayms(10);if(k4==0){n3++;while(!k4);if(n3==31)n3=1;}}tab_1302[3]=n3;change();P1=0x7f;P0=tab_num[tab_day[7]];delayms(10);P1=0xbf;P0=tab_num[tab_day[6]];delayms(10);P1=0xef;P0=tab_num[tab_day[4]];delayms(10);P1=0xf7;P0=tab_num[tab_day[3]];delayms(10);P1=0xfd;P0=tab_num[tab_day[1]];delayms(10);P1=0xfe;P0=tab_num[tab_day[0]];delayms(10);}if(ky==4){flag=0;ds1302_init();}}}。