当前位置:文档之家› 带温度显示的万年历_数码管显示(附电路图和源代码)

带温度显示的万年历_数码管显示(附电路图和源代码)

设计报告设计任务:设计一个智能化万年历时钟电路,LED数码管作为电路的显示部分,按钮开关作为调时部分,通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期、温度。

并能准确计算闰年闰月的显示。

设计要求:通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期等功能,并能准确计算闰年闰月的显示,三个个按钮连接P3.0、P3.1、P3.2可以精确调整每一个时间数值,通过对所设计的万年历时钟电路进行实验测试,达到了动态显示时间,随时调整时间等技术所连线路和单片机接口仿真图如图3所示:图3 仿真按键4)温度采集部分:DS18B20温度传感器,测温范围-55℃~+125℃,固有测温分辨率0.5℃。

独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。

DS18B20的采集数据通过DQ传入单片机,单片机读取数据后将数据输出!如图所示:程序如下:ReadOneChar(void){unsigned char i=0;// 定义i用于循环unsigned char dat = 0;// 读取的8位数据for (i=8;i>0;i--)//8次循环{DQ = 0;// 拉低DQ总线开始读时序dat>>=1;// dat左移一位DQ = 1; //释放DQ总线if(DQ)// 如果DQ=1,执dat|=0x80;(0x80即第7位为1,如果DQ为1,即读取的数据为1,将dat的第7为置1,然后dat>>=1,循环8次结束,dat 即为读取的数据)//DQ=0,就跳过dat|=0x80;Tdelay(4);// 延时以完成此次读时序,之后再读下一数据}return(dat); 返回读取的dat}//写一个字节WriteOneChar(unsigned char dat){unsigned char i=0;//for (i=8; i>0; i--)//{DQ = 0;//DQ = dat&0x01;//Tdelay(5);//延时以完成此次读时序,之后再读下一数据DQ = 1;//dat>>=1;//}}//读取温度ReadTemperature(void){unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;//Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0x44);// 启动温度转换Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0xBE);// 写指令,读暂存存储器a=ReadOneChar();//读低8位b=ReadOneChar();//读高8位t=b;//t<<=8;//t=t|a;//tt=t*0.0625;//t= tt*10+0.5;//return(t); //获得0.01°C 的精度并返回}LED数码管的选择LED数码管分为共阴和共阳两种,以利用STC89C51的P0口作为LED显示的数据部分,以P2口的七个口作为显示部分的位选,通过三八译码器和4-16译码器扩展为17位的位选分别接在一个四位数码管和13个数码管的位选部分。

详细电路图如图4-5所示:程序如下:P2=0xF0;P0=L1;delay(1); //yearh P2=0xF1;P0=L2;delay(1); //yearhif(cursor==8){P2=0x1F|a;P0=L17;delay(1);}else{P2=0x1F;P0=L17;delay(1);}//weekif(cursor==6){P2=0xF2|a;P0=L3;delay(1);}else{P2=0xF2;P0=L3;delay(1);} //yearlif(cursor==6) {P2=0xF3|a;P0=L4;delay(1);}else{P2=0xF3;P0=L4;delay(1);} //yearlif(cursor==5) {P2=0xF4|a;P0=L5;delay(1);}else{P2=0xF4;P0=L5;delay(1);} //monthif(cursor==5) {P2=0xF5|a;P0=L6;delay(1);}else{P2=0xF5;P0=L6;delay(1);} //monthif(cursor==4) {P2=0xF6|a;P0=L7;delay(1);}else{P2=0xF6;P0=L7;delay(1);} //dayif(cursor==4) {P2=0xF7|a;P0=L8;delay(1);}else{P2=0xF7;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3) {P2=0xF8|a;P0=L9;delay(1);}else{P2=0xF8;P0=L9;delay(1);} //hourif(cursor==3) {P2=0xF9|a;P0=L10;delay(1);else{P2=0xF9;P0=L10;delay(1);} //hourif(cursor==2) {P2=0xFA|a;P0=L11;delay(1);}else{P2=0xFA;P0=L11;delay(1);} //minif(cursor==2) {P2=0xFB|a;P0=L12;delay(1);}else{P2=0xFB;P0=L12;delay(1);} //minif(cursor==1) {P2=0xFC|a;P0=L13;delay(1);}else{P2=0xFC;P0=L13;delay(1);} //secif(cursor==1)P2=0xFD|a;P0=L14;delay(1);}else{P2=0xFD;P0=L14;delay(1);} //secP2=0xFE;P0=L15;delay(1); //tempP2=0x0F;P0=L16;delay(1); //tempP2=0xFF;}图5 日期显示仿真实验整个电路仿真图如下图6所示所示:图6 仿真电路图实物的制作与调试(1)原理图的绘制与PCB的制作(2)原理图的绘制(3)在Protel99se中先新建一个工程,把所需要的元件载入到文档里面。

(4)按照所设计的电路画原理图(5)通过电气检查是否有错,并修改完善。

原理图如图7所示:显示部分图7 原理图系统实现:1、方案设计、方案比较方案一:采用实时时钟芯片实时时钟芯片具备年、月、日、时、分、秒计时功能和多点定时功能,计时数据的更新每秒自动进行一次,不需程序干预。

计算机可通过中断或查询方式读取数据进行显示,因此计时功能的实现无需占用CPU的时间,程序简单。

此外,实时时钟芯片多数带有锂电池做后备电源,具备永不停止的计时功能;具有可编程方波输出功能,可用做实时测控系统的采样信号等;有的实时时钟芯片内部还带有非易失性RAM,可用来存放需长期保存但有时也需变更的数据。

由于功能完美,精度高,软件程序设计相对简单,且计时不占用CPU时间,因此,在工业实时测控系统中多采用这一类专用芯片来实现实时时钟功能。

方案二:软件控制利用单片机内部的定时/计数器进行中断定时,配合软件延时实现时、分、秒的计时,该方案节省硬件成本,且能使设计者对单片机的指令系统能有更深入的了解,从而掌握单片机应用技术MCS-51汇编语言程序设计方法,因此,本系统设计采用此种软件控制方法来实现时, STC89C51单片机是低功耗的具有4KB在线可编程FLASH存储器的单片机。

它与通用80C51系列单片机的指令第和引脚兼容。

片内的FLASH集成在一个芯片上,形成了功能强大、使用灵活和具有较高性能价格比的微控制器。

它的功能强大,而且也较容易购买。

总结:所要实现的功能通过单片机编程就可以达到,不需要额外的时钟芯片来增加成本,并使外围电路更加简单明了。

3、实验步骤(1)、给电路通上电源, LED显示是否通电;(2)、电路板上分别选择模式、+ 和 - 按键,可以对时间和日期进行任意的调整,数码管分别显示日期和时间;调整模式按键按下表示对时间开始进行调整,通过选位来确定所要调整的位置,分别可以加和减。

(3)、用一个四位数码管和13个数码管,可显示时间和日期。

实验实物图如图11-12所示:总结:经过测试,我所做的万年历相对稳定,并且能准确的计时以及调整时间,经过这次试验懂得了仿真与实物是有差别的,也学会了很多。

实验总结:1、这次我的设计的任务是万年历时钟的设计,通过C51芯片程序控制显示万年历。

本次实验是设计一个智能化万年历时钟电路,LED数码管作为电路的显示部分,按钮作为调整时间和日期部分,可任意的对时间进行所需的调整,通过与单片机连接数码管动态显示年、月、日、时、分、秒、星期、温度等功能,并能准确计算闰年闰月的显示。

2、我采用的是12MHZ的晶振,再通过一系列的计算从而实现万年历时钟的基本功能。

在实验调试过程中,出现了很多的问题,仿真时不需要数码管驱动依然能够实现所需的功能,但实验时出现了数码管亮度达不到要求的情况。

我采用了以下方案来驱动数码管:1)74LS138和74HC154作为位选驱动;2)在P0口接的上拉电阻,在这个过程中又涉及了上拉电阻的大小,开始用10K的电阻,因为电阻过大,使电流不能达到要求,以至于不能增加数码管的亮度。

最后我们换用1K的上拉电阻,成功的实现了我们所要得到的结果,数码管的亮度达到了所需的要求。

3、在做板过程中出现的线断路问题;通过万用表的检测一一排除和焊接!4、本次实验让自己对单片机的应用有了进一步的了解,对程序也有了更深的体会!元件清单附录源程序如下所示:#define uchar unsigned char#define uint unsigned int#define DQ P3_7#include<AT89X51.H>uint sec; 初始化秒uint min=50;//初始化分钟uint hour=9;// 初始化时uint day=10;// 初始化天uint month=6;// 初始化月uint yearl=11;// 初始化年低位uint yearh=20;// 初始化年高位uint week=6;// 初始化星期uint tcnt; // 定义tcnt变量uint cursor=0;// 定义cursor变量uchar a=0xff;定义a变量uchar code Seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴数码显示码值void delay(uint t){uint i;while(t--){for (i=0;i<125;i++);}} //延时函数子函数void Tdelay(unsigned int i){while(i--);}void Kdelay(){uchar i,j;//定义I J 变量for(i=100;i>0;i--)for(j=248;j>0;j--);}//延时Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位Tdelay(8); //稍做延时DQ = 0; //单片机将DQ拉低Tdelay(80); //精确延时,大于480usDQ = 1; //拉高总线Tdelay(14);Tdelay(20);//延时}//读一个字节ReadOneChar(void){unsigned char i=0;// 定义i用于循环unsigned char dat = 0;// 读取的8位数据for (i=8;i>0;i--)//8次循环{DQ = 0;// 拉低DQ总线开始读时序dat>>=1;// dat左移一位DQ = 1; //释放DQ总线if(DQ)// 如果DQ=1,执dat|=0x80;(0x80即第7位为1,如果DQ为1,即读取的数据为1,将dat的第7为置1,然后dat>>=1,循环8次结束,dat 即为读取的数据)//DQ=0,就跳过dat|=0x80;Tdelay(4);// 延时以完成此次读时序,之后再读下一数据}return(dat); 返回读取的dat}//写一个字节WriteOneChar(unsigned char dat){unsigned char i=0;//for (i=8; i>0; i--)//{DQ = 0;//DQ = dat&0x01;//Tdelay(5);//延时以完成此次读时序,之后再读下一数据 DQ = 1;//dat>>=1;//}}//读取温度ReadTemperature(void){unsigned char a=0;unsigned char b=0;unsigned int t=0;float tt=0;//Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0x44);// 启动温度转换Init_DS18B20();WriteOneChar(0xCC);// 写指令,跳过ROM,WriteOneChar(0xBE);// 写指令,读暂存存储器a=ReadOneChar();//读低8位b=ReadOneChar();//读高8位t=b;//t<<=8;//t=t|a;//tt=t*0.0625;//t= tt*10+0.5;//return(t); //获得0.01°C 的精度并返回}void display(uchar L1,uchar L2,uchar L3,uchar L4,uchar L5,uchar L6,uchar L7,uchar L8,uchar L9,uchar L10,uchar L11,uchar L12,uchar L13,uchar L14,uchar L15,uchar L16,uchar L17)/***********动态显示数码管的时间**************/{P2=0xF0;P0=L1;delay(1); //yearhP2=0xF1;P0=L2;delay(1); //yearhif(cursor==8){P2=0x1F|a;P0=L17;delay(1);}else{P2=0x1F;P0=L17;delay(1);}//weekif(cursor==6){P2=0xF2|a;P0=L3;delay(1);}else{P2=0xF2;P0=L3;delay(1);} //yearlif(cursor==6){P2=0xF3|a;P0=L4;delay(1);}else{P2=0xF3;P0=L4;delay(1);} //yearlif(cursor==5) {P2=0xF4|a;P0=L5;delay(1);}else{P2=0xF4;P0=L5;delay(1);} //monthif(cursor==5) {P2=0xF5|a;P0=L6;delay(1);}else{P2=0xF5;P0=L6;delay(1);} //monthif(cursor==4) {P2=0xF6|a;P0=L7;delay(1);}else{P2=0xF6;P0=L7;delay(1);} //dayif(cursor==4) {P2=0xF7|a;P0=L8;delay(1);}else{P2=0xF7;P0=L8;delay(1);} //dayP2=0xFF;if(cursor==3) {P2=0xF8|a;P0=L9;delay(1);}else{P2=0xF8;P0=L9;delay(1);} //hourif(cursor==3) {P2=0xF9|a;P0=L10;delay(1);}else{P2=0xF9;P0=L10;delay(1);} //hourif(cursor==2) {P2=0xFA|a;P0=L11;delay(1);}else{P2=0xFA;P0=L11;delay(1);} //minif(cursor==2) {P2=0xFB|a;P0=L12;delay(1);}else{P2=0xFB;P0=L12;delay(1);} //minif(cursor==1) {P2=0xFC|a;P0=L13;delay(1);}else{P2=0xFC;P0=L13;delay(1);} //secif(cursor==1) {P2=0xFD|a;P0=L14;delay(1);}else{P2=0xFD;P0=L14;delay(1);} //secP2=0xFE;P0=L15;delay(1); //tempP2=0x0F;P0=L16;delay(1); //tempP2=0xFF;}main(){uint i;TMOD=0x02; //设置模式为定时器T0的模式2 (8位自动重装计数初值的计数值)TH0=0x06; //设置计数器初值,靠TH0存储重装的计数值X0=256-250=6TL0=0x06;TR0=1; //启动T0ET0=1; //开启定时器T0中断允许EA=1; //开启中断总控制while(1){P3_0=1;if(P3_0==0){delay(10);if(P3_0==0)//如果按键被按下{Kdelay();if(P3_0==0)//确定按键按下{while(P3_0==0); // 等待按键放开cursor++;if(cursor>=9){cursor=0;}//如果cursor大于9则cursor=0if(P1_0==0){cursor=0;}} }}P3_1=1;if(P3_1==0){delay(10);if(P3_1==0) //如果按键被按下{Kdelay();if(P3_1==0) //确定按键按下{if(cursor==1){sec++;//如果cursor=1则按键按下秒数加一if(sec==60)sec=0;//如果秒数等于60秒则回到0开始}if(cursor==2){min++;//如果cursor=2则按键按下分数加一if(min==60)min=0; 如果分数等于60分则回到0开始}if(cursor==3){hour++;//如果cursor=3则按键按下时数加一if(hour==24)hour=0; //如果时数等于24时则回到0开始}if(cursor==4){day++;//如果cursor=4则按键按下天数加一if(day==31)day=0; //如果天数等于31天则回到0开始}if(cursor==5){month++;//如果cursor=5则按键按下月数加一if(month==13)month=0; //如果月数等于13月则回到0开始}if(cursor==6){yearl++;//如果cursor=6则按键按下年数低位加一if(yearl==100)yearl=0; //如果年数等于100则回到0开始}if(cursor==7){yearh++;//如果cursor=7则按键按下年数高位加一if(yearh==30)yearh=20; //如果年数大于30则回到0开始}{week++;//如果cursor=8则按键按下星期数加一if(week==8)week=1; //如果星期数等于8则回到0开始}}while(P3_1==0);}}P3_2=1; //写入时先写1if(P3_2==0){//按键按下delay(10);//延时10个毫秒if(P3_2==0)//确定按键按下{Kdelay();if(P3_2==0){if(cursor==1){sec--;//如果cursor=1则按键按下秒数减一if(sec==0)sec=59; //如果秒数小于0则回到59开始}if(cursor==2){min--;//如果cursor=2则按键按下分数减一if(min==0)min=59; //如果分数小于0则回到59开始}if(cursor==3){hour--;//如果cursor=3则按键按下时数减一if(hour==0)hour=23; //如果时数小于0则回到23开始}if(cursor==4){day--;//如果cursor=4则按键按下天数减一if(day==0)day=31; //如果天数小于0则回到31开始}if(cursor==5){month--;//如果cursor=5则按键按下月数减一month=12; //如果月数小于0则回到12开始}if(cursor==6){yearl--;//如果cursor=6则按键按下年的低位数减一if(yearl==0)yearl=99; //如果年数小于0则回到99开始}if(cursor==7){yearh--;//如果cursor=7则按键按下年的高位数减一if(yearh==20)yearh=30; //如果年数小于0则回到30开始}if(cursor==8){week--;//如果cursor=8则按键按下秒星期减一if(week==0)week=7; //如果星期数小于0则回到7开始}while(P3_2==0);}}}i=ReadTemperature();display(Seg[yearh/10],Seg[yearh%10],Seg[yearl/10],Seg[yearl%10],Seg[ month/10],Seg[month%10],Seg[day/10],Seg[day%10],Seg[hour/10],Seg[hou r%10],Seg[min/10],Seg[min%10],Seg[sec/10],Seg[sec%10],Seg[i/100],Seg [i/10%10],Seg[week%10]); // 数据显示}}void t0(void)interrupt 1 using 0 //t0的中断程序{tcnt++;if(tcnt==4000)//定时器的定时计数,4000次250us为1秒{tcnt=0;sec++;if(sec==60){sec=0; 秒计到60时清0min++;//分数加一if(min==60){min=0; //分数计到60时清0hour++; //时数加一if(hour==24){hour=0;时数计到24时回到0开始day++;week++;天数和星期加一if(month==2&&((yearl==0&&yearh%4==0)||(yearl!=0&&yearl%4==0))&&day== 30)day=1;else if(month==2&&day==29)day=1;elseif((month==4||month==6||month==9||month==11)&&day==31)day=1; // 判断闰年else if(day==32)day=1;//天计到32时清1if(day==1){month++;//月数加一if(month==13){month=1;// 月数计到1时清1yearl++;//年的低位加一if(yearl==100){yearl=0;//年低位数计到100时清0yearh++;//高位加一if(yearh==100)//如果高位年数计到100 {yearh=20;//高位年数回到20}}}}}}}}}。

相关主题