当前位置:文档之家› ds18b20测温加ds1302时钟

ds18b20测温加ds1302时钟

#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit SCLK=P1^7;
sbit IO=P3^3;
sbit RST=P3^2;
sbit LCD_RS=P2^2;
sbit LCD_RW=P2^3;
sbit LCD_E=P2^4;
sbit LCD_BF=P0^7;
sbit DQ=P1^2;
sbit s1=P1^0;
sbit s2=P1^1; //addkey
sbit s3=P1^2; //minuskey //温度输入口
uint h;
uint temp;
uchar num=0;

uchar design[]="Designed by YZH";

uchar zifu[]={0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00,
0x0e,0x11,0x10,0x10,0x10,0x11,0x0e,0x00};

uchar code ditab[16]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04, //温度小数部分用查表法//
0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};
uchar data temp_data[2]={0x00,0x00}; //读出温度暂放
uchar data display[6]={0x00,0x00,0x00,0x00,0x00,0x00}; //显示单元数据,共4个数据和一个运算暂用

uchar time[8]; //存储当前时间
//uchar week[5]={"Week"};
uchar Date[10];
//read_1302_add[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
//write_1302_add[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
//lcd_date_pose[]={0x82,0x}
/*****************函数声明*************/
void delayu(uchar);
void delay(uint);
void lcd_busy(void);
void lcd_writecmd(uchar);
void init_lcd(void);
void lcd_writedat(uchar);
void lcd_write_CGRAM(void);
void lcd_write_start(void);
void ds1302write_byte(uchar);
uchar ds1302read_byte(void);
void write_ds1302(uchar,uchar);
uchar read_ds1302(uchar);
void init_ds1302(void);
void displaytime(void);
void displayw(uchar w[4]);
void displayweek(void);
void displaydat(void);
void init_ds18b20(void);
uchar ds18b20read_byte(void);
uchar ds18b20read_byte(void);
read_temp();
work_temp(uint);

///////lcd显示主函数//////

void main(void)
{
uchar i;
init_lcd();
lcd_write_start();
init_lcd();
lcd_write_CGRAM();
init_ds1302();
init_ds18b20();
while(1)
{
displaytime(); //显示时间
displaydat(); //显示日期
displayweek(); //显示星期
work_temp(read_temp()); //处理温度数据
lcd_writecmd(0x80+0x49); //写显示位置
for(i=0;i<5;i++)
{
lcd_writedat(display[4-i]); //显示当前温度值
}
}
}
void lcd_write_start(void)
{
uchar j;
lcd_writecmd(0x8e);
for(j=0;j<15;j++)
{
lcd_writedat(design[j]);
lcd_writecmd(0x07);
delay(200);
}
delay(1000);
}

void lcd_write_CGRAM(void)
{
uchar i;
lcd_writecmd(0x40); //把数据写入CGRAM
for(i=0;i<16;i++)
{
lcd_writedat(zifu[i]);
}
lcd_writecmd(0x80+0x4e); //写两个字符
for(i=0;i<2;i++)
{
lcd_writedat(i);
}
}

void delayu(uchar k)
{
while(k--)
_nop_();

}
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=120;j>0;j--);
}

void lcd_busy(void)
{
do
{
LCD_E=0;
LCD_RS=0;
LCD_RW=1;
P0=0xff;
LCD_E=1;
}
while(LCD_BF==1);
LCD_E=0;
}

void lcd_writecmd(uchar d

at)
{
lcd_busy();
LCD_RS=0; //指令
LCD_RW=0; //写入
LCD_E=0;
delayu(2);
P0=dat; //允许
delayu(4); //
LCD_E=1;
delayu(4);
LCD_E=0;
delayu(4); //
}

void init_lcd(void) //chu shi hua
{
delay(15);
lcd_writecmd(0x38);
delay(5);
lcd_writecmd(0x38);
delay(5);
lcd_writecmd(0x38);
lcd_writecmd(0x38);
lcd_writecmd(0x08);
lcd_writecmd(0x01);
lcd_writecmd(0x06);
lcd_writecmd(0x0c);
}

void lcd_writedat(uchar dat)
{
lcd_busy();
LCD_RS=1; //数据
LCD_RW=0; //写入
LCD_E=0;
delayu(2); //允许
P0=dat;
delay(4);
LCD_E=1;
delayu(4);
LCD_E=0;
delayu(4);

}
//////////////DS1302子程序///////////////
////////////////////////////////////////
//向DS1302写入一个字节指令//
void ds1302write_byte(uchar cmd)
{
uchar i; //先准备好数据然后再写入
for(i=0;i<8;i++)//也就是先把数据送到总线上,然后时钟脉冲给一个上升沿
{ //时序很重要……
SCLK=0;
IO=cmd&0x01; //准备好数据……等待上升沿到来
SCLK=1; //上升沿到来……写入数据
cmd>>=1;
}
}
//从DS1302读出一个字节
uchar ds1302read_byte(void) //读时序先来下降沿然后读出数据
{
uchar i,dat;
for(i=0;i<8;i++)
{
dat>>=1;
SCLK=1; //先形成下降沿,等待数据
SCLK=0;
if(IO) //读出数据
dat=dat|0x80;
}
return dat;
}
/////向指定地址写入数据////////
//单字节写数据函数,向DS1302写入一个字节的数据
void write_ds1302(uchar add,uchar dat)
{
RST=0; //看时序图
SCLK=0;
RST=1;
ds1302write_byte(add);
ds1302write_byte(dat);
SCLK=1;
RST=0;
}
/////从指定地址读出数据///////
//单字节读数据函数//
uchar read_ds1302(uchar add)
{
uchar k;
RST=0;
SCLK=0;
RST=1;
ds1302write_byte(add);
k=ds1302read_byte();
SCLK=1;
RST=0;
return k;
}

void init_ds1302(void) //显示初始时间2011-08-12-周五—18-17-00
{
SCLK=0;
IO=0;
RST=0;
write_ds1302(0x8e,0x00);
write_ds1302(0x80,0x00); //秒
write_ds1302(0x82,0x17); //分
write_ds1302(0x84,0x18); //小时
write_ds1302(0x86,0x12); //日
write_ds1302(0x88,0x08); //月
write_ds1302(0x8a,0x05); //星期
write_ds1302(0x8c,0x11); //年
write_ds1302(0x90,0xa5); //允许慢速充电
write_ds1302(0x8e,0x80);
}

void displaytime(void) //显示时间函数
{
uchar i;
uchar sec,min,hour;
sec=read_ds1302(0x81);
min=read_ds1302(0x83);
hour=read_ds1302(0x85); //读出的是BCD码

time[7]=sec%16+'0';
time[6]=sec/16+'0'; //BCD码转换为ASCII码
time[5]=0x3a;
time[4]=min%16+0x30;
time[3]=min/16+0x30;
time[2]=0x3a;
time[1]=hour%16+0x30;
time[0]=hour/16+0x30;

lcd_writecmd(0x80+0x40);
for(i=0;i<8;i++)
{
lcd_writedat(time[i]);
}
}

//显示周子函数
void displayw(uchar w[4])
{
uchar i;
lcd_writecmd(0x8b);
for(i=0;i<4;i++)

{
lcd_writedat(w[i]);
}
}

void displayweek(void) //显示星期函数
{
// uchar i;
uchar day;
day=read_ds1302(0x8b);
switch(day%16)
{
case 1:displayw(" Mon");break;
case 2:displayw(" Tus");break;
case 3:displayw(" Wen");break;
case 4:displayw("Thur");break;
case 5:displayw(" Fri");break;
case 6:displayw(" Sat");break;
case 7:displayw(" Sun");break;
}
/* for(i=0;i<4;i++)
{
write_lcd(week[i]);
}
write_cmd(0x8f);
write_lcd(day%16+0x30); */
}

void displaydat(void)
{
uchar i;
uchar year,month,date;
date=read_ds1302(0x87);
month=read_ds1302(0x89);
year=read_ds1302(0x8d);
Date[9]=2+'0';
Date[8]=0x30;
Date[7]=year/16+0x30;
Date[6]=year%16+0x30;
Date[5]=0x2d;
Date[4]=month/16+0x30;
Date[3]=month%16+0x30;
Date[2]=0x2d;
Date[1]=date/16+0x30;
Date[0]=date%16+0x30;

lcd_writecmd(0x80);
for(i=0;i<10;i++)
{
lcd_writedat(Date[9-i]);
}
}

//DS18B20初始化子函数//
void init_ds18b20(void)
{
char presence=1;
while(presence)
{
while(presence)
{
DQ=1;_nop_();_nop_();//从高拉倒低
DQ=0;
delayu(50); //550 us
DQ=1;
delayu(6); //66 us
presence=DQ; //presence=0 复位成功,继续下一步
}
delayu(45); //延时500 us
presence=~DQ;
}
DQ=1; //拉高电平
}
//
//
/****************DS18B20写命令函数************************/
//向1-WIRE 总线上写1个字节
void ds18b20write_byte(uchar val)
{
uchar i;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_(); //从高拉倒低
DQ=0;_nop_();_nop_();_nop_();_nop_(); //5 us
DQ=val&0x01; //最低位移出
delayu(6); //66 us
//val=val/2;
val>>=1; //右移1位
}
DQ=1;
delay(1);
}
//
/****************DS18B20读1字节函数************************/
//从总线上取1个字节
uchar ds18b20read_byte(void)
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
DQ=1;_nop_();_nop_();
value>>=1;
DQ=0;_nop_();_nop_();_nop_();_nop_(); //4 us
DQ=1;_nop_();_nop_();_nop_();_nop_(); //4 us
if(DQ)
value|=0x80;
delayu(6); //66 us
}
DQ=1;
return(value);
}
//
/****************读出温度函数************************/
//
read_temp()
{
init_ds18b20(); //总线复位
delay(200);
ds18b20write_byte(0xcc); //发命令
ds18b20write_byte(0x44); //发转换命令
init_ds18b20();
delay(1);
ds18b20write_byte(0xcc); //发命令
ds18b20write_byte(0xbe);
temp_data[0]=ds18b20read_byte(); //读温度值的第字节
temp_data[1]=ds18b20read_byte(); //读温度值的高字节
temp=temp_data[1];
temp<<=8;


temp=temp|temp_data[0]; // 两字节合成一个整型变量。
return temp; //返回温度值16位的数据
}
//温度数据处理函数
//二进制高字节的低半字节和低字节的高半字节组成一字节,这个
//字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩
//下的低字节的低半字节转化成十进制后,就是温度值的小数部分
work_temp(uint tem) //数据处理 存入数组
{
uchar n=0;
if(tem&0xf000) // 温度值正负判断
{
temp=~temp+1;
n=1;
} // 负温度求补码,标志位置1
display[5]=tem&0x0f; // 取小数部分的值
display[0]=ditab[display[5]]+0x30; // 存入小数部分显示值//查表得到
display[5]=tem>>4; // 取中间八位,即整数部分的值
display[4]=display[5]/100+0x30; // 取百位数据暂存
display[1]=display[5]%100; // 取后两位数据暂存
display[3]=display[1]/10+0x30; // 取十位数据暂存
display[2]=display[1]%10+0x30;
display[1]=0x2e;
/*符号位判断显示*/
if(display[4]==0x30) //最高位为零时!display[3]=1;条件成立执行括号内语
{
display[4]=0x20; //最高位为0时不显示(显示空格)
if(display[3]==0x30)
{display[3]=0x20;} //次高位为0时不显示
}
if(n)
{display[4]=0x2d;} //负温度时最高位显示"-"
}


//按键功能




相关主题
相关文档 最新文档