数码管万年历实习报告Word下载.docx
《数码管万年历实习报告Word下载.docx》由会员分享,可在线阅读,更多相关《数码管万年历实习报告Word下载.docx(29页珍藏版)》请在冰豆网上搜索。
DS1302内部有一个31×
8的用于临时性存放数据的RAM寄存器。
具有主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
主要特点是采用串行数据传输,可为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。
采用普通32.768kHz晶振。
因此,本设计中采用DS1302提供时钟。
3.74LS154
74LS154为4线-16线译码器,其主要电特性的典型值如下:
当选通端(G1、G2)均为低电平时,可将地址端(ABCD)的二进制编码在一个对应的输出端,以低电平译出。
若将G1和G2中的一个作为数据输入端,由ABCD对输出寻址,54/74154还可作4线-16线数据分配器。
引出端符号:
A、B、C、D译码地址输入端(低电平有效)
G1、G2选通端(低电平有效)
0-15输出端(低电平有效)
可用此种芯片作为数码管的选址芯片。
4.74HC573
74HC573是八进制3态非反转透明锁存器,是高性能硅门CMOS器件。
当锁存使能端为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。
当锁存使能变低时,符合建立时间和保持时间的数据会被锁存。
输出能直接接到CMOS,NMOS和TTL接口上操作电压范围:
2.0V~6.0V×
低输入电流:
1.0uA。
本实训采用此芯片作为数码管的驱动芯片。
5.数码管
本实训使用共阴极数码管作为显示器件,采用LED数码管动态扫描,LED数码管价格适中,对于显示数字也最合适。
综上各模块的选择方案与论证,确定最后的主要硬件资源如下:
采用AT89S51作为主控制系统;
DS1302提供时钟;
DS18B20作为数字式温度传感器;
74LS154作为选址芯片;
74HC573作为数码管的驱动芯片;
共阴极数码管显示数字;
S8550驱动扬声器。
二、实训原理
为了使万年历在包装美化时简单化及布线的方便,我将万年历分为两部分,一部分是主体部分含有年份、月、日、时、分、秒,另一部分是小模块包含周、温度。
电路图如下:
主电路图:
主电路PCB:
周,温度电路图:
周,温度PCB:
三、程序编写
使用Keil软件编写程序。
程序包括主函数、时间显示函数、温度显示函数、时间调整函数、DS18B20模块、DS1302模块和周计算函数等。
程序的编写使我熟练的掌握了Keil软件的应用。
具体程序见附录。
四、程序的烧写与调试
程序烧写需要用专用的烧写软件将Keil软件声生成的.hex文件写进单片机里。
经过多次的程序的改写与调试,最终制作出比较满意的成品。
五、成品展示:
心得体会:
经过此次实训我学到了很多,刚开始以为做万年历很难,着手开始做这个产品没有一点头绪,经过上网查资料,产生了最初的制作框架,然后就开始找芯片,查芯片资料,设计电路图,又请同学帮忙指点,修改原理图。
接着买元器件,做封装,生成PCB,制作电路板,焊接元器件,最后完成了整个硬件部分的制作。
完成了硬件制作后,我又编了测试软件测试硬件是否有问题,发现数码管不亮,经过问题排查及资料查询,发现单片机P0口缺少了上拉电阻,接上后,解决了问题。
编程也是比较困难的,由于掌握的知识不够多,借鉴了别人的程序,并加入自己的想法,经过调试,程序编写成功。
最终完成了产品的制作。
在实习的过程中我得到了别人的帮助,同时也主动帮助别人,得到了很多经验,为以后学习提供了方便。
实习就是学习的过程,本次实习是最成功的一次,也是学到最多的一次。
参考文献:
《单片机C51程序设计教程与实验》北京航空航天大学出版社
《单片机原理及应用(C51语言)》清华大学出版社
《数字电子技术》黄河水利出版社
《ProtelDXP2004电路设计与仿真教程》北京航空航天大学出版社
附录:
程序
万年历.c
#include<
reg51.h>
intrins.h>
#defineucharunsignedchar
#defineuintunsignedint
ucharcodedigit[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x39,0x00};
ucharmode,TH,TL,TN,seconds,minutes,hours,years,months,days,WEEK,n;
ucharcount=0;
sbitSET=P3^4;
sbitADD=P3^5;
//增加
sbitRED=P3^6;
//减小
sbitCANL=P3^7;
sbitle=P2^6;
sbitoe=P2^7;
sbiten=P1^4;
sbitbeep=P2^4;
ucharGetWeekFromDay(ucharyears,ucharmonths,uchardays);
voidWriteSet1302(ucharcmd,uchardate);
ucharReadSet1302(ucharcmd);
voidReadyreadDS18B20(void);
ucharReadDS18B20(void);
voidIntDS1302(void);
voiddelay1ms(uintx)
{
uchari,j;
for(i=x;
i>
0;
i--)
for(j=124;
j>
j--);
}
voiddelaynus(ucharn)//延时若干微秒
while(n--);
voiddisplay_Year(year)//显示年
{
i=year/10;
j=year%10;
P0=digit[2];
P1=8;
delay1ms
(2);
P0=digit[0];
P1=9;
P0=digit[i];
P1=10;
P0=digit[j];
P1=11;
delay1ms
(1);
voiddisplay_Month(month)//显示月
i=month/10;
j=month%10;
P1=6;
P1=7;
voiddisplay_Day(day)//显示日
i=day/10;
j=day%10;
P1=4;
P1=5;
voiddisplay_Hour(hour)//显示时
i=hour/10;
j=hour%10;
P1=2;
P0=digit[j]+n*0x80;
P1=3;
voiddisplay_Minute(minute)//显示分
i=minute/10;
j=minute%10;
P1=0;
P1=1;
voiddisplay_Week(void)//显示周
{
WEEK=GetWeekFromDay(years,months,days);
P1=12;
switch(WEEK)
case1:
P0=digit[1];
delay1ms
(2);
break;
case2:
P0=digit[2];
case3:
P0=digit[3];
case4:
P0=digit[4];
case5:
P0=digit[5];
case6:
P0=digit[6];
case7:
P0=digit[8];
}
}
voiddisplay_Time(void)//显示实时时间
ucharvalue;
value=ReadSet1302(0x83);
minutes=(((value&
0x70)>
>
4)*10+(value&
0x0f));
display_Minute(minutes);
value=ReadSet1302(0x85);
hours=(((value&
display_Hour(hours);
value=ReadSet1302(0x87);
days=(((value&
display_Day(days);
value=ReadSet1302(0x89);
months=(((value&
display_Month(months);
value=ReadSet1302(0x8D);
years=(((value&
0xf0)>
display_Year(years);
display_Week();
/*****************时间调整部分*********************/
voidhourset(void)//调时
uchartimevalue,hour;
delay1ms(500);
//防止多次触发
WriteSet1302(0x8e,0x00);
//将写保护去掉,确保能正常将调整后的数值写入DS1302
timevalue=ReadSet1302(0x85);
//读取此时的数值
hour=(((timevalue&
4)*10+(timevalue&
while
(1)
if(ADD==0)
{
delay1ms(20);
if(ADD==0)
{
hour++;
delay1ms(100);
while(ADD==0);
}
if(RED==0)
if(RED==0)
hour--;
if(hour==0)hour=23;
while(RED==0);
if(hour>
=24)hour=0;
timevalue=(((hour)/10)<
<
4|(hour%10));
WriteSet1302(0x84,timevalue);
delay1ms
(2);
display_Hour(hour);
delay1ms(10);
if(CANL==0)
mode=0;
if(SET==0)break;
}
WriteSet1302(0x8e,0x80);
voidminuteset(void)//调分
uchartimevalue,minute;
timevalue=ReadSet1302(0x83);
minute=(((timevalue&
minute++;
if(minute>
=60)timevalue=0;
delay1ms(10);
minute--;
if(minute==0)minute=59;
delay1ms(300);
if(minute>
=60)minute=0;
timevalue=((minute/10)<
4|(minute%10));
WriteSet1302(0x82,timevalue);
display_Minute(minute);
voidyearset(void)//调年
uchardatevalue,year;
datevalue=ReadSet1302(0x8d);
year=(((datevalue&
4)*10+(datevalue&
year++;
year--;
datevalue=((year/10)<
4|(year%10));
WriteSet1302(0x8c,datevalue);
delay1ms(5);
display_Year(year);
voidmonthset(void)//调月
uchardatevalue,month;
datevalue=ReadSet1302(0x89);
month=(((datevalue&
month++;
if(month>
12)month=1;
month--;
if(month==0)month=12;
datevalue=((month/10)<
4|(month%10));
WriteSet1302(0x88,datevalue);
display_Month(month);
voiddayset(void)//调日
uchardatevalue,day;
datevalue=ReadSet1302(0x87);
day=(((datevalue&
day++;
if(day>
31)day=1;
if(day==0)day=31;
day--;
datevalue=((day/10)<
4|(day%10));
WriteSet1302(0x86,datevalue);
display_Day(day);
voidTimeSet(void)//时间调整函数
if(SET==0)
delay1ms(20);
if(SET==0)
{while(!
SET);
mode++;
switch(mode)
case1:
{yearset();
delay1ms(20);
}break;
case2:
{monthset();
case3:
{dayset();
delay1ms(20);
case4:
{hourset();
delay1ms(20);
case5:
{minuteset();
if(mode==5)mode=0;
/***************显示温度模块********************/
ucharflag;
/*********************显示温度整数部分*************************/
voidDisplay_Integer(unsignedcharx)
uchars,g;
s=x%100/10;
g=x%10;
P0=digit[s];
P1=13;
delay1ms(3);
P0=digit[g]+0x80;
P1=14;
delay1ms(3);
P0=digit[10];
P1=15;
voiddisplay_Temperature(void)
{
ReadyreadDS18B20();
TL=ReadDS18B20();
TH=ReadDS18B20();
if((TH&
0XF8)!
=0X00)
{
flag=1;
TL=~TL;
TH=~TH;
TL+=1;
if(TL>
255)TH+=1;
TN=TH*16+TL/16;
}
TN=TH*16+TL/16;
Display_Integer(TN);
/****************设置模块******************/
voidSet(void)
delay1ms(50);