基于51单片机设计的带有测温功能的电子时钟汇总.docx
- 文档编号:23613119
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:47
- 大小:795.67KB
基于51单片机设计的带有测温功能的电子时钟汇总.docx
《基于51单片机设计的带有测温功能的电子时钟汇总.docx》由会员分享,可在线阅读,更多相关《基于51单片机设计的带有测温功能的电子时钟汇总.docx(47页珍藏版)》请在冰豆网上搜索。
基于51单片机设计的带有测温功能的电子时钟汇总
、
职业技能训练之
电子技术课程设计报告
学院
电子与信息学院
设计题目
基于51单片机设计的带有测温功能的电子时钟
班级
XXX
姓名
XXX
学号
XXX
指导教师
XXX
时间
2012年06月25日
一、设计要求
二、课程设计的方案、目的及意义
三、硬件设计方案
四、软件设计方案
五、总结
六、参考资料
一、设计要求
用51单片机设计带温度显示的电子时钟,具体要求如下:
1、利用DS1302时钟芯片实现时钟功能模块。
2、时钟要求可以调节时间:
年、月、日、时、分、秒。
3、利用LCD1602显示。
4、利用DS18B20芯片实现温度功能模块。
5、利用按键完成各项功能。
二、课程设计方案、目的及意义
1、总体方案:
用STC89C51单片机作为CPU主控制器,DS1302时钟芯片提供准确时钟信号,DS18B20温度传感器采集温度信息,三个按键进行加减调整、功能切换作用,通过LCD1602对外多功能显示。
2、具体方案:
CPU控制所有模块,通过循环反复从DS1302中读取时钟信息,传送至LCD1602显示,得到基本时钟功能。
当分为59,秒为56时开始,每隔一秒LED灯点亮240毫秒,0分0秒时LED灯点亮700毫秒。
从而实现整点光报时。
定时循环从DS18B20中读取温度信息,传送至LCD1602显示,得到基本温度计功能。
当温度高于30度(包括30度)时,点亮红色LED灯,提醒当天为高温天气。
低于0度时,点亮蓝色LED灯,提醒当天为冰冻天气。
键盘使用扫面方式,MENU键控制功能切换,完成时钟和温度间的转换。
OK键控制时间调整与确定,UP、DOWN键调节时间,R、L键选择调整对象。
进入调整时,暂停DS1302数据读取,并将改变的时间数据写入DS1302,并送LCD1602显示,同时,启动LCD1602光标闪烁,确定调整对象,完成人机对话。
退出调整时,停止写入数据,重新读取DS1302时钟信息。
从而完善时钟功能。
3、目的及意义
可作为产品生产,作为居家的时钟显示与温度计。
三、硬件设计方案
1、原理图
2、PCB图
3、各功能模块分析
(一)、主控制器:
STC单片机89C51
功能:
程序存储器16K、RAM数字存储器1280、可直接通过串口下载程序,单一+5V电源供电,五个中断源的中断控制系统,片内振荡器和时钟产生电路,石英晶体和微调电容需要外接。
CPU:
由运算和控制逻辑组成,同时还包括中断系统和部分外部特殊功能寄存器。
RAM:
用以存放可以读写的数据,如运算的中间结果、最终结果以及欲显示的数据。
ROM:
用以存放程序、一些原始数据和表格。
I/O口:
四个8位并行I/O口,既可用作输入,也可用作输出。
P0口做I/O口需接上拉电阻。
T/C:
两个定时/记数器,既可以工作在定时模式,也可以工作在记数模式。
(二)、LCD1602显示模块
介绍:
工业字符型液晶,能够同时显示16x02即32个字符(16列2行)。
管脚信息:
显示模式设置:
显示开关及功能设置:
数据指针设置:
写时序:
注:
R3调节显示屏对比度
(三)、DS1302时钟芯片
管脚信息:
VCC:
Vcc1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
X1、X2:
X1和X2是振荡源,外接32.768kHz晶振。
RST:
RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:
首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
I/O为串行数据输入输出端(双向),后面有详细说明。
SCLK:
SCLK为时钟输入端。
日历寄存器:
注:
(1):
小时寄存器的位7用于定义DS1302是运行于12小时模式还是24小时模式。
当为高时,选择12小时模式。
在12小时模式下,位5为低时为AM,高时为PM。
在24小时模式下,位5是第二个10小时位。
(2)、秒寄存器的位7定义为时钟暂停标志。
当该位置为1时,时钟振荡器停止,DS1302处于低功耗状态;该位置0是,时钟开始运行。
(3)、控制寄存器的位7是写保护位,其他7位均置为0。
在任何的对时钟和RAM的写操作之前,WP位必须为0。
当WP位1时,写保护位防止对任一寄存器的写操作。
控制字节:
注:
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
数据读写及时序:
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
(四)、DS18B20温度传感器
管脚信息:
GND:
接地
DQ:
数据I/O
VDD:
电源
存储器:
控制字节:
SkipROM[CCh]:
允许总线控制器不用提供64位ROM编码就使用存储器操作命令,在单点总线情况下右以节省时间。
ConvertT[44h]:
开始温度转换。
ReadScratchpad[BEh]:
读取暂存器和CRC字节,知道9字节
时序:
读时间隙:
当从DS12B20读取数据时,主机生成读时间隙。
当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。
数据线必须保持至少1μs,从DS18B20输出的数据在读时间隙的下降沿出现后15μs内有效。
因此,主机在读时间隙开始后必须停止把I/O脚驱动为低电平15μs,以读取I/O脚状态。
在读时间隙的结尾,I/O引脚将被外部上拉电阻拉到高电平。
所有读时间隙必须最少60μs,包括两个读周期间至少1μs的恢复时间。
写时间隙:
当主机把数据线从逻辑高电平拉到逻辑低电平的时候,写时间隙开始。
所有写时间隙必须最少持续60μs,包括两个写周期间至少1μs的恢复时间。
I/O线电平变低后,DS18B20在一个15μs到60μs的窗口内对I/O线采样。
如果线上是高电平,就是写1,如果线上是低电平,就是写0。
主机要生成一个写时间隙,必须把数据线拉到低电平然后释放,在写时间隙开始后的15μs内允许数据线拉到高电平。
主机要生成一个写0时间隙,必须把数据线拉到低电平并保持60μs。
(六)、按键部分
原理:
键盘扫描,先将P3.6口置零,此时扫描S5~S8,如果P3.0~P3.3中有为0,则说明有对应键按下。
然后将P3.7口置零,此时扫描S1~S4,如果P3.0~P3.3中有为0,则说明有对应键按下。
四、软件设计方案
部分程序代码
(一)主程序:
#include
#include"lcd1602.h"//包含头文件,直接引用显示文件
#include"ds18b20.h"
#include"DS1302.h"
#defineucharunsignedchar
#defineuintunsignedint
#defineTIMER0_COUNT0xEE11
sbitmode=P3^0;//设定修改位数
sbitplus=P3^1;//加键
sbitdec=P3^2;//减键
ucharcount,s1num,timer0_tick,count=0;
typedefstruct{
charhour;
charminute;
charsecond;
}time;
typedefstruct{
uintyear;
charmonth;
charday;
}date;
timenow={11,20,7};//显示时间初始值
datetoday={12,6,16};
charcodedayofmonth[]={31,28,31,30,31,30,31,31,30,31,30,31};//设定月份数组,用以判定12个月的最大值
charcodeweekday[7][10]={"Week1","Week2","Week3","Week4","Week5","Week6","Week7"};//设定行星期显示数
ucharmonthday(ucharyear,ucharmonth)
{
if(month==2&&year%4==0)//用以判定是否为润年,其2月有29天
return(29);
else
return(28);//非闰年时的该月份天数28
}
voiddisplay_week()//由年月日计算星期,用以显示星期数
{
chardays;
days=(today.day+1+2*today.month+3*(today.month+1)/5+today.year+today.year/4-today.year/100+today.year/400)%7;
display_string(&weekday[days][0]);
}
staticvoidtimer0_initialize(void)//timer0initialize
{
EA=0;//设置不接受所有中断
timer0_tick=0;
TR0=0;//关闭Timer0
TMOD=0X01;//设置Timer0为模式2,16位工作模式
TL0=(TIMER0_COUNT&0X00FF);//设置Timer0低八位数值
TH0=(TIMER0_COUNT>>8);//设置Timer0高八位数值
PT1=1;//设置Timer0的优先级为最高
ET0=1;//设置接受Timer0的中断
TR0=1;//启动Timer0
EA=1;//设置系统接受中断
}
voidwrite_time(ucharadd,ucharnumber)//写时间
{
gotoxy(2,add);
display_data(number);
}
voidwrite_riqi(ucharadd,ucharnumber)//写日期
{
gotoxy(1,add);
display_data(number);
}
voidkeyscan()//按键扫描程序
{
ucharmode_num;//设定mode_num,来判断是哪一位要修改,当mode_num为零时,为非修改模式
if(mode==0)//"修改位"的选择
{
delay(5);//延时
if(mode==0)//当外部按键mode没按下一次时,都使mode_num自加,即mode_num表示为按键mode按下的次数
{mode_num++;
while(!
mode);
TR0=0;
write_com(0x0f);
}
if(mode_num==1)gotoxy(1,1);//当mode_num为1时,为年份改变位,光标移到(1,2)
if(mode_num==2)gotoxy(1,4);//当mode_num为2时,为月份改变位,光标移到(1,5)
if(mode_num==3)gotoxy(1,7);//当mode_num为3时,为日期改变位,光标移到(1,8)
if(mode_num==4)gotoxy(2,1);//当mode_num为4时,为小时改变位,光标移到(2,2)
if(mode_num==5)gotoxy(2,4);//当mode_num为5时,为分钟改变位,光标移到(2,5)
if(mode_num==6)gotoxy(2,7);//当mode_num为6时,为秒数改变位,光标移到(2,8)
if(mode_num==7)//当mode_num为7时,退出修改模式
{
mode_num=0;//非修改模式时,将mode_num置零,有助于判断是否为修改模式
write_com(0x0c);
TR0=1;
}
}
if(mode_num!
=0)//为修改模式时,加减键的处理子程序
{
if(plus==0)//当加键为零,即外部触发一次时,进行以下处理
{
delay(5);//延时
if(plus==0)//延时再次判断加键,防止抖动
{
if(mode_num==1)//当为年份改变时,年份自加一,并且显示修改后的日期
{
today.year++;
write_riqi(1,today.year);//因为年份主要是最后两位在改变,所以除以100来计算年份值,除以100求得的商值为十位
gotoxy(1,14);
display_week();//因为改变日期都会改变周数,所以要重新显示
}
if(mode_num==2)//以下处理同上
{
today.month++;
if(today.month==13)today.month=1;//特别注意,月份不能超过12,当为13时,要将月份置1
write_riqi(4,today.month);//除以10来计算月份值,除以10求得的商值为十位
gotoxy(1,14);
display_week();
}
if(mode_num==3)//以下处理同上
{
today.day++;
if(today.day>monthday(today.year,today.month))//特别要判断每个月份的最大值,不能超过此数,超过后要将天数置一
today.day=1;
write_riqi(7,today.day);//除以10来计算月份值,除以10求得的商值为十位
gotoxy(1,14);
display_week();
}
if(mode_num==4)//以下处理同上
{
now.hour++;
if(now.hour==24)now.hour=0;//小时不能超过24
write_time(1,now.hour);
}
if(mode_num==5)//以下处理同上
{
now.minute++;
if(now.minute==60)now.minute=0;
write_time(4,now.minute);
}
if(mode_num==6)//以下处理同上
{
now.second++;
if(now.second==60)now.second=0;
write_time(7,now.second);
}
}
}
if(dec==0)//减键的处理和加键处理处理相反
{
delay(5);
if(dec==0)
{
if(mode_num==1)
{
today.year--;
write_riqi(1,today.year);
gotoxy(1,14);
display_week();
}
if(mode_num==2)
{
today.month--;
if(today.month==0)today.month=12;//要注意月份的最小值为1,当减为零时,要讲月份置为12
write_riqi(4,today.month);//除以10来计算月份值,除以10求得的商值为十位
gotoxy(1,14);
display_week();
}
if(mode_num==3)
{
today.day--;
if(today.day==0)//当天数减为0时,要重新赋值,为上一个月的最大值
today.day=monthday(today.year,today.month);
write_riqi(7,today.day);//除以10来计算月份值,除以10求得的商值为十位
gotoxy(1,14);
display_week();
}
if(mode_num==4)
{
now.hour--;
if(now.hour<0)now.hour=23;//当小时数小于0时,要重新赋值,置为23
write_time(1,now.hour);
}
if(mode_num==5)
{
now.minute--;
if(now.minute<0)now.minute=59;//注意点同上
write_time(4,now.minute);
}
if(mode_num==6)
{
now.second--;
if(now.second<0)now.second=59;//注意点同上
write_time(7,now.second);
}
}
}
}
}
voiddisplay_temp()//显示温度子程序
{
uintwendu;//设置wendu变量来存放从18b20读取的温度
ucharA1,A2;//A1用来存放温度值的十位,A2存放个位
tmpchange();//启动温度转换
wendu=tmp();//读取温度值
A1=wendu/10;//求A1值
A2=wendu%10;//求A2值
gotoxy(2,10);
display_data(A1);//显示A1值
display_string(".");//用小数点分开个位和小数
write_date(int_to_char[A2]);//向lcd写数据,并且注意要转换A2数据类型
}
voidtimer0(void)interrupt1
{
TR0=0;
TL0=(TIMER0_COUNT&0X00FF);//设置Timer0低八位数值
TH0=(TIMER0_COUNT>>8);//设置Timer0高八位数值
TR0=1;
count++;
if(count==30)display_temp();//延时,当count=30时,显示温度,并延时
if(count==200)//当count自加到200时,开始判断此时时、分、秒的值,并进行转换
{
count=0;
now.second++;
if(now.second==60)//当秒达到60时,向分进位,且秒数置零
{
now.second=0;
now.minute++;
if(now.minute==60)//当分达到60时,向时进位,且分数置零
{
now.minute=0;
now.hour++;
if(now.hour==24)//当时达到24时,向天进位,且时数置零
{
now.hour=0;
today.day++;
if(today.day>monthday(today.year,today.month))//判断天数,当超过本月最大天数时,向月份进位,且天数置一
{
today.day=1;
today.month++;
if(today.month==13)//判断月份,当月份超过12时,向年份进位,月份置一
{
today.month=1;
today.year++;
}
write_riqi(4,today.month);//在位置4处,向lcd写月份
}
write_riqi(7,today.day);//在位置7处,向lcd写天数
gotoxy(1,14);
display_week();
}
write_time(1,now.hour);//在位置1处,向lcd写时数
}
write_time(4,now.minute);//在位置4处,向lcd写分数
}
write_time(7,now.second);//在位置7处,向lcd写秒数
}
}
voidmain()
{
SYSTEMTIMECurrentTime;
LcdInitiate();//初始化lcd
timer0_initialize();//初始化内部定时器
Initial_DS1302();//初始化DS1302
DateToStr(&CurrentTime);//从DS1302读取日期
TimeToStr(&CurrentTime);//从DS1302读取时间
gotoxy(1,1);
display_string(CurrentTime.DateString);//显示日期
gotoxy(1,10);
display_week();//显示周几
gotoxy(2,1);
display_string(CurrentTime.TimeString);//显示时间
gotoxy(2,10);
display_string("00.0C");//显示温度
while
(1)keyscan();
}
(二)DS1302时钟模块
#include
#include
#ifndef_REAL_TIMER_DS1302_2003_7_21_
#define_REAL_TIMER_DS1302_2003_7_21
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 51 单片机 设计 带有 测温 功能 电子 时钟 汇总