单片机时钟显示温度显示
基于单片机的多功能数字时钟设计

技术平台采用碱性电解液电沉积活性锌粉,选取电解液浓度1.25g/cm3,电流密度150mA/cm2,电解槽温度只需控制在室温,锌粉洗涤后真空干燥,所制得的锌粉比表面积大于0.8m2/g,具有较高的电化学活性,能满足锌银电池生产需要,生产效率也达到批量生产要求。
参考文献:[1]侯新刚,王胜,王玉棉.超细活性锌粉的制备与表征[J].粉末冶金工业,2004,14(1):10-13.[2]李永祥,黄孟阳,任锐.电解法制备树枝状锌粉工艺研究[J].四川有色金属,2011,(3):45-50.[3]胡会利,李宁,程瑾宁,等.电解法制备超细锌粉的工艺研究[J].粉末冶金工业,2007,17(1):24-29.基于单片机的多功能数字时钟设计刘晓萌(安徽职业技术学院铁道学院/合肥铁路工程学校,安徽 合肥 230011)摘 要:常见的数字钟有时间、闹钟等功能。
本文基于单片机、温度传感器、液晶显示屏、时钟芯片等硬件设计了多功能数字时钟,软件部分采用C语言编程实现。
该多功能数字时钟包含万年历、节日、节气、温度信息显示等功能,并且在断电的情况下也能正常工作。
关键词:单片机;多功能数字时钟;C语言编程0 引言人类对于时间的需求从古到今始终存在。
古代有浑天仪、日晷,近代出现了机械时钟。
如今,传统的计时工具,甚至是电子钟都已经满足不了人们多元化的时间需求。
数字时钟具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的应用空间[1]。
使用数字时钟,用户可以获取精确到秒的时间信息,或是对时钟进行自定义的操作,为现代社会提供了极大的方便[2]。
然而,传统的数字时钟只包含时间显示、闹钟等功能,存在一定的局限性。
本文基于单片机、温度传感器、液晶显示屏、时钟芯片、键盘模块、闹铃模块和电力支持模块等硬件,设计了一款多功能的数字时钟。
1 系统硬件组成数字时钟的硬件由七个模块组成,包括:STC89C52单片机主控芯片、DS1302时钟芯片、DS18B20温度芯片、LCD1602液晶显示模块、闹铃模块、键盘模块和电源。
基于51单片机的多功能电子钟设计

基于51单片机的多功能电子钟设计1. 本文概述随着现代科技的发展,电子时钟已成为日常生活中不可或缺的一部分。
本文旨在介绍一种基于51单片机的多功能电子钟的设计与实现。
51单片机因其结构简单、成本低廉、易于编程等特点,在工业控制和教学实验中得到了广泛应用。
本文将重点阐述如何利用51单片机的这些特性来设计和实现一个具有基本时间显示、闹钟设定、温度显示等功能的电子钟。
本文的结构安排如下:将详细介绍51单片机的基本原理和特点,为后续的设计提供理论基础。
接着,将分析电子钟的功能需求,包括时间显示、闹钟设定、温度显示等,并基于这些需求进行系统设计。
将详细讨论电子钟的硬件设计,包括51单片机的选型、时钟电路、显示电路、温度传感器电路等。
软件设计部分将介绍如何通过编程实现电子钟的各项功能,包括时间管理、闹钟控制、温度读取等。
本文将通过实验验证所设计的电子钟的功能和性能,并对实验结果进行分析讨论。
通过本文的研究,旨在为电子钟的设计提供一种实用、经济、可靠的方法,同时也为51单片机的应用提供一个新的实践案例。
2. 51单片机概述51单片机,作为一种经典的微控制器,因其高性能、低功耗和易编程的特性而被广泛应用于工业控制、智能仪器和家用电器等领域。
它基于Intel 8051微处理器的架构,具备基本的算术逻辑单元(ALU)、程序计数器(PC)、累加器(ACC)和寄存器组等核心部件。
51单片机的核心是其8位CPU,能够处理8位数据和执行相应的指令集。
51单片机的内部结构主要包括中央处理单元(CPU)、存储器、定时器计数器、并行IO口、串行通信口等。
其存储器分为程序存储器(ROM)和数据存储器(RAM)。
程序存储器通常用于存放程序代码,而数据存储器则用于存放运行中的数据和临时变量。
51单片机还包含特殊功能寄存器(SFR),用于控制IO端口、定时器计数器和串行通信等。
51单片机的工作原理基于冯诺伊曼体系结构,即程序指令和数据存储在同一块存储器中,通过总线系统进行传输。
单片机用C51实现时间、星期、年月、温度在DS1602上显示的多功能数字钟

//***************************************************************************** //******用DS1602实现可调日期,时间,星期及温度实时监测的实用数字钟功能******* //*****************创建日期:2010-1-7***********************//功能介绍:用3*3按键在DS1602上显示第一排显示"2010-01-05 MON"第二排显示"23:59:00"//*******************功能介绍**************************************//********* K6:adjtime K3:hour K2:minute K1:OK*******************//********* K3:adjalarm K3:hh K1:OK**********************//********* K2:lookalarm K1:OK **********************//********* K1:alarm ON/OFF ***********************//********* K5:adjdate (K9:month)K8:day (K7:week)K4:OK*********//***********************************************************************#include "main.h"void lcd_data(unsigned char dat);//DS1602数据写入unsigned char kbscan();//按键扫描void ds1602();//DS1602初始化void lcd_com(unsigned char com);//DS1602命令写入void timer0();//用于延时的定时中断初始2mSvoid disp();//主程序的显示调用void display();//正常的显示void display_alarm();//查看闹铃void alarm();//闹铃void process();//按键的处理unsigned char hands();//与18B20通信握手void write_temp_date(unsigned char dat);//写温度数据18B20unsigned char read_temp_date();//读温度数据18B20void tmpdelay(unsigned char tmp);//ds18b20对时序要求严格unsigned char result();//计算月份的天数//*******************************//DS1602命令的写入//*******************************void lcd_com(unsigned char com){rs=0;rw=0;P0=com;dema=1;while(dema!=0);en=1;dema=1;while(dema!=0);en=0;}//*********************//DS1602数据的写入//*********************void lcd_data(unsigned char dat){rs=1;rw=0;P0=dat;dema=1;while(dema!=0);en=1;dema=1;while(dema!=0);en=0;}//***************************//3*3按键的扫描//***************************unsigned char kbscan(){unsigned char sccode,recode,tenp;P1=0XF8;tenp=P1;if(tenp!=0xf8){demb=3;while(demb!=0);if(tenp==P1){sccode=0xfe;while((sccode&0xf7)!=0){P1=sccode;if((P1&0xf8)!=0xf8){recode=P1&0Xf8;sccode=sccode&0xc7;return(recode|sccode);}elsesccode=sccode<<1|0x01;}}}return(0);}//**************************//*********每月的天数计算***//**************************unsigned char result(){switch(month){case 1:return 31;break;case 3:return 31;break;case 5:return 31;break;case 7:return 31;break;case 8:return 31;break;case 10:return 31;break;case 12:return 31;break;case 4:return 30;break;case 6:return 30;break;case 9:return 30;break;case 11:return 30;break;case 2:if(year%4==0){return 29;//闰年29天}else{return 28;//平年28天}}}//**************************//*********DS1602的初始化***//**************************void ds1602(){lcd_com(0x38);//16*2显示5*7矩阵dema=1;while(dema!=0);lcd_com(0x0c);//显示开,无光标无闪烁dema=1;while(dema!=0);lcd_com(0x06);//指针+1,整屏不动dema=1;while(dema!=0);lcd_com(0x01);//清屏}//*******************************//定时中断延时的初始化以及中断***//*******************************void timer0(){TMOD=0X01;TH0=0Xf8;TL0=0X30; //2mS初值12M晶振TR0=1;ET0=1;EA=1;}TIME0() interrupt 1{TR0=0;TH0=0Xf8;TL0=0X30; //2mS初值TR0=1;count++;if(count>=500)//1s{count=0;second++;if(second>=60)//1m{second=0;minute++;if(minute>=60)//1h{minute=0;hour++;if(hour>=24)//1day{hour=0;flag_week++;//星期调整if(flag_week>8){flag_week=1;}day++;if(day>(days=result()))//1month{day=1;month++;if(month>12)//1year{month=1;year++;if(year>100){year=0;}}}}}}}if(dema)dema--;//写命令的延时if(demb)demb--;//按键的延时//************闹铃**********if(demc){demc--;}if(demd){demd--;}flag++;if(flag>=200){flag=0;temp=1;deme++;if(deme>=2){demc=0;temp=0;}}}//**************************//正常日期时间显示//**************************void display(){a=hour/10;b=hour%10;c=minute/10;d=minute%10;e=second/10;f=second%10;m3=year/10;m4=year%10;m6=month/10;m7=month%10;m9=day/10;m10=day%10;//*****第一排显示**********lcd_com(0x81);//第一排从第2个位置开始显示lcd_data(0x32);lcd_com(0x82);lcd_data(0x30);lcd_com(0x83);lcd_data(0x30+m3);lcd_com(0x84);lcd_data(0x30+m4);lcd_com(0x85);lcd_data(0x2d);//"-"lcd_com(0x86);lcd_data(0x30+m6);lcd_com(0x87);lcd_data(0x30+m7);lcd_com(0x88);lcd_data(0x2d);//"-"lcd_com(0x89);lcd_data(0x30+m9);lcd_com(0x8a);lcd_data(0x30+m10);if(flag_week==1)//周1{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week1[n]);}}else if(flag_week==2)//周2 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week2[n]);}}else if(flag_week==3)//周3 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week3[n]);}}else if(flag_week==4)//周4 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week4[n]);}}else if(flag_week==5)//周5 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week5[n]);}}else if(flag_week==6)//周6 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week6[n]);}}else if(flag_week==7)//周7{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week7[n]);}}//*****第二排显示***********lcd_com(0xc1);//第二排从第3个位置开始显示lcd_data(0x30+a);lcd_com(0xc2);lcd_data(0x30+b);lcd_com(0xc3);lcd_data(0x3a);//":"lcd_com(0xc4);lcd_data(0x30+c);lcd_com(0xc5);lcd_data(0x30+d);lcd_com(0xc6);lcd_data(0x3a);//":"lcd_com(0xc7);lcd_data(0x30+e);lcd_com(0xc8);lcd_data(0x30+f);lcd_com(0xca);lcd_data(0x47);//"G"lcd_com(0xcb);lcd_data(0x47);//"G"lcd_com(0xcd);all_date=all_date%100;lcd_data(match[all_date/10]);//十位lcd_com(0xce);lcd_data(match[all_date%10]);//个位lcd_com(0xcf);lcd_data('C');//"temperapure" "C"}//********************************************** //*************************看闹钟*************** void display_alarm(){a=hh/10;b=hh%10;c=min/10;d=min%10;e=sec/10;f=sec%10;m3=year/10;m4=year%10;m6=month/10;m7=month%10;m9=day/10;m10=day%10;//*****第一排显示**********lcd_com(0x81);//第一排从第2个位置开始显示lcd_data(0x32);lcd_com(0x82);lcd_data(0x30);lcd_com(0x83);lcd_data(0x30+m3);lcd_com(0x84);lcd_data(0x30+m4);lcd_com(0x85);lcd_data(0x2d);//"-"lcd_com(0x86);lcd_data(0x30+m6);lcd_com(0x87);lcd_data(0x30+m7);lcd_com(0x88);lcd_data(0x2d);//"-"lcd_com(0x89);lcd_data(0x30+m9);lcd_com(0x8a);lcd_data(0x30+m10);if(flag_week==1)//周1{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week1[n]);}}else if(flag_week==2)//周2{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week2[n]);}}else if(flag_week==3)//周3 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week3[n]);}}else if(flag_week==4)//周4 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week4[n]);}}else if(flag_week==5)//周5 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week5[n]);}}else if(flag_week==6)//周6 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week6[n]);}}else if(flag_week==7)//周7 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week7[n]);}}//****第二排**************lcd_com(0xc1);//第二排从第3个位置开始显示lcd_data(0x30+a);lcd_com(0xc2);lcd_data(0x30+b);lcd_com(0xc3);lcd_data(0x3a);//":"lcd_com(0xc4);lcd_data(0x30+c);lcd_com(0xc5);lcd_data(0x30+d);lcd_com(0xc6);lcd_data(0x3a);//":"lcd_com(0xc7);lcd_data(0x30+e);lcd_com(0xc8);lcd_data(0x30+f);lcd_com(0xcd);all_date=all_date%100;lcd_data(match[all_date/10]);//十位lcd_com(0xce);lcd_data(match[all_date%10]);//个位lcd_com(0xcf);lcd_data('C');//"temperapure" "C"}//**********************//闹钟开的显示**********//**********************void display_onalarm(){a=hour/10;b=hour%10;c=minute/10;d=minute%10;e=second/10;f=second%10;m3=year/10;m4=year%10;m6=month/10;m7=month%10;m9=day/10;m10=day%10;//*****第一排显示**********lcd_com(0x81);//第一排从第2个位置开始显示lcd_data(0x32);lcd_com(0x82);lcd_data(0x30);lcd_com(0x83);lcd_data(0x30+m3);lcd_com(0x84);lcd_data(0x30+m4);lcd_com(0x85);lcd_data(0x2d);//"-"lcd_com(0x86);lcd_data(0x30+m6);lcd_com(0x87);lcd_data(0x30+m7);lcd_com(0x88);lcd_data(0x2d);//"-"lcd_com(0x89);lcd_data(0x30+m9);lcd_com(0x8a);lcd_data(0x30+m10);if(flag_week==1)//周1{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week1[n]);}}else if(flag_week==2)//周2{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week2[n]);}}else if(flag_week==3)//周3{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week3[n]);}}else if(flag_week==4)//周4{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week4[n]);}}else if(flag_week==5)//周5{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week5[n]);}}else if(flag_week==6)//周6{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week6[n]);}}else if(flag_week==7)//周7{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week7[n]);}}//****第二排**************lcd_com(0xc1);//第二排从第3个位置开始显示lcd_data(0x30+a);lcd_com(0xc2);lcd_data(0x30+b);lcd_com(0xc3);lcd_data(0x3a);//":"lcd_com(0xc4);lcd_data(0x30+c);lcd_com(0xc5);lcd_data(0x30+d);lcd_com(0xc6);lcd_data(0x3a);//":"lcd_com(0xc7);lcd_data(0x30+e);lcd_com(0xc8);lcd_data(0x30+f);lcd_com(0xca);lcd_data(0x4B);//"K"lcd_com(0xcb);lcd_data(0x4B);//"K"lcd_com(0xcd);all_date=all_date%100;lcd_data(match[all_date/10]);//十位lcd_com(0xce);lcd_data(match[all_date%10]);//个位lcd_com(0xcf);lcd_data('C');//"temperapure" "C" }//*****************************//*******按键的处理************//***************************** void process(){if(key!=0){if(key==K6){display();while((key=kbscan())!=K1){display();if((key=kbscan())==K3){hour++;if(hour>=24){hour=0;}}if((key=kbscan())==K2){minute++;if(minute>=60){minute=0;}}}}else if(key==K2)//看闹铃{while(((key=kbscan())!=K1)){display_alarm();}}else if(key==K3)//调闹铃{display_alarm();while((key=kbscan())!=K1){display_alarm();if((key=kbscan())==K3){hh++;if(hh>=24){hh=0;}}if((key=kbscan())==K2){min++;if(min>=60){min=0;}}}}else if(key==K1)//开/关闹钟{flag_alarm=~flag_alarm; }else if(key==K5)//调日期星期{display();while((key=kbscan())!=K4)//ok{display();// if((key=kbscan())==K9)//month // {// month++;// if(month>12)// {// month=1;// }// }if((key=kbscan())==K8)//day{day++;flag_week++;if(flag_week>7){flag_week=1;}if(day>(days=result())){day=1;month++;if(month>12){month=1;year++;if(year>100){year=0;}}}// if((key=kbscan())==K7)//week // {// flag_week++;// if(flag_week>8)// {// flag_week=1;// }// }}}}}}//*************************************//*****************闹铃****************//*************************************void alarm(){if(flag_offalarm==1){if(flag_alarm==1){if(temp){TR0=0;TH0=0Xf8;TL0=0X30;TR0=1; //重装初值2mSdemd=2;while(demd!=0);//P37=~P37;}else{TR0=0;TH0=0XF8;TL0=0X30;TR0=1; //重装初值demc=1;while(demc!=0);//P37=~P37;}}else{P37=1;flag_offalarm=0;}}elseif((flag_alarm==1)&&(minute==min)&&(hour==hh)) {flag_offalarm=1;if(temp){TR0=0;TH0=0Xf8;TL0=0X30;TR0=1; //重装初值2mSdemd=2;while(demd!=0);//P37=~P37;}else{TR0=0;TH0=0XF8;TL0=0X30;TR0=1; //重装初值demc=1;while(demc!=0);//P37=~P37;}}}//**********************************//***********DS18B20时序控制*********** //**********************************void tmpdelay(unsigned char tmp)//注意!!{while(tmp>0){tmp--;}}//*tmdelay(1) ;//16.28us//增加一个就加6.5us // tmdelay(2) ;//22.78us// tmdelay(3) ;//29.30us// tmdelay(4) ;//35.81us// tmdelay(70) ;//465.49// tmdelay(74) ;//491.54// tmdelay(80) ;//530.60// tmdelay(115) ;//150us *//*例如16.28+(?*6.5)=490*///********************************//**************************************//**********DS18B20读取温度***********//*************************************unsigned char read_temp_date()//读温度数据18B20{unsigned char i;unsigned int y=0;value=0;for(i=8;i>0;i--){value>>=1;DQ=0;// tmpdelay(1);//>15usy++;y++;y++;y++;//1-15usDQ=1;// tmpdelay(1);//读温度对时序要求严格不能用tmpdelay(1)代替y++;if(DQ==1){value=value|0x80;}else{}tmpdelay(16);//120US}return (value);}//**************************************//**********DS18B20写指令温度***********//*************************************void write_temp_date(unsigned char dat)//写温度指令18B20{unsigned char i;for(i=8;i>0;i--){DQ=0;tmpdelay(1);//>15usif((dat&0x01)==1){DQ=1;tmpdelay(16);//120us}else{DQ=0;tmpdelay(16);//120usDQ=1;tmpdelay(1);//>15us}dat=dat>>1;}DQ=1;tmpdelay(1);//>15us}//**************************************//**********DS18B20复位*****************//*************************************unsigned char hands()//握手复位{temp=0;// noanswer:do{DQ=0;tmpdelay(72);//490uSDQ=1;tmpdelay(11);/*>60uS 注意:此处把函数名改为hans()后,这里两处的tmpdelay()括号内最好改成74和12*/}while(DQ!=0);temp=1;tmpdelay(35);//>240usDQ=1;return(temp);//此处可以采用两种方式表达,1用直到...才;2用goto转向// if(DQ==1)// {// goto noanswer;// }// else if(DQ==0)// {// temp=1;// tmpdelay(40);//>250uS// DQ=1;// }// return(temp);}void disp(){if(flag_alarm){display_onalarm();}else{display();}}//***********************//*******主程序**********//***********************main(void){timer0();//中断延时初始化ds1602();//初始化while(1){key=kbscan();//调用按键process();//按键处理alarm();//闹零if(hands()==1){write_temp_date(0xcc);//跳过write_temp_date(0x44);//温度转换tmpdelay(75);//500us// dema=250;// while(dema!=0);//500ms}if(hands()==1){write_temp_date(0xcc);//跳过write_temp_date(0xbe);//读取温度数据tmpdelay(75);//500us// dema=250;// while(dema!=0);//500ms}date_l=read_temp_date();//读取低位温度date_h=read_temp_date();//读取高位温度all_date=((date_h<<4)|(date_l>>4));// 整数位// dot_date=date_l&0x0f;// dot_date=dot_date*625;//小数位// all_date=all_date+dot_date/10000;disp();//显示}}。
51单片机+ds1302+DS18b20温度时钟(电路图+C语言程序)

时钟电路图:*■11PCB板:酱时井務ft是用诵m-pdfMerisi 口叵因Fjr 齐舱 C :s ® 工细理沖缶皿ndm - * TfS ' 4' 包田U i > 'ir ft ZS:MZ fH钟些fl是用说町-Pdf Wirrcf闻礒雜sbit dis_ bitlsbit dis_ bit2sbit dis_ bit3sbit dis_ bit4sbit dis_ bit5sbit dis_ bit6sbit ledl _bitsbit led2 ! bit=P2A7; II定义数码管控制口=P2A6; II定义数码管控制口=卩2八4; II定义数码管控制口=卩2八3; II定义数码管控制口=P2A1; II定义数码管控制口=P2A0; II定义数码管控制口=P2A2; II定时LED勺控制口=P2A5; II定时LED勺控制口单片机程序:/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>訂开始 LJ-雲匕®务如1痒3月计ttVl. •呈T』d"吐拠席射■ w耳pg文宇■[豹…SS时軽件思冃说#define uehar #define uint unsigned char unsigned intsbit s1_bit =P1A 0; // 定义S1 控制口 sbit s2_bit =P01; // 定义 S2控制口 sbit s3_bit =P02; // 定义 S3控制口 sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据 sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t);//8US 延时基准程序void delay_50us(ui nt t); //void display1(uchar dis_data); void display2(uchar dis_data); void display3(uchar dis_data); void display4(uchar dis_data); void display5(uchar dis_data); void display6(uchar dis_data);void init_t0(); //定时器0初始化函数 void dis_led(); //LED 处理函数 void judge_s1(); //S1 按键处理函数void judge_s2(); //S2 按键处理函数 void judge_s3(); //S3 按键处理函数void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1); 示子程序 void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchar s1,uchar san); 〃闪烁显示子程序 void judge_dis(); //显示处理函数 void judge_clock(); // 显示处理函数 void set_ds1302(); // 设置时间void get_ds1302();// 读取当前时间void w_1byte_ds1302(uchar t); // 向 DS130写一个字节的数据 uchar r_1byte_ds1302(); // 从DS130读一个字节的数据//DS18B20测温函数定义延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序 //数码管4显示子程序 //数码管5显示子程序 //数码管6显示子程序//显 s2,ucharvoid w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};// 上电时默认的时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TRO =1;//// set_ds1302();〃设置DS1302勺初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timerO() interrupt 1{TH0=(65536-50000)/256;TL0=(65536 - 50000)%256; t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒{ _msec on d_co unt =0;sec on d_flag =1;}}}//**************************************************//显示处理函数void judge_dis(){if (flag1 ==0){if (second_flag ==1){ _zancun7 ++;sec on d_flag =0;} _if (zancun7 <1){if (temp_flag2 ==1){ 一readtemp_ds18b20(); // 读取温度temp_flag2 =0;厂dis_temp(); //温度显示函数}if (zancun7 >=1){temp_flag2 =1;zancun4 =hour_count &0xf0;zancun4 >>=4;zancun5 =minute_count&0xf0;zancun5 >>=4;zancun6 =sec on d_co unt&0xf0;zancun6 >>=4;dis(za ncun4 ,hour_co unt &0x0f,za ncun5,minu te_co unt &0x0f,za ncun 6,sec ond_ cou nt &0x0f);dis_led();if (zancun7 ==5)zancun7 =0;}}if (flag1 !=0){switch (flag1){case 1:dis(5,10,11,1,12,12); // 显示SET1led1_bit =1;led2_bit =1;break;case 2:dis(5,10,11,2,12,12); // 显示SET2break;case 3:dis(5,10,11,3,12,12); // 显示SET3break;case 4:dis(5,10,11,4,12,12); // 显示SET4break;case 5:dis(5,10,11,5,12,12); // 显示SET5break;case 6:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,1); break;case 7:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,2); break;case 8:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,3); break;case 9: //进入修改时间,时间分位个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,12,4); break;case 10: //进入修改闹钟,闹钟小时十位闪烁dis_san(zancunl / 10,zancunl %10,zancun2/ 10,zancun2 %0,12,zancun3,1); break;case 11://进入修改闹钟,闹钟小时个位闪烁dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,12,zancun3,2); break;case 12: //进入修改闹钟,闹钟小时十位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,3);break;case 13: //进入修改闹钟,闹钟小时个位闪烁dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,4);break;case 14: //进入修改闹钟的开关dis_sa n(zan cu n1 / 10,za ncun1 %10,za ncun 2/ 10,za ncu n2%0,12,za ncun 3,6);break;case 15:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,1);break;case 16:dis_san(zancun1 / 10,zancunl %10,zancun2/10,zancun2%0,zancun3/ 10,zancun3%10,2);break;case 17:dis_san(zancun1 / 10,zancunl %10,zancun2/ 10,zancun2%0,zancun3/ 10,zancun 3%10,3);break;case 18:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,4);break;case 19:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,5);break;case 20:dis_sa n(zancun1 / 10,za ncun1 %10,za ncun 2/ 10,za ncun 2%0,za ncun3/ 10,za ncun 3%10,6);break;case 21:if (second_flag ==1){ _sec on d_flag =0;countdown_second --;if (countdown_second ==255){ _coun tdow n_sec ond =59;countdown_minute --;if (countdown_minute ==255){ _coun tdow n_min ute =59;countdown_hour --;if (countdown_hour ==255){flag1 =22;coun tdow n_min ute =0;coun tdow n_hour =0;coun tdow n_sec ond =0;coun tdow n_flag=1;_ } } } }dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 22:{ speak =1;}dis(countdown_hour / 10,countdown_hour %10,countdown_minute / 10,countdown _minute%10,countdown_second/ 10,countdown_second%10); //break; case 23: dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break; case 24:if (msecond_flag ==1) { _msec on d_flag =0; msec on d_msec ond ++;if (msecond_msecon (==10){msec on d_msec ond =0; msec on d_sec ond ++;if (msecond_second==60) { _msecond_second =0; msec ond_minute ++;if (countdown_flag { _speak=0;if (second_flag { _sec on d_flag coun tdow n_flag} _ } else>0 &&countdown_flag <7)==1) =0; ++;if (msecond_minute==1OO) { _msec ond_minute =99;flagl =23;}}}}dis(msecond_minute / 10,msecond_minute%10,msecond_second/ 10,msecond_sec on d%10,mseco nd_msec on d%0,12);break;case 25:dis(zancun3 / 10,zancun3 %0,zancun2 / 10,zancun2 %10,zancun1 /10,zancun1 %0 );break;default :break;}}}//**************************************************〃S1按键处理函数void judge_s1(){ _s1_bit =1;//置IO为1,准备读入收据if (s1_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s1_bit ==0){switch (flag1){case 0:case 1:case 2:case 3:case 4:case 6:case 7:case 8:case 10:case 11:case 12:case 13:case 15:case 16:case 17:case 18:case 19: flag1++;break;case 9: flag1=6;break;case 14: flag1=10;break;case 20: flag1=15;break;case 5:case 21:case 22:case 23: //系统从秒表状态复位case 24: //系统从秒表状态复位case 25: //系统从计数器复位flag1 =0;break;default :break;}while (s1_bit ==0){ _judge_dis();}〃等待按键释放}}}〃************************************************** 〃S2按键处理函数void judge_s2(){ _s2_bit =1; //置IO为1,准备读入收据if (s2_bit ==0)//判断是否有按键按下=0;{delay_50us(1); //延时,去除机械抖动 if (s2_bit ==0) { switch (flagl) { flag1 =6; zancun4 =hour_count &0xf0;zancun4 >>=4; zancun6 =hour_count &0x0f;zancun1=zancun4*10+zancun6; //zancun 1=hour_co unt; zancun5 =minute_count &0xf0; zancun5 >>=4; zancun6 =minute_count &0x0f; zancun2 =za ncun5* 10+za ncun6; case 1: //在显示SET 状态下按S2牛,进入修改时间 // zancun2=minu te_co unt; break; case 2: //在显示SET2犬态下按S2,进入设置闹钟 zancunl =clock_hour; zancun2 =clock_m inu te; flagl =10; break; case 6: //修改时钟小时十位状态下按 case 7: //修改时钟小时个位状态下按 case 8: //修改时钟分钟十位状态下按 case 9: //修改时钟分钟个位状态下按 〃zancun4=za ncun 1/10; 测S:SM tab23[2] =zancun1/10* 16+za ncu n1%10; tab23[1] hour_c ount minu te_c ount sec ond_co unt tab23[0]set_ds1302(); flag1//zancun 5=za ncun2&0 xf0; //zancun 5>>=4; =zancun2/10* 16+za ncu n2%10; =tab23[2]; =tab23[1]; =0; //设置DS130的初始时间 =0;break; case 10: //修改闹钟小时十位状态下按S2case 11: //修改闹钟小时个位状态下按S2case 12: //修改闹钟分钟十位状态下按S2 case 13: //修改闹钟分钟个位状态下按S2 case 14: //修改闹钟使能状态下按S2clock_hour clock_m inute clock_e n flag1=zancun1; =zancun2; =zancun3;=0;break;case 3:flagl =15;zancunl =co un tdow n_hour;zancun2 =co un tdow n_minu te;zancun3 =co un tdow n_sec ond;break;case 15:case 16:case 17:case 18:case 19:case 20:coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flag1 =21;coun tdow n_flag =0;break;case 22:flag1 =21;break;case 21:flag1 =22;break;case 4:flag1 =23; //秒表暂停msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 23:flag1 =24;break;case 24:flag1 =23;break;case 5:flagl =25;//进入计数器模式zancunl =0;zancun2 =0;zancun3 =0;break; default :break;}while (s2_bit ==0){ _judge_dis();}//等待按键释放}}}//**************************************************//S3按键处理函数void judge_s3(){ _s3_bit =1;//置IO为1,准备读入收据if (s3_bit ==0)//判断是否有按键按下{delay_50us(1); //延时,去除机械抖动if (s3_bit ==0){ _switch (flag1){case 6: //修改时间小时的十位数zancun1 +=10;if (zancun1 >=24)zancun1 =zancun 1%10;break;case 7: //修改时间小时的个位数za ncun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 8: //修改时间分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60;break;case 9: //修改时间分钟的个位数za ncun2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 10: //修改闹钟小时的十位数zancunl +=10;if (zancunl >=24)zancunl =zancun 1%10; break;case 11: //修改闹钟小时的个位数zancunl =za ncu n1/10* 10+(za ncun1 %10+1) %10;if (zancun1 >=24)zancun1 =20;break;case 12: //修改闹钟分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 13: //修改闹钟分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 14:zancun3 A=1;break;case 15: //修改倒计时小时的十位数zancun1 +=10;if (zancun1 >=100)zancun 1 -=100; break;case 16: //修改倒计时小时的个位数zancun1 =za ncu n1/10* 10+(za ncun1 %10+1) %10;break;case 17: //修改倒计时分钟的十位数zancun2 +=10;if (zancun2 >=60)zancun2-=60; break;case 18: //修改倒计时分钟的个位数zan cu n2 =za ncun2/10* 10+(za ncun2 %10+1) %10;break;case 19: //修改倒计时秒的十位数zancun3 +=10;if (zancun3 >=60)zancun3-=60; break;case 20: //修改倒计时秒的个位数zan cu n3 =za ncun3/10* 10+(za ncun3 %10+1) %10;break;case 21:case 22: //coun tdow n_hour =zancun1;coun tdow n_minute =za ncun2;coun tdow n_sec ond =za ncun3;flagl =21;break;case 23:case 24: //秒表复位flag1 =24;msec ond_minute =0;msecond_second =0;msec on d_msec ond =0;break;case 25:zancun1 ++;if (zancun1 ==100){zancun1 =0;zancun2 ++;if (zancun2 ==100){zancun2 =0;zancun3 ++;}}break;default : break;}while (s3_bit ==0){ _judge_dis();}〃等待按键释放}}} //显示处理函数void judge_clock() {zancun4 =hour_count &0xf0;zancun4 >>=4;zancun6 =hour_count &0x0f;zancun4 *=10;zancun4 +=za ncun6;zancun5=minute_count &0xf0;if (san ==1){zancun5 >>=4;zancun6 =minute_count &0x0f;zancun5 *=10;zancun5 +=za ncun6;if (msecond_count<=5) {speak =0; speak_co unt ++;}else{speak =1;}}else{speak =1;}}〃****************************************////闪烁显示子程序void dis_sa n( uchar s6,uchar s5,uchar s4,uchar s3,uchars1,uchar san){if (clock_hour ==zancun4 &&clock_minute ==zancun5){ 一 一if (clock_en { _ speak_co unt clock_flag speak_co unt} _ } else{clock_flag =0;} _if{ (clock_flag ==1 ==1&&clock_flag ==0)=0; //开启蜂鸣器=1;=0;&&speak_count <400)s2,ucharif (msecond_count<5) { _ display1(s6);}}else{display1(s6);}if (san ==2){if (msecond_count<5) { _ display2(s5);}}else{display2(s5);}if (san ==3){if (msecond_count<5) { _ display3(s4);}}else{display3(s4);}if (san ==4){if (msecond_count<5) { _ display4(s3);}}else{display4(s3);}if (san ==5){if (msecond_count<5){ _ display5(s2);}}else{display5(s2);}if (san ==6){if (msecond_count<5){ _ display6(s1);}}else{ display6(s1);}}〃****************************************//时钟显示程序void dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1) { display1(s6);display2(s5);display3(s4);display4(s3);display5(s2);display6(s1);}〃********************************************************************************************void init_tO(){ _TMOD0x01;〃设定定时器工作方式1,定时器定时50毫秒TH0=(65536-50000)/256;TL0=(65536- 50000)%256;EA=1; //开总中断ET0=1; //允许定时器0中断t0_crycle =0; //定时器中断次数计数单元}//LED处理函数void dis_led(){if (msecond_count<5){ _Ied1_bit =1;Ied2_bit =1;}else{led1_bit =0;led2_bit =0;}}〃***************************************************************//功能:把数据1显示在数码管1上void display6(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit6 =0; // 锁存数据delay_50us(40); dis_bit6 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display5(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit5 =0; // 锁存数据delay_50us(40);dis_bit5 =1;} _〃***************************************************************//功能:把数据1显示在数码管1上void display4(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit4 =0; // 锁存数据delay_50us(40);dis_bit4 =1;} 〃***************************************************************//功能:把数据1显示在数码管1上void display3(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit3 =0; // 锁存数据delay_50us(40);dis_bit3 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display1(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit1 =0; // 锁存数据delay_50us(40);dis_bit1 =1;}〃***************************************************************//功能:把数据1显示在数码管1上void display2(uchar dis_data){ _smg_data =tabl1[dis_data]; // 送显示断码dis_bit2 =0; // 锁存数据delay_50us(40);dis_bit2 =1;}〃******************************************************************* *******************************// 函数名称:void delay_50US(unsigned int t)//功能:延时50*t(us)void delay_50us(uint t){ _unsigned char j;for (;t >0;t --){for (j =19;j >0;j --);}}〃******************************************************************* ************〃8微秒延时基准程序void delay_8us(uint t){while (-- t);}************〃3微秒延时程序void delay_3us() {}〃******************************************************************* ************//子程序功能:向DS18B2写一字节的数据void w_1byte_ds18b20(uchar value){uchar i =0;for (i =0;i <8;i ++){dq_ds18b20 =1;delay_3us();dq_ds18b20 =0; delay_8us(2);if ( value & 0x01) dq_ds18b20 =1; 〃DQ = 1 delay_50us(1); // 延时50us 以上delay_8us(2);value >>=1;}dq_ds18b20 =1; //DQ = 1}//读一个字节uchar r_1byte_ds18b20( void){ 一一uchar i =0;uchar value = 0;for (i =0;i <8;i ++){value >>=1;dq_ds18b20 =0;// DQ_L;delay_3us();dq_ds18b20 =1; 〃DQ_H;delay_8us(2);if (dq_ds18b20==1) value |= 0x80;delay_8us(6); // 延时40us}dq_ds18b20 =1;return value ;}11 ・**************************************************〃ds18b20复位子程序void rest_ds18b20( void){rest:delay_3us(); // 稍做延时delay_3us();dq_ds18b20 =1;delay_3us();dq_ds18b20 =0;// DQ_L; delay_50us(11); 〃480us<T<960usdq_ds18b20 =1; // 拉高总线delay_8us(5);if (dq_ds18b20==1){return ;}delay_50us(2); // 延时90usif (dq_ds18b20==1){return ;}else{goto rest;}}〃****************************************************//读取温度void readtemp_ds18b20( void){ _uchar temp32;rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0x44); // 启动温度转换delay_8us(2);rest_ds18b20();w_1byte_ds18b20(0xcc); //跳过读序列号的操作w_1byte_ds18b20(0xbe); //读取温度寄存器等(共可读9个寄存器)前两个就是温度templ =r_1byte_ds18b20();temph =r_1byte_ds18b20();if ((temph &0xf0)) //判断温度的正负性{temp_flag =0; //温度为负数标志temph =-temph;tempi =-templ;t_x =tabl3[templ & OxOf]; // 计算温度的小数temp32 =temph & OxOf;temp32 <<=4;tempi >>=4;temp32 =temp32 | tempi;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据5else //为正数{t_x =tabl3[templ & 0x0f]; // 计算温度的小数temp32 =temph & 0x0f;temp32 <<=4;templ >>=4;temp32 =temp32 | templ;t_b =temp32/100%10; //计算温度的百位数据t_s =temp32/10%0;〃计算温度的十位数据t_g =temp32%0;〃计算温度的个位数据temp_flag =1;} _}void dis_temp() //温度显示函数{ _if (temp_flag =1){ _if (t_b ==0){dis(12,12,t_s,t_g,13,12);}else{dis(12,t_b,t_s,t_g,13,12);}}else{dis(14,t_b,t_s,t_g,13,12);}}/ / """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ############ //;子程序名:w_1byte_ds1302//;功能:向DS130写一个字节的数据void w_1byte_ds1302(uchar t){uchar i;for (i =0;i <8;i ++){if (t & 0x01){io_ds1302=1;}else{io_ds1302 =0;}clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();delay_3us();t >>=1;}}/ / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ######//;子程序名:r_1byte_ds1302()//;功能:从DS130读一个字节的数据uchar r_1byte_ds1302(){ 一一uchar i,temp11 =0;io_ds1302 =1;//置10为1,准备读入数据for (i =0;i <8;i ++){temp11 >>=1;if (io_ds1302) temp11 |= 0x80;clk_ds1302 =1;delay_3us();delay_3us();clk_ds1302 =0;delay_3us();}return (temp11);}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""/ / , JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ JJ """""""""""""""ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff//;子程序名:setbds1302//;功能:设置DS130初始时间,并启动计时void set_ds1302(){uchar i,j;rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); // 写控制命令字delay_3us();w_1byte_ds1302(0x00); // 写保护关闭clk_ds1302 =1;delay_3us();for (i =0,j =0x80;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(j);delay_3us();w_1byte_ds1302(tab23[i]);delay_3us();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();delay_3us();} _rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();rest_ds1302 =1;delay_3us();w_1byte_ds1302(0x8e); delay_3us();w_1byte_ds1302(0x80); clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();}/ / """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" / / , ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff //;子程序名:get1302void get_ds1302(){ _uchar temp11[7],i,j;for (i =0;i <7;i ++){temp11[i] =0;}for (i =0,j =0x81;i <7;i ++,j +=2){rest_ds1302 =0;delay_3us();clk_ds1302 =0;delay_3us();delay_3us();w_1byte_ds1302(j);temp11[i] =r_1byte_ds1302();delay_3us();clk_ds1302 =1;delay_3us();rest_ds1302 =0;delay_3us();} _if (temp11[0] != 0xff){second_count =temp11[0]; }if (temp11[1] != 0xff) // 数据验证{minute_count =temp11[1]; }if (temp11[2] != 0xff) // 数据验证{hour_count =temp11[2]; }// date=temp[3];//mon th=temp[4];// week=temp[5];//year=temp[6];}/*===================================================================调试要求:1. MCU:AT89S52 芯片或AT89C522. 晶振:12MHz功能:多功能时钟+温度计/#inelude <reg52. h>#inelude vintrins . h>sbit dis_bit1 =P2A 7; //定义数码管控制口sbit dis_bit2 =卩2八6;//定义数码管控制口sbit dis_bit3 =卩2八4;//定义数码管控制口sbit dis_bit4 =卩2八3;//定义数码管控制口sbit dis_bit5 =卩2八1; //定义数码管控制口sbit dis_bit6 =P2A0; //定义数码管控制口sbit led1_bit =卩2八2; // 定时 LED 勺控制口sbit led2_bit =卩2八5; // 定时 LED 勺控制口sbit s1_bit =P1A0; // 定义S1 控制口sbit s2_bit =P01; // 定义 S2空制口sbit s3_bit =P02; // 定义 S3控制口sbit dq_ds18b20 =P3A3;// 定义控制 DS18B20 sbit speak =P3A7; //定义蜂鸣器控制口sbit clk_ds1302 =P3A6; // 定义控制 DS1302勺时钟线 sbit io_ds1302 =P3A5;//定义控制DS1302勺串行数据sbit rest_ds1302 =P3A4;#define smg_data P0 //定义数码管数据口 void delay_3us(); //3US 的延时程序 void delay_8us(ui nt t); //8US 延时基准程序void delay_50us(ui nt t); // void display1(uehardis_data); voiddisplay2(uehar dis_data); void display3(uehar dis_data); void display4(uehar dis_data); void display5(uehar dis_data); void display6(uehar dis_data);void init_t0(); //定时器0初始化函数void dis_led(); //LED 处理函数void judge_s1();//S1 按键处理函数 void judge_s2(); //S2 按键处理函数void judge_s3(); //S3 按键处理函数 void dis(uehar s6,uehar s5,uehar s4,uehar s3,uehar s2,uehar s1); 示子程序 void dis_sa n( uchar s6,uehar s5,uehar s4,uehar s3,uehars1,uchar san); 〃闪烁显示子程序void judge_dis(); //显示处理函数void judge_clock(); // 显示处理函数void set_ds1302(); // 设置时间void get_ds1302(); // 读取当前时间#define uehar#define uintunsigned char unsigned int延时50*T 微妙函数的声明//数码管1显示子程序 //数码管2显示子程序 //数码管3显示子程序//数码管4显示子程序//数码管5显示子程序//数码管6显示子程序 //显s2,ueharvoid w_1byte_ds1302(uchar t); // 向DS130写一个字节的数据uchar r_1byte_ds1302(); // 从DS130读一个字节的数据〃*******************************************************************//DS18B20测温函数定义void w_1byte_ds18b20(uchar value); // 向DS18B2写一个字节ucharr_1byte_ds18b20( void ); // 从DS18B2读取一个字节的数据voidrest_ds18b20( void ); //DS18B20复位程序void readtemp_ds18b20( void ); // 读取温度void dis_temp(); //温度显示函数//共阳数码管断码表const uchar tabl1[16] ={ 0xc0,0xf9,0xa4,0xb0,0x99,0x92,// 0 1 2 3 4 50x82,0xf8,0x80,0x90,0x86,0x87,0xFF,//6 7 8 9 E T B0xc6,0xbf,0xff };// C -const uchar tabl3[] ={ 0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09 };uchar t0_crycle;uchar hour_co un t, minu te_c oun t,sec on d_co un t,msec ond_count;uchar clock_hour,clock_m inu te;uchar coun tdow n_sec ond;uchar coun tdow n_hour,co un tdow n_min ute;uchar clock_en; //闹钟关闭和开启的标志,1开启,0关闭uchar flag1,sec on d_flag,za ncun 1,za ncun 2,za ncun3;uchar zancun4 ,za ncun 5,za ncun 6,za ncun7;uchar clock_flag,co un tdow n_flag;uchar msec on d_mi nute,msec on d_sec on d,mseco nd_mseco nd,mseco nd_flag; // 秒表相关参数uint speak_c ount;uchar templ,temph,temp_flag;uchar t_b,t_s,t_g,t_x,temp_flag2; //从左到右分别存储温度百位,十位,个位,小数位上电时默认的uchar tab23[3]; 〃二{0x40,0x59,0x23,0x28,0x11,0x06,0x09};//时间//主程序void main(){P3 =0x00;flag1 =0;zancun3 =0;msecond_minute =0; //置秒表相关参数为0msecond_second =0;msec on d_msec ond =0;speak =1;//关闭蜂鸣器speak_co unt =0;clock_hour =0;clock_m inute =0;clock_flag =0;countdown_flag =0; //倒计时标志位为0clock_en =0;//开机时默认关闭闹钟ini t_t0();TR0 =1;//// set_ds1302();〃设置DS130的初始时间//接下来开始编写让数码管显示的程序while (1){get_ds1302();judge_dis(); // 显示处理judge_s1();judge_s2();judge_s3();judge_clock(); //闹钟处理程序} _}void timer0() interrupt 1{TH0=(65536-50000)/256;TL0=(65536- 50000)%256;t0_crycle ++;if (t0_crycle ==2) // 0.1 秒{t0_crycle =0;msec on d_flag =1;msec ond_count ++;if (msecond_count==10)//1 秒。
基于单片机的带温度显示的数字钟设计(c51语言编程)【开题报告】

开题报告电气工程及其自动化基于单片机的带温度显示的数字钟设计(c51语言编程)一、课题研究意义及现状1980年因特尔公司推出了MCS-51单片机,近30年来,其衍生系列不断出现,从Atmel加入FLASH ROM,到philips加入各种外设,再到后来的Cygnal推出C8051F,使得以8051为核心的单片机在各个发展阶段的低端产品应用中始终扮演着一个重要的角色,其地位不断升高,资源越来越丰富,历经30年仍在生机勃勃地发展,甚至在SoC时代仍占有重要的一席之地。
单片机具有体积小、功能强、低功耗、可靠性高、价格低廉等一系列优点,不仅已成为工业测控领域智能仪表、机电一体化、实时控制、国防工业普遍采用的智能化控制工具,而且已渗入到人们工作和和生活的各个角落,有力地推动了各行业的技术改造和产品的更新换代,应用前景广阔。
C语言已经成为当前举世公认的高效简洁而又贴近硬件的编程语言之一。
将C语言向单片机8051上移植十余20世纪80年代的中后期,经过几十年的努力,C语言已成为专业化单片机上的实用高级语言。
C语言是一种编译型程序设计语言,它兼顾了多种高级语言的特点,并具备汇编语言的功能。
此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。
与汇编语言相比,C51在功能、结构、可读性、可维护性上有明显的优势,因而易学易用。
另外C51可以缩短开发周期,降低成本,可靠性,可移植性好。
因此,使用C语言进行程序设计已成为软件开发的一个主流,用C语言进行8051单片机程序设计是单片机开发与应用的必然趋势。
随着人们生活水平的提高,对物质需求也越来越高,人们已不再满足于钟表原先简单的报时功能,希望出现一些新的功能,诸如环境温度显示、日历的显示、重要日期倒计时、显示跑表功能等,用以带来更大的方便。
而所有这些,又都是以数字化的电子时钟为基础的,不仅应用了数字电路技术,而且还加入了需要模拟电路技术和单片机技术。
基于51单片机的简易电子钟设计

基于51单片机的简易电子钟设计一、设计目的现代社会对于时间的要求越来越精确,电子钟成为家庭和办公场所不可缺少的设备之一、本设计基于51单片机,旨在实现一个简易的电子钟,可以显示当前的时间,并且能够通过按键进行时间的调整和设置闹钟。
二、设计原理本设计主要涉及到51单片机的IO口、定时器、中断、LCD显示技术等方面知识。
1.时钟模块时钟模块采用定时器0的中断进行时间的累加和更新。
以1秒为一个时间单位,每当定时器0中断发生,就将时间加1,并判断是否需要更新小时、分钟和秒的显示。
同时,根据用户按键的操作,可以调整时间的设定。
2.显示模块显示模块采用16x2字符LCD显示屏,通过51单片机的IO口与LCD连接。
可以显示当前时间和设置的闹钟时间。
初次上电或者重置后,LCD显示时间为00:00:00,通过定时器中断和键盘操作,实现时间的更新和设定闹钟功能。
3.键盘模块键盘模块采用矩阵键盘连接到51单片机的IO口上,用于用户进行时间的调整和设置闹钟。
通过查询键盘的按键状态,根据按键的不同操作,实现时间的调整和闹钟设定功能。
4.中断模块中断模块采用定时器0的中断,用于1秒的定时更新时间。
同时可以添加外部中断用于响应用户按键操作。
三、主要功能和实现步骤1.系统初始化。
2.设置定时器,每1秒产生一次中断。
3.初始化LCD显示屏,显示初始时间00:00:00。
4.查询键盘状态,判断是否有按键按下。
5.如果按键被按下,根据不同按键的功能进行相应的操作:-功能键:设置、调整、确认。
-数字键:根据键入的数字进行时间的调整和闹钟设定。
6.根据定时器的中断,更新时间的显示。
7.判断当前时间是否与闹钟设定时间相同,如果相同,则触发闹钟,进行提示。
8.循环执行步骤4-7,实现连续的时间显示和按键操作。
四、系统总结和改进使用51单片机设计的简易电子钟可以显示当前时间,并且实现时间的调整和闹钟设定功能。
但是由于硬件资源有限,只能实现基本的功能,不能进行其他高级功能的扩展,例如闹铃的音乐播放、温度、湿度的显示等。
基于STC89C52单片机时钟的设计与实现

基于STC89C52单片机时钟的设计与实现1. 本文概述本文主要介绍了基于STC89C52单片机和DS1302时钟芯片的电子时钟设计与实现。
该电子时钟系统具有年月日等基本时间显示功能,并集成了秒表计时处理、闹钟定时、蜂鸣器和温度显示等附加功能。
系统采用LCD1602作为液晶显示器件,通过单片机对时钟和温度等数据进行处理后传输至LCD进行显示。
用户可以通过按键对时间进行调节,同时,单片机还通过扩展外围接口实现了温度采集等功能。
本文的目标是提供一个功能丰富、易于操作的电子时钟系统,为学习和应用单片机技术提供一个实用的案例。
2. 系统设计要求在设计基于STC89C52单片机的时钟系统时,我们需要考虑以下几个关键的设计要求:时钟系统必须具备基本的时间显示功能,能够以小时、分钟和秒为单位准确显示当前时间。
系统还应支持设置闹钟功能,允许用户设定特定的时间点进行提醒。
系统需要保证长时间稳定运行,具备良好的抗干扰能力,确保在各种环境下都能准确计时。
还应具备一定的容错能力,即使在操作失误或外部干扰的情况下,也能保证系统的正常运行。
用户界面应简洁直观,便于用户快速理解和操作。
时钟的显示部分应清晰可见,即使在光线较暗的环境下也能保持良好的可视性。
同时,设置和调整时间的操作应简单易懂,方便用户进行日常使用。
在设计时钟系统时,应考虑到未来可能的功能扩展,如温度显示、日期显示等。
系统的设计应具有一定的灵活性和扩展性,以便在未来可以轻松添加新的功能模块。
鉴于时钟系统可能需要长时间运行,能耗是一个重要的考虑因素。
设计时应选择低功耗的元件,并优化电源管理策略,以延长电池寿命或减少能源消耗。
在满足上述所有要求的同时,还需要控制成本,确保产品的市场竞争力。
这可能涉及到对单片机的编程优化、选择性价比高的外围元件等措施。
通过满足上述设计要求,我们可以确保开发出一个功能完善、稳定可靠、用户友好、易于扩展、节能环保且成本效益高的STC89C52单片机时钟系统。
电子时钟温度计使用说明书

电子时钟温度计DIY套件使用说明书
作者:张卫兵 时间:2010.1.27
本套DIY套件专为业余电子爱好者制作,DIY简单实用,成本低。
产品如图所示:
上图为空板。
焊好的成品板。
功能说明:
本套件程序已经烧好,单片机数字时钟温度计DIY,掉电切换到备用电池,无需重新设置时间,显示完整的日历和温度
时间:24小时制显示。
秒:计时由小数点闪烁 精确定时一秒散动一次
温度:显示精确到0.1度
日历:月份和日期显示,年份,月份自动控制
功能按键:K2为设置动能键,可以设定时间,日期,星期等 K3和K4分别为加一和减一功能键。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
单片机时钟显示+温度显示————————————————————————————————作者:————————————————————————————————日期:南华大学计算机技术综合课程设计报告学院:湘南学院题目:单片机LCD时钟显示和温度测量学生姓名:专业班级:指导老师:教研室主任:2012年6月29日一、概述:本次设计的LCD时钟显示和温度测量系统是由中央控制器、温度检测器、时钟系统、显示器及键盘部分组成。
控制器采用单片机STC89C51RC,温度检测部分采用DS18B20温度传感器,时钟系统用时钟芯片DS1302,用LCD液晶1602作为显示器,用蜂鸣器构成闹铃模块。
单片机通过时钟芯片DS1302获取时间数据,对数据处理后显示时间;温度传感器DS18B20采集温度信号送该给单片机处理;单片机再把时间数据和温度数据送液晶显示器1602显示;键盘是用来调整时间的。
二、方案设计及方案论证1. 时钟显示和温度测量的总体设计思路按照系统的设计功能要求,本时钟显示和温度测量系统的设计必须采用单片机软件系统实现,用单片机的自动控制能力配合按键控制,来控制时钟、温度的调整及显示。
获得时钟显示和温度测量数据信息,单片机对其进行一系列的处理,最后通过液晶显示出来。
2.时钟显示和温度测量系统方案论证2.1时钟系统方案选择方案1:通过单片机内部的定时器/计数器,用软件实现,直接用单片机的定时器编程以实现时钟;方案2:用专门的时钟芯片实现时钟的记时,再把时间数据送入单片机,由单片机控制显示。
虽然用软件实现时钟硬件线路简单,但是程序运行的每一步都需要时间,多一步或少一步程序都会影响记时的准确度,对定时器定时也不是十分准确,时钟精度很低,对于我们实现所需要的功能造成软件编程非常复杂。
用专用时钟芯片硬件成本相对较高,但它的精度很高,软件编程很简单。
综上所述,选择方案2。
本次设计采用具有涓细电流充电能力的低功耗实时时钟电路DS1302。
它可以对年、月、日、周日、时、分、秒进行计时,且具有闰年补偿等多种功能。
它采用主电源和备用电源双电源供电。
它的工作电压范围2.0~5.5V,在2.2V时,小于300nA。
它内部含有31个字节的静态RAM,可提供用户访问。
DS1302可以对年、月、日、周日、时、分、秒进行计时,可以达到我们设计的基本的要求。
内部的寄存器为我们调时,闹钟定时提供了寄存空间。
备用用电源也实现了当系统断电后,时钟仍然可以保持。
而且它是串行接口,与单片机通信所需要的接口少。
2.2 显示系统的方案比较方案1:用数码管或LED显示。
方案2:用液晶1602显示。
方案3:用液晶12864显示。
时钟和温度的显示可以用数码管或LED,而且价格便宜。
但是数码管的只能显示简单的设计的系统,与我们设计要求也不相符。
有很多东西需要显示,还是用显示功能更好的液晶显示器比较好,它能显示更多的数据,用12864显示略想复杂,用1602液晶显示可以完全满足本次设计的数据显示要求。
2.3 温度系统方案选择方案1:用热敏电阻等测温元件测出电压,再转换成对应的温度。
需要比较多的外部元件支持,且硬件电路复杂,制作成本相对较高。
方案2:用DS18B20直接测温。
DS18B20温度传感器是美国DALLAS半导体公司最新推出的一种改进型智能温度传感器,它能直接读出被测温度,并且可根据实际要求通过简单的编程实现9~12位的数字值读数方式。
经比较,我们选择方案2。
温度实现只能通过外部的温度传感器来实现。
经上网查阅,DS18b20体积小,只有3只脚,电路接法简单。
精度为0.5°C,也符合我们设计的要求。
DS18B20也是我们通常使用的型号,因此温度传感器用DS18B20。
2.4 键盘控制方案选择方案1:购买集成键盘,采用矩阵形式连接。
方案2:购买单个复位开关做成键盘。
虽然集成键盘美观,与单片机的接口少,但是它的成本比较高。
单片机的IO口对于我们的设计绰绰有余。
通常我们选用价格便宜单个复位开关做成键盘。
3.时钟显示和温度测量系统总体设计初步确定设计系统由单片机主控模块、时钟模块、测温模块、闹铃模块、显示模块、键盘接口模块共6个模块组成,电路系统框图如下图所示。
图1:电路系统框图 三、硬件电路单元设计 1、单片机最小系统设计1.1复位电路:复位电路有两种方式:上电复位和按钮复位,我们主要用按钮复位方式。
如下图所示:图2:复位电路1.2 晶振电路晶振电路选取条件:晶振12M ,电容20pF 到30pF ,本电路选取20pF 。
晶振电路原理如下图:主 控 器件DS18B20 温度采集系统DS1320 时间采集系统1602显示系统蜂鸣器 闹铃系统键盘控制系统图3:晶振电路2、时钟系统设计DS1302时钟电路晶振选用3.2678KHZ,原理图如下:图4:基于ds1302时钟系统设计电路3、温度系统设计DS18B20温度传感DQ端接单片机P1.3口,电路原理图如下:图5:基于DS18b20温度系统设计电路4、液晶显示系统设计1602液晶显示电路由1K电阻和10K的精密电阻组成,控制端接P1.0、P1.1、P1.2口,数据端接P2口,电路图如下:图6:液晶1602显示电路把15脚的10K电阻改成1K电阻5、蜂鸣器系统设计蜂鸣器闹铃电路由蜂鸣器跟1K限流电阻组成,电路图如下:图7:蜂鸣器电路6、电源模块本系统采用USB供电,用发光二极管显示通电状况,电源电源电路如下:图8:电源电路7、时间调节模块本系统采用3个按键调节时间。
S1是菜单键,选择要调节的位;S2按一下表示加一;S3按一下表示减一。
电路如下:图9:时钟调节电路四、软件调试1、程序流程图如下:图10:程序流程图2、程序见附录五、硬件调试1、原理图如下:图11:总原理图2、PCB图如下:图12:PCB图其中红色部分为跳线;3、实物测试板子制作完成后上电测试发现电源灯没有显示,用万用表测量之后发现精密电阻接线错误,导致VCC与GND直接连通。
修正之后发现电源指示灯还是没有亮,测量USB两端电压为-4.88V,卸掉USB口,插上排针用杜邦线连接单片机的VCC和GND之后,电源灯能够点亮,液晶能够驱动,但是亮度不够。
测量液晶两端的电压发现只有2.5V,用导线将液晶背光的VCC直接接上电源VCC 后,液晶亮度正常。
将程序下载之后经过几次调试和修改,最终实现了想要达到的效果。
六、总结与体会在开始本次课程设计前花费了十多天的时间认真学习了单片机,通过书本和视频的学习,对单片机有了进一步的掌握并学会C51编程的一些方法。
这对于完成本次课程设计提供了很大的帮助。
从这次的课程设计中,我真真正正的意识到,在写程序时,逻辑思维要清晰,要有耐心。
同时要巧妙的利用C语言的可移植性,这对写程序有很大的帮助。
参考文献:1.郭天祥单片机学习板配套资料2.《51单片机C语言教程》郭天祥主编电子工业出版社3.《C语言程序设计》尹业安,白燕主编国防科技大学出版社4.《单片机原理与应用及C51程序设计》谢维成杨加国主编清华大学出版社程序如下:#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define LCDIO P2sbit DQ=P1^3;//ds18b20与单片机连接口sbit rs=P1^0;sbit rd=P1^1;sbit lcden=P1^2;sbit acc0=ACC^0; //移位时的第0位sbit acc7=ACC^7; //移位时用的第7位uchar second,minute,hour,day,month,year,week,count=0;uchar ReadValue,num,time;uint tvalue;//温度值uchar tflag;uchar code table[]={" 2012-06-29 FIR"};uchar code table1[]={" 08:45:00 000.0C"};uchar code table2[]= "FRISATSUNMONTUEWESTUR";uchar data disdata[5];sbit DATA=P0^1; //时钟数据接口sbit RST=P0^2;sbit SCLK=P0^0;sbit menu=P3^5; //菜单sbit add=P3^6; //加一sbit dec=P3^7; //减一void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void delay1(uint z){for(;z>0;z--);}void write_com(uchar com) //lcd写命令指令:RS=L,RW=L, D0~D7=指令码,E=高脉冲{rs=0;rd=0;lcden=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date) //lcd写数据指令:RS=H,RW=L, D0~D7=数据,E=高脉冲{rs=1;rd=0;lcden=0;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void init(){uchar num;lcden=0;write_com(0x38); //显示模式设置,默认为0x38,不用变。
write_com(0x0c); //显示功能设置0x0f为开显示,显示光标,光标闪烁;0x0c为开显示,不显光标,光标不闪write_com(0x06); //设置光标状态默认0x06,为读一个字符光标加1.write_com(0x01); //显示清屏,将上次的内容清除,默认为0x01.write_com(0x80); //设置初始化数据指针,是在读指令的操作里进行的delay(5);write_com(0x80); //初始化显示时间(table table1中的内容)for(num=0;num<15;num++){write_date(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<15;num++){write_date(table1[num]);delay(5);}}void Write1302(uchar dat) //写8bit数据{uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备delay1(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续写8个二进制位数据{DATA=dat&0x01; //取出dat的第0位数据写入1302delay(2); //稍微等待,使硬件做好准备SCLK=1; //上升沿写入数据delay1(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位}}void WriteSet1302(uchar Cmd,uchar dat) //向cmd相应地址中写入一个字节的数据{RST=0; //禁止数据传递SCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输delay1(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302(dat); //写数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递}uchar Read1302(void) //读8bit数据{uchar i,dat;delay(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据{dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位if(DATA==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位SCLK=1; //将SCLK置于高电平,为下降沿读出delay1(2); //稍微等待SCLK=0; //拉低SCLK,形成脉冲下降沿delay1(2); //稍微等待}return dat; //将读出的数据返回}uchar ReadSet1302(uchar Cmd) //从cmd相应地址中读一个字节的数据{uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输Write1302(Cmd); //写入命令字dat=Read1302(); //读出数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat; //将读出的数据返回}void Init_DS1302(void){WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值WriteSet1302(0x82,((45/10)<<4|(45%10))); //根据写分寄存器命令字,写入分的初始值WriteSet1302(0x84,((8/10)<<4|(8%10))); //根据写小时寄存器命令字,写入小时的初始值WriteSet1302(0x86,((29/10)<<4|(29%10))); //根据写日寄存器命令字,写入日的初始值WriteSet1302(0x88,((6/10)<<4|(6%10))); //根据写月寄存器命令字,写入月的初始值WriteSet1302(0x8c,((12/10)<<4|(12%10))); // 根据写年寄存器命令字,写入年的初始值WriteSet1302(0x8a,((1/10)<<4|(1%10))); // 根据写星期寄存器命令字,写入星期的初始值}void DisplaySecond(uchar x) //显示秒{uchar i,j;i=x/10;j=x%10;write_com(0xc7);write_date(0x30+i);write_date(0x30+j);}void DisplayMinute(uchar x) //显示分{uchar i,j;i=x/10;j=x%10;write_com(0xc4);write_date(0x30+i);write_date(0x30+j);}void DisplayHour(uchar x) //显示小时{uchar i,j;i=x/10;j=x%10;write_com(0xc1);write_date(0x30+i);write_date(0x30+j);}void DisplayDay(uchar x) //显示日期、天{uchar i,j;i=x/10;j=x%10;write_com(0x89);write_date(0x30+i);write_date(0x30+j);}void DisplayMonth(uchar x) //显示日期、月{uchar i,j;i=x/10;j=x%10;write_com(0x86);write_date(0x30+i);write_date(0x30+j);}void DisplayYear(uchar x) //显示日期、年{uchar i,j;i=x/10;j=x%10;write_com(0x83);write_date(0x30+i);write_date(0x30+j);}void DisplayWeek(uchar x) //显示星期{ uchar i;x=x*3;write_com(0x8c);for(i=0;i<3;i++){write_date(table2[x]);x++;}}void read_date(void){ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //从DS1302读取时间秒ReadValue = ReadSet1302(0x83);minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //从DS1302读取时间分ReadValue = ReadSet1302(0x85);hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //从DS1302读取时间小时ReadValue = ReadSet1302(0x87);day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //从DS1302读取日期日ReadValue = ReadSet1302(0x89);month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //从DS1302读取日期月ReadValue = ReadSet1302(0x8d);year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //从DS1302读取日期年ReadValue=ReadSet1302(0x8b);week=ReadValue&0x07; //从DS1302读星期DisplaySecond(second); // 显示秒、分、小时、天、月、年、星期DisplayMinute(minute);DisplayHour(hour);DisplayDay(day);DisplayMonth(month);DisplayYear(year);DisplayWeek(week);}void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num) //刷新时间(将改变的时间显示到LCD上){newval=ReadSet1302(newaddr);//读取当前时间newval=((newval&0x70)>>4)*10+(newval&0x0f); //将bcd码转换成十进制if(flag) //判断是加一还是减一{newval++;switch(s1num){ case 1: if(newval>99) newval=0;DisplayYear(newval);break;case 2: if(newval>12) newval=1;DisplayMonth(newval);break;case 3: if(newval>31) newval=1;DisplayDay(newval);break;case 4: if(newval>6) newval=0;DisplayWeek(newval);break;case 5: if(newval>23) newval=0;DisplayHour(newval);break;case 6: if(newval>59) newval=0;DisplayMinute(newval);break;case 7: if(newval>59) newval=0;DisplaySecond(newval);break;default:break;}}else{newval--;switch(s1num){ case 1: if(newval==0) newval=99;DisplayYear(newval);break;case 2: if(newval==0) newval=12;DisplayMonth(newval);break;case 3: if(newval==0) newval=31;DisplayDay(newval);break;case 4: if(newval<0) newval=6;DisplayWeek(newval);break;case 5: if(newval<0) newval=23;DisplayHour(newval);break;case 6: if(newval<0) newval=59;DisplayMinute(newval);break;case 7: if(newval<0) newval=59;DisplaySecond(newval);break;default:break;}}WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10)); //将新数据写入寄存器}void key_scan(void) //键盘扫描程序{ uchar miao,s1num=0;if(menu==0){delay(5);if(menu==0){while(!menu);s1num++;while(1){if(menu==0){delay(5);if(menu==0){while(!menu);s1num++;}}rd=0;miao=ReadSet1302(0x81);second=miao;WriteSet1302(0x80,miao|0x80);write_com(0x0f);//光标闪射if(s1num==1){ year=ReadSet1302(0x8d);write_com(0x80+4); //年光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(year,1,0x8d,1);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(year,0,0x8d,1);}}}if(s1num==2){month=ReadSet1302(0x89);write_com(0x80+7); //月光标{delay(3);if(add==0){ while(!add);turn_val(month,1,0x89,2);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(month,0,0x89,2);}}}if(s1num==3){ day=ReadSet1302(0x87);write_com(0x80+10);//日光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(day,1,0x87,3);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(day,0,0x87,3); //写入日寄存器}}}if(s1num==4){ week=ReadSet1302(0x8b);write_com(0x80+14); //星期光标if(add==0){delay(3);if(add==0)turn_val(week,1,0x8b,4);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(week,0,0x8b,4);}}}if(s1num==5){ hour=ReadSet1302(0x85);write_com(0x80+0x40+2); //时光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(hour,1,0x85,5);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(hour,0,0x85,5);}}}if(s1num==6) //调时间分{ minute=ReadSet1302(0x83);write_com(0x80+0x40+5);if(add==0){delay(5);if(add==0){ while(!add);turn_val(minute,1,0x83,6); //写入分寄存器}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(minute,0,0x83,6); //写入分寄存器}}}if(s1num==7)//调时间秒{ second=ReadSet1302(0x81);write_com(0x80+0x40+8);//秒光标if(add==0){delay(3);if(add==0){ while(!add);if(second==0x60)second=0x00;turn_val(second,1,0x81,7);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(second,0,0x81,7);}}}if(s1num==8){ miao=ReadSet1302(0x81);second=miao;WriteSet1302(0x80,second&0x7f);s1num=0;//s1num清零write_com(0x0c);//光标不闪烁break;}}}}}void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst() //ds1820复位{ unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()///读数据{ unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)//写数据{unsigned char i=0;for (i=8; i>0; i--){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp()//读取温度值并转换{uchar a,b;ds1820rst();ds1820wr(0xcc);//跳过读序列号ds1820wr(0x44);//启动温度转换ds1820rst();ds1820wr(0xcc);//跳过读序列号ds1820wr(0xbe);//读取温度a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue);}void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}write_com(0xc9);write_date(flagdat);//显示符号位write_com(0xca);write_date(disdata[0]);//显示百位write_com(0xcb);write_date(disdata[1]);//显示十位write_com(0xcc);write_date(disdata[2]);//显示个位write_com(0xcd);write_date(0x2e);//显示小数点write_com(0xce);write_date(disdata[3]);//显示小数位write_com(0xcf);write_date('C');}void main(){init(); //初始化显示Init_DS1302(); //将1302初始化read_temp(); //读取温度ds1820disp();//显示while(1){read_date();key_scan();read_temp();//读取温度ds1820disp();//显示}}。