光控数字温度时钟.docx
《光控数字温度时钟.docx》由会员分享,可在线阅读,更多相关《光控数字温度时钟.docx(26页珍藏版)》请在冰豆网上搜索。
光控数字温度时钟
序号:
11
光电技术课程设计
题目:
光控数字温度时钟
学生
刘慧
班级
电子1202-1BF
学号
14122502243
专业
电子科学与技术
指导老师
田芃
职称
副教授
完成时间
2015年6月15日
(湖南理工学院物理与电子学院)
课程设计任务书
1、主题词、关键词
数字时钟;DS1302;A/D;D/A;热敏电阻;光敏电阻;51单片机
2、课程设计内容要求
•掌握DS1302时钟芯片使用方法
•掌握光敏电阻原理、特点和使用方法
•掌握热敏电阻原理、特点和使用方法
•掌握LED数码管动态显示原理与使用方法
•设计与开发一套数字时钟
•采用DS1302S时钟芯片,带断电保护;
•具有闹钟和定点报时功能;
•具有温度显示功能;
•具有光控功能,能根据环境光线的强弱,动态调节显示亮度。
3、进程安排
•第13周:
系统硬件电路设计
•第14周:
系统软件设计与仿真
•第15周:
实物制作
•第16周:
撰写总结报告
一、引言
在科技飞速发展的今天,电子技术获得了飞速的发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,推动了社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。
数字钟已成为人们日常生活中必不可少的必需品,广泛用于个人家庭以及办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大的方便。
由于数字集成电路技术的发展,使数字钟具有走时准确、性能稳定的特点。
因此在许多电子设备中被广泛应用。
电子钟是人们日常生活中常用的计时工具,而且电子钟又具有重量轻、走时准确、结构简单、耗电量少等优点而在生活中被广泛使用,因此本次设计就用数字集成电路来设计一个电子钟,使其完成多功能。
本文主要介绍由单片机控制的带有温度显示的电子钟的设计。
随着人们生活水平的日益提高,人们对生活的要求越来越高,原有的事物已经不能满足人们的生活需求了,一些带有新功能的事物已经在慢慢的取代旧事物。
就像电子钟一样,人们用电子钟不仅仅只是看时间了,人们还需要看温度了。
越来越多的新功能更贴近人们的生活了,所以也越来越受人们所喜欢。
二、设计目的
1:
熟悉51单片机的操作,引脚分配,定时器的使用,及相关一些外设的使用;
2:
掌握数字钟的组成及工作原理;
3:
熟悉数字钟的设计与制作;
4:
掌握DS1302时钟芯片使用方法
5:
掌握LED数码管动态显示原理与使用方法
6:
学习ADCDAC芯片的使用方法
7:
熟悉PROTEUS软件的使用.
三、设计要求
1:
掌握DS1302时钟芯片使用方法
2:
掌握光敏电阻原理、特点和使用方法
3:
掌握热敏电阻原理、特点和使用方法
4:
掌握LED数码管动态显示原理与使用方法
5:
设计与开发一套数字时钟
(1):
采用DS1302S时钟芯片,带断电保护;
(2):
具有闹钟和定点报时功能;
(3):
具有温度显示功能;
(4):
具有光控功能,能根据环境光线的强弱,动态调节显示亮度。
四、硬件设计
硬件电路主要包括:
控制器模块,数字时钟发生模块,显示模块,温度与亮度测量与转换模块,提示模块,按键调节模块。
硬件电路如下:
1、DS1302组成数字时钟发生模块:
DS1302可通过简单的串行接口与单片机进行通信
可提供:
--秒,分,时,星期,年,月,日
--每月的天数和闰年的天数可自动调整
--可通过AM/PM指示决定采用24或12小时格式
--低功耗:
保持数据和时钟信息时功率小于1mW,可用在断电保护
2、D/A模块
采用DAC0808用于控制数码管的亮度
DAC输出经放大器接至PNP三极管发射极,通过改变发射极电压来控制数码管的亮度。
3、显示模块
用4位数码管显示
数码管为共阳极数码管,
数码管采用动态显示时间,温度。
数码管阳极接至PNP三极管集电极,以提供数码管的驱动,并便于控制数码管的亮度(通过控制PNP三极管的发射极电位)。
4、温度光强采集模块
用光敏电阻和热敏电阻分别采集光强信号和温度信号,再经过TLC1543串行10位AD将采集到的信号传送给单片机。
使用10位串行ADCTLC1543不但能得到较高的精度,而且采用串行通信减少了单片机的引脚连接。
程序软件编写应注意TLC1543通道地址必须为写入字节的高四位,而CPU读入的数据是芯片上次A/D转换完成的数据。
5、提示模块与按键
蜂呜器用于闹钟提示与整点报时。
按键用于调时间和设闹钟。
并设置了长按键功能(长按功能键返回正常显示状态,长按加键快速调时或设闹钟)。
实际硬件采用的专用单片机:
STC15F204EA单片机。
它与通用51的区别如下:
STC15F204EA单片机是A/D转换单片机,1个时钟/机器周期,高速,高可靠,8路10位高速A/D转换,内部有高精度R/C时钟,±1%温飘,彻底省掉外部昂贵的晶振,5MHz~35MHz宽范围可设置.
•内部高精度R/C时钟,时钟从5M~35MHz可选;
•内部高可靠复位,彻底省掉外部复位电路;
•8通道,10位高速ADC,速度可达30万次/秒;
•通用I/O口(26个),可设置成四种模式:
准双向口/弱上拉,推挽/强上拉,仅为输入/高阻,开漏。
我们使用的STC15F204EA单片机它的外部封装如下:
它的相关功能如下:
实物如下:
五、软件设计
/***************DS1302.C******************/
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitIO=P1^5;//DS1302'sI/O
sbitSCLK=P1^6;//DS1302'sclock
sbitRST=P1^7;//DS1302'sReset
voidWrite_A_Byte_TO_DS1302(ucharx)
{
uchari;
for(i=0;i<8;i++)
{
IO=x&0x01;SCLK=1;SCLK=0;x>>=1;
}
}
ucharGet_A_Byte_FROM_DS1302()
{
uchari,b=0x00;
for(i=0;i<8;i++)
{
b|=_crol_((uchar)IO,i);
SCLK=1;SCLK=0;
}
returnb/16*10+b%16;//返回BCD码
}
ucharRead_Data(ucharaddr)//从DS1302指定位置读数据
{
uchardat;
RST=0;SCLK=0;RST=1;
Write_A_Byte_TO_DS1302(addr);
dat=Get_A_Byte_FROM_DS1302();
SCLK=1;RST=0;
returndat;
}
voidWrite_DS1302(ucharaddr,uchardat)
{
SCLK=0;RST=1;
Write_A_Byte_TO_DS1302(addr);
Write_A_Byte_TO_DS1302(dat);
SCLK=0;RST=0;
}
voidGetTime(uchar*DateTime)//读取当前日期时间
{
uchari,addr=0x81;
for(i=0;i<7;i++)
{
DateTime[i]=Read_Data(addr);addr+=2;
}
}
voidSET_DS1302(uchar*DateTime)
{
uchari;
Write_DS1302(0x8E,0x00);//写控制位,取消保护
for(i=1;i<7;i++)
Write_DS1302(0x80+2*i,(DateTime[i]/10<<4)|(DateTime[i]%10));
Write_DS1302(0x8E,0x80);//加保护
}
*********************Display********************
#include"Display.h"
externunsignedcharTempData[8];//存储显示值的全局变量
/*------------------------------------------------
显示函数,用于动态扫描数码管
------------------------------------------------*/
voidNormalDisplay(void)
{
if((time_buf1[4]/10)==0)
{LATCH1=1;}
else
{LATCH1=0;}
DataPort=TempData[0];
DelayMs(4);
LATCH1=1;
LATCH2=0;
DataPort=TempData[1];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH2=1;
LATCH3=0;
DataPort=TempData[2];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH3=1;
LATCH4=0;
DataPort=TempData[3];
DelayMs(4);
LATCH4=1;
voidHourDisplay(void)
{
if((time_buf1[4]/10)==0)
{LATCH1=1;}
else
{
if(((time_buf1[6]%10)%2)==0)
{LATCH1=0;}
else
{LATCH1=1;}
}
DataPort=TempData[0];
DelayMs(4);
LATCH1=1;
if(((time_buf1[6]%10)%2)==0)
{LATCH2=0;}
else
{LATCH2=1;}
DataPort=TempData[1];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH2=1;
LATCH3=0;
DataPort=TempData[2];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH3=1;
LATCH4=0;
DataPort=TempData[3];
DelayMs
(2);
LATCH4=1;
}
voidMinuteDisplay(void)
{
if((time_buf1[4]/10)==0)
{LATCH1=1;}
else
{LATCH1=0;}
DataPort=TempData[0];
DelayMs(4);
LATCH1=1;
LATCH2=0;
DataPort=TempData[1];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH2=1;
if(((time_buf1[6]%10)%2)==0)
{LATCH3=0;}
else
{LATCH3=1;}
DataPort=TempData[2];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs
(2);
LATCH3=1;
if(((time_buf1[6]%10)%2)==0)
{LATCH4=0;}
else
{LATCH4=1;}
DataPort=TempData[3];
DelayMs
(2);
LATCH4=1;
}
voidDataDisplay(void)
{
LATCH1=0;
DataPort=TempData[4];
DelayMs(4);
LATCH1=1;
LATCH2=0;
DataPort=TempData[5];
//SEC=((time_buf1[6]%10)%2);//跳秒处理
SEC=0;
DelayMs(4);
LATCH2=1;
LATCH3=0;
DataPort=TempData[6];
//SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH3=1;
LATCH4=0;
DataPort=TempData[7];
SEC=0;
DelayMs(4);
LATCH4=1;
}
voidMoothDisplay(void)
{
if(((time_buf1[6]%10)%2)==0)
{LATCH1=0;}
else
{LATCH1=1;}
DataPort=TempData[4];
DelayMs(4);
LATCH1=1;
if(((time_buf1[6]%10)%2)==0)
{LATCH2=0;}
else
{LATCH2=1;}
DataPort=TempData[5];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH2=1;
LATCH3=0;
DataPort=TempData[6];
//SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs
(2);
LATCH3=1;
LATCH4=0;
DataPort=TempData[7];
DelayMs
(2);
LATCH4=1;
}
voidDayDisplay(void)
{
LATCH1=0;
DataPort=TempData[4];
DelayMs(4);
LATCH1=1;
LATCH2=0;
DataPort=TempData[5];
//SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs(4);
LATCH2=1;
if(((time_buf1[6]%10)%2)==0)
{LATCH3=0;}
else
{LATCH3=1;}
DataPort=TempData[6];
//SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs
(2);
LATCH3=1;
if(((time_buf1[6]%10)%2)==0)
{LATCH4=0;}
else
{LATCH4=1;}
DataPort=TempData[7];
SEC=((time_buf1[6]%10)%2);//跳秒处理
DelayMs
(2);
LATCH4=1;
}
*******************Delay**************
#include"delay.h"
voidDelayUs(unsignedchart)
{
while(--t);
}
voidDelayMs(unsignedchart)
{
while(t--)
{
//大致延时1mS
DelayUs(245);
DelayUs(245);
}
}
**********************main.c*******************
#include//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include"ds1302.h"
#include"Display.h"
#include"Delay.h"
sbitLED0=P1^0;
sbitLED1=P1^1;
sbitK1=P2^4;//定义按键端口,选择调整什么
sbitK2=P2^5;//加键
bitReadTimeFlag=1;//定义读时间标
//bitSecondFlag=0;
unsignedcharcodeDuanMa1[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳显示段码值0~9
unsignedcharcodeDuanMa2[10]={0xc0,0xcf,0xa4,0x86,0x8b,0x92,0x90,0xc7,0x80,0x82};//第三个数码管的数组
unsignedcharTempData[8];//存储显示值的全局变量
unsignedcharSetTime=0;
voidInit_Timer0(void);//定时器初始化
/*------------------------------------------------
主函数
------------------------------------------------*/
voidmain(void)
{
Init_Timer0();
Ds1302_Init();
Ds1302_Read_Time();
while
(1)
{
if(!
K1)
{
DelayMs(10);
if(!
K1)
{
while(!
K1);
{
LED0=~LED0;
SetTime++;
if(SetTime==5)SetTime=0;
}
}
}
if(!
K2)
{
DelayMs(10);
if(!
K2)
{
while(!
K2);
{
LED1=~LED1;
if(SetTime==0)
{SetTime=50;LED0=~LED0;}
else
{//
switch(SetTime)
{
case1:
time_buf1[4]++;if(time_buf1[4]==24)time_buf1[4]=0;
Ds1302_Write_Time();break;//正常时间小时加1
case2:
time_buf1[5]++;if(time_buf1[5]==60)time_buf1[5]=0;
Ds1302_Write_Time();break;//分加1
case3:
time_buf1[2]++;if(time_buf1[2]==13)time_buf1[2]=1;
Ds1302_Write_Time();break;//正常时间月加1
case4:
time_buf1[3]++;if(time_buf1[3]==31)time_buf1[3]=1;
Ds1302_Write_Time();break;//日加1
default:
break;
}
}
}
}
}//
if(ReadTimeFlag==1)//大致100ms
{
ReadTimeFlag=0;
TempData[0]=DuanMa1[time_buf1[4]/10];//时//数据的转换,
TempData[1]=DuanMa1[time_buf1[4]%10];//因我们采用数码管0~9的显示,将数据分开
TempData[2]=DuanMa2[time_buf1[5]/10];//分
TempData[3]=DuanMa1[time_buf1[5]%10];
TempData[4]=DuanMa1[time_buf1[2]/10];//月
TempData[5]=DuanMa1[time_buf1[2]%10];
TempData[6]=DuanMa2[time_buf1[3]/10];//日
TempData[7]=DuanMa1[time_buf1[3]%10];
}
}
}
/*------------------------------------------------
定时器初始化子程序//
------------------------------------------------*/
voidInit_Timer0(void)
{
TMOD|=0x01;//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
//TH0=0x00;//给定初值
//TL0=0x00;
EA=1;//总中断打开
ET0=1;//定时器中断打开
TR0=1;//定时器开关打开
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
voidTimer0_isr(void)interrupt1
{
staticunsignedintnum;
TH0=(65536-500)/256;//重新赋值0.5ms
TL0=(65536-500)%256;
num++;
if(num==1)
{
Ds1302_Read_Time();
switch(SetTime)
{
case0:
NormalDisplay();break;
case1:
HourDisplay();break;
case2:
MinuteDisplay();break;
case3:
MoothDisplay();break;
case4:
DayDisplay();break;
case50:
while(SetTime--)
{
DataDisplay();DelayMs(20