一、简介
此系统主要由AT89C51、DS18B20温度模块、LCD1602液晶显示屏、DS1302时钟模块和矩阵按键组成。
二、运行效果图
三、部分代码
#include
#include //包含_nop_()函数定义的头文件
#define uchar unsigned char
#define uint unsigned int
//以下是对1302的定义
sbit clk= P2^3; //实时时钟时钟线引脚
sbit IO= P2^2; //实时时钟数据线引脚
sbit rst =P2^1; //实时时钟复位线引脚
uchar second,minute,hour,week,day,month,year; //8421码表示的时间 高四位用于表示十位,低四位用于表示个位
char second1,minute1,hour1,week1,day1,month1,year1;//十进制表示的时间 也即普通意义下的时间
uchar read_byte(uchar com);
uchar readyear_byte(uchar com);
void write_byte(uchar com,uchar date);
void init_1302();
void readtime();
//以下是对lcd1602的定义
sbit wela=P2^6;
sbit dula=P2^7;
uchar table[]="0123456789";
sbit LCM_RS=P2^6; //寄存器选择位,将RS位定义为P2.6引脚
sbit LCM_EN=P2^5; //使能信号位,将E位定义为P2.5引脚
bit lcd_bz(void);
void write_com(unsigned char CMD);
void write_date(unsigned char dataW);
void init_1602();
void displaytime();
void delaynms(unsigned char n);
//以下是对按键调时程序的定义
sbit mode=P1^0; //调整闹钟或者时间时的选择按键
sbit plus=P1^1; //加1键
sbit minus=P1^2; //减1键
sbit s1=P1^3; //计算器和万年历切换键
void key();
void delay20ms();
//以下是对温度采集部分的定义
sbit DS=P2^0; //DS18B20数据端口
uchar code wendu[]="0123456789"; //利用一个温度表解决温度显示乱码
void write_byte(uchar com,uchar date); //写一个字节
void tmpDelay(int num); // 延时
void Init_DS18B20(); //初始化DS18B20
unsigned char ReadOneChar(); //读一个字节
void WriteOneChar(unsigned char dat); //写数据
unsigned int Readtemp(); //读温度
void display(); //显示温度
/**************************************************************
主程序
*************************************************************/
main()
{ init_1602(); //LCD1602初始化
while(1)
{readtime(); //读时间
displaytime(); //显示时间
key(); //调整时间键盘
display(); //读温度并显示
switchfunction();//调功能切换程序,若功能切换键按下,进入计算器显示模式
}
}
/*************DS18B20温度读取模块*************/
void tmpDelay(int num)//延时函数
{
while(num--) ;
}
void Init_DS18B20()//初始化ds1820
{
unsigned char x=0;
DS = 1; //DS复位
tmpDelay(8); //稍做延时
DS = 0; //单片机将DS拉低
tmpDelay(80); //精确延时 大于 480us
DS = 1; //拉高总线
tmpDelay(14);
x=DS; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
tmpDelay(20);
}
unsigned char ReadOneChar()//读一个字节
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DS = 0; // 给脉冲信号
dat>>=1;
DS = 1; // 给脉冲信号
if(DS) dat|=0x80;
tmpDelay(4);
}
return(dat);
}
void WriteOneChar(unsigned char dat)//写一个字节
{ char i;
for (i=8; i>0; i--) {
DS = 0; DS = dat&0x01; tmpDelay(5);
DS = 1; dat>>=1; }
}
unsigned int Readtemp()//读取温度
{
unsigned char a=0;
unsigned char b=0;
unsigned int t=0;
float tt=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器
a=ReadOneChar(); //连续读两个字节数据 //读低8位
b=ReadOneChar(); //读高8位
t=b;
t<<=8;
t=t|a; //两字节合成一个整型变量。
tt=t*0.0625; //得到真实十进制温度值,因为DS18B20可以精确到0.0625度,所以读回数据的最低位代表的是0.0625度
t= tt*10+0.5; //放大十倍,这样做的目的将小数点后第一位也转换为可显示数字,同时进行一个四舍五入操作。
return(t);
}
void display()
{
uint num; //定义的时候用uchar宏定义就会出错
uint shi,ge,xiaoshu; //这里的num,shi,ge,xiaoshu 必须用uint无符号整数来表示,用uchar字符型则显示错误
num=Readtemp();
shi=num/100; ge=num/10%10; xiaoshu=num%10; //
write_com(0x80+0x40+0xa); write_date(wendu[shi]);
write_com(0x80+0x40+0xb); write_date(wendu[ge]);
write_com(0x80+0x40+0xc); write_date(0x2e);
write_com(0x80+0x40+0xd); write_date(wendu[xiaoshu]);
write_com(0x80+0x40+0xe); write_date(0xdf);
write_com(0x80+0x40+0xf); write_date(0x43);
}