51单片机和lcd12864与ds1302 ds18b20 1000310116李强蓝志腾.docx
《51单片机和lcd12864与ds1302 ds18b20 1000310116李强蓝志腾.docx》由会员分享,可在线阅读,更多相关《51单片机和lcd12864与ds1302 ds18b20 1000310116李强蓝志腾.docx(44页珍藏版)》请在冰豆网上搜索。
51单片机和lcd12864与ds1302ds18b201000310116李强蓝志腾
作品介绍
基于红外的数字钟和温度计的设计
作者:
李强蓝志腾
摘要:
本设计利用SCT90C516RD+单片机设计了一款具有时钟、温度、闹铃并可用红外遥控器进行时间、日历、温度、闹铃设置功能的红外遥控多功能数字钟。
液晶显示用12864,界面清晰美观大方。
红外遥控及检测部分有(38k)小型红外21键发射模块及一体化接收头组成,操作简单方便,操作距离空旷地可达6m,时钟模块才采用DS1302为时钟源,温度模块为DS18B20温度传感器,电源模块由两节可充电池提供。
关键字:
SCT90C516RD+、红外遥控、时钟日历、12864液晶.,温度DS18B20
一、总体设计方案
采用SCT90C516RD+为主控芯片、DS1302为时钟源、DS18B20为温度传感器、(38K)小型红外21键发射模块为红外发射模块、一体化红外接收头作为接收模块、显示模块利用蓝屏的12864液晶,总体方案图如图1-1所示
图1-1系统总体方案设计框图
二、硬件电路设计
1、主控器模块
以STC90C516RD+为主控芯片构成最小系统,包括STC90C516RD+/复位电路、晶振电路、电源接口及I/O口的上拉及输出接口。
如图2-1所示
图2-1最小系统图
2时钟和温度模块
时钟和温度模块由时钟芯片DS1302外加32.768k的晶振构成时钟源,由DS18B20温度传感器采集温度信息。
如图2-2所示。
图2-1时钟和温度模块
3.红外和闹钟模块
红外和脑子模块由三极管驱动蜂鸣器构成,红外接收部分由一体化接收头构成。
如图2-3所示
图2-3温度和闹钟模块
4.显示模块
显示模块由LCD12864构成如图2-4所示
图2-4显示模块
三.软件设计
软件部分:
主函数:
#include
#include
#include
#include
ucharwelcome_flag=0,set_flag=0,exit_flag=0,alarm_flag=0;
uchardisp[5];
ucharrow_num=1,line_num=2;//lcd上的显示坐标x,y
ucharmodel=0;
voidmain()
{
lcd_init();//初始化lcd
timer0init();//定时计数器中断初始化
Ex0_init();//外部中断1初始化
init_ds18b20();
set_rtc();
while
(1)
{
if(model==0)
{
start_lcd();//按上下键选择模式或者模式键进入相应的模块
}
if(model==1)
{
xianshi_lcd();
}
}
}
1.时钟部分:
DS1302.H
#include
#include
#ifndef_DS1302_H_
#define_DS1302H_
#defineuintunsignedint
#defineucharunsignedchar
sbitsck=P1^5;//时钟
sbitsda=P1^6;//数据
sbitrst1=P1^7;//DS1302复位
externvoidwrite_ds1302_byte(ucharadddat);//单字节写入数据或者地址
externvoidwriteds1302(ucharadd,intdat);//写地址数据
externucharreadds1302_byte(ucharadd);//读取一个字节的数据
externvoidset_rtc();//设置初始时间
externvoidread_rtc();//读时钟数?
voidrtc_display_sfm();//显示时分胿oidrtc_display_nyr();//显示年月日
voidrtc_display_week();//显示星期
externvoidshow_time();//显示时间
externvoidjudge_alarm();
externvoidinit_set_time_sign();
externvoidset_over_time_show();
#endif
DS1302.C:
#include
#include
uchardisdata[5];
ucharcodeLine17[]={"温度℃"};
externuinttemper;//温度值
voiddelay(uintn)
{
while(n--);
}
voidinit_ds18b20()
{
uchartmp;
ds18b20=1;
delay(8);
ds18b20=0;
delay(90);//750us左右
ds18b20=1;
delay(8);
tmp=ds18b20;
delay(5);
}
voidwrite_ds18b20(uchardat)
{
uchari;
for(i=0;i<8;i++)
{
ds18b20=0;
ds18b20=dat&0x01;
delay(4);
ds18b20=1;
dat>>=1;
}
delay(4);
}
ucharread_ds18b20()
{
uchari,value;
for(i=0;i<8;i++)
{
ds18b20=0;
value>>=1;
ds18b20=1;//释放总线
if(ds18b20==1)
value|=0x80;
delay(4);
}
returnvalue;
}
ucharget_temper()//读取温度
{
uchara,b;//用于存放温度
floattt;
init_ds18b20();//初始化
write_ds18b20(0xcc);//跳过rom
write_ds18b20(0x44);//启动温度装换
//delay1ms(300);
init_ds18b20();
write_ds18b20(0xcc);
write_ds18b20(0xbe);//读取温度
a=read_ds18b20();//低八位
b=read_ds18b20();
temper=b;//temp为温度值UINT16bit
temper<<=8;//两个字节组合到一起
temper=temper|a;
tt=temper*(0.0625);//temp/16则是温度的真实值tt.7位整数,4位小数
temper=tt*10+0.5;//扩大十倍取出了第一位小数
return(temper);
}
voidtemper_display(uinttemp)
{
uchari;
disdata[0]=temp/1000+0x30;
disdata[1]=temp%1000/100+0x30;
disdata[2]=temp%100/10+0x30;
disdata[3]=0x2e;
disdata[4]=temp%10+0x30;
if(disdata[0]==0x30)
{
disdata[0]=0x20;//百位为零,不显示
if(disdata[1]==0x30)
{
disdata[1]=0x20;//百位为零,而且十位也为零,不显示
}
}
poslcd(4,0);
for(i=0;i<4;i++)
{
write_dat(Line17[i]);
}
poslcd(4,2);
for(i=1;i<5;i++)
{
write_dat(disdata[i]);
}
poslcd(4,4);
for(i=4;i<6;i++)
{
write_dat(Line17[i]);
}
}
2.显示部分:
LCD12864.H
#include
#include
#ifndef__LCD12864_H__
#define__LCD12864H__
#defineuintunsignedint
#defineucharunsignedchar
#definelcdP0//lcd数据线选择P0口
sbitrs=P1^1;
sbitrw=P1^2;
sbiten=P1^3;
sbitpsb=P2^4;//选择并口方式
sbitrst=P2^2;
/**************函数声明**********/
voiddelay1ms(uint);
voiddelay_ms(int);
externvoidlcd_init(void);//初始化lcd
externvoidwriteinst(uchar);//写入指令
externvoidwrite_dat(uchar);//写入数据
externbitcheckbf(void);//检查忙绿
externvoidposlcd(ucharx,uchary);//写入位置
//externvoidwrite_inst_dat(uchar,int);//写命令数据函数
externvoidmodel_row(uchar,uchar,uchar);
#endif
LCD12864.C
#include
voiddelay1ms(uintx)//延时x*1ms
{
inti,j;
for(i=0;ifor(j=0;j<120;j++);
}
voiddelay_ms(intx)
{
inti,j;
for(i=0;ifor(j=0;j<60;j++);
}
voidlcd_init(void)//初始化
{
psb=1;
rst=0;
delay1ms(3);
rst=1;
delay1ms(5);
writeinst(0x30);//设置功能采用8位数据传输基本指令00110000
delay1ms(40);//延时40ms
writeinst(0x0c);//显示开关控制
writeinst(0x01);//清屏
delay1ms(10);//延时10ms
}
bitcheckbf()//检查忙绿函数
{
bittemp;
rs=0;
rw=1;
en=1;
temp=(bit)(P0&0x80);
_nop_();
en=0;
_nop_();
return(temp);
}
voidwriteinst(ucharinst)//写指令函数
{
while(checkbf());
rs=0;
rw=0;
en=0;
delay1ms(10);
P0=inst;
_nop_();
_nop_();
en=1;
delay1ms(5);
en=0;
}
voidwrite_dat(uchardat)//写数据函数
{
while(checkbf());
rs=1;
rw=0;
en=0;
delay1ms(10);
P0=dat;
en=1;
delay1ms(5);
en=0;
}
voidposlcd(ucharx,uchary)//写入位置函数
{
ucharpos;
if(x==1)
{
pos=0x80;
}
elseif(x==2)
{
pos=0x90;
}
elseif(x==3)
{
pos=0x88;
}
elseif(x==4)
{
pos=0x98;
}
pos=pos+y;
writeinst(pos);//写入显示的位置
//writeinst(0x0f);//开启光标
}
3.红外部分:
IR.H
/*****红外遥控定义的引脚为P3^4;采用外部中断1******/
#ifndef_IR_H_
#define_IRH_
externvoidtimer0init();//定时器0初始化
externvoidint0init();//中断0初始化
externvoidirpros();//红外处理函数
externvoidir_display();//红外按键显示
externvoidreceive();//红外读取成功
externvoidEx0_init();//外部中断1
externvoidkeyscan();//按键扫描
externvoidstart_lcd();//开始屏幕显示内容
externvoidalarm(int,int);
externvoidxianshi_lcd();
externvoidalter_time();
#endif
IR.C
#include
#include
ucharirtime;//计数0-255
ucharstartflag;//检测到引导码标志位
ucharirreceiveok;//红外接收完成标志位
ucharirbitnum;//用于计数总共有33位码
ucharirproseok;//将32位码存放到ircode[i]后完成标志位
ucharirdata[33];//存放33位
externucharircode[4];
voidtimer0init()
{
TMOD=0X02;
TH0=0X00;
TL0=0X00;
EA=1;
ET0=1;
TR0=1;
}
voidEx0_init()
{
IT0=1;//设置为负边缘触发
EA=1;
EX0=1;
}
voidtimer0(void)interrupt1
{
irtime++;//255
}
voidEx0()interrupt0
{
if(startflag)
{
if(irtime>32)//9ms/0.256=35存在载波变形检测到引导码
{
irbitnum=0;//把红外时间清0准备记录下一次的时间
}
irdata[irbitnum]=irtime;
irtime=0;//每记录一次都要清0
irbitnum++;
if(irbitnum==33)//所有数据记录完成
{
irbitnum=0;
irreceiveok=1;
}
}
else
{
startflag=1;
irtime=0;
}
}
voidirpros()
{
uchark=1,j,i,temp;
for(j=0;j<4;j++)
{
//第一位数据不需要
for(i=0;i<8;i++)
{
temp=temp>>1;
if(irdata[k]>6)
{
temp=temp|0x80;
}
k++;
}
ircode[j]=temp;
}
irproseok=1;
}
voidreceive()//成功接收到引导码并转化到display()中
{
if(irreceiveok)
{
irpros();
irreceiveok=0;
}
if(irproseok)
{
ir_display();
irproseok=0;
}
}
4.温度部分:
DS18B20.H
#include
#include
#ifndef__DS18B20_H__
#define__DS18B20H__
#defineuintunsignedint
#defineucharunsignedchar
sbitds18b20=P1^0;//温度引脚
externvoiddelay(uint);//延时1us
externvoidinit_ds18b20();//初始化ds18b20
externvoidwrite_ds18b20(uchar);//写字节
externucharread_ds18b20();//读取一个字节
externucharget_temper();//得到温度
externvoidtemper_display(uint);//温度显示处理
#endif
DS18B20.C
#include
#include
uchardisdata[5];
ucharcodeLine17[]={"温度℃"};
externuinttemper;//温度值
voiddelay(uintn)
{
while(n--);
}
voidinit_ds18b20()
{
uchartmp;
ds18b20=1;
delay(8);
ds18b20=0;
delay(90);//750us左右
ds18b20=1;
delay(8);
tmp=ds18b20;
delay(5);
}
voidwrite_ds18b20(uchardat)
{
uchari;
for(i=0;i<8;i++)
{
ds18b20=0;
ds18b20=dat&0x01;
delay(4);
ds18b20=1;
dat>>=1;
}
delay(4);
}
ucharread_ds18b20()
{
uchari,value;
for(i=0;i<8;i++)
{
ds18b20=0;
value>>=1;
ds18b20=1;//释放总线
if(ds18b20==1)
value|=0x80;
delay(4);
}
returnvalue;
}
ucharget_temper()//读取温度
{
uchara,b;//用于存放温度
floattt;
init_ds18b20();//初始化
write_ds18b20(0xcc);//跳过rom
write_ds18b20(0x44);//启动温度装换
//delay1ms(300);
init_ds18b20();
write_ds18b20(0xcc);
write_ds18b20(0xbe);//读取温度
a=read_ds18b20();//低八位
b=read_ds18b20();
temper=b;//temp为温度值UINT16bit
temper<<=8;//两个字节组合到一起
temper=temper|a;
tt=temper*(0.0625);//temp/16则是温度的真实值tt.7位整数,4位小数
temper=tt*10+0.5;//扩大十倍取出了第一位小数
return(temper);
}
voidtemper_display(uinttemp)
{
uchari;
disdata[0]=temp/1000+0x30;
disdata[1]=temp%1000/100+0x30;
disdata[2]=temp%100/10+0x30;
disdata[3]=0x2e;
disdata[4]=temp%10+0x30;
if(disdata[0]==0x30)
{
disdata[0]=0x20;//百位为零,不显示
if(disdata[1]==0x30)
{
disdata[1]=0x20;//百位为零,而且十位也为零,不显示
}
}
poslcd(4,0);
for(i=0;i<4;i++)
{
write_dat(Line17[i]);
}
poslcd(4,2);
for(i=1;i<5;i++)
{
write_dat(disdata[i]);
}
poslcd(4,4);
for(i=4;i<6;i++)
{
write_dat(Line17[i]);
}
}
按键操作部分:
/********有关按键操作部分********/
#include
#include
#include
#include
sbitbell=P3^5;//蜂鸣器低电平将一直响
ucharsum=0;//用于存放两个数低位、高位
ucharplus=0,sub=0;//使能键遥控按键加减
ucharpower_num=0,flag_num=0;//判断有第一次数值键按下
ucharalarm_clock;
ucharnum=1;
ucharircode[4];
tab[11];
uinttemper;
ucharset_time_flag;
uchartime_data1_num=6;
ucharshineng_flag=1;
ucharcount_num=0;
externinttime_data1[7];//存放修改设置的时间把设置的时间赋给time_data[7]
externinttime_data2[3];//设置闹钟的时间和time_data[2];进行对比如果一样开启闹钟
/**菜单界面*******/
ucharcodeLine1[10]={"1.WELCOME!
"};
ucharcodeLine2[9]={"2.SETTIME"};
ucharcodeLine3[7]={"3.ALARM"};
ucharcodeLine4[6]={"4.E