求AT89C51单片机和4 x DS18B20温度传感器、LCD1602液晶显示的数字温度计加SD Card储存温度资料.
2011-08-13
展开全部
#include <reg52.h>
#include <math.h> //Keil library
#include <stdio.h> //Keil library
#include <INTRINS.H>
#define uchar unsigned char
#define uint unsigned int
#define display1 0xfe //数码管1从左至右
#define display2 0xfd //数码管2从左至右
#define display3 0xfb //数码管3从左至右
#define display4 0xf7 //数码管4从左至右
#define display5 0xef //数码管5从左至右
#define display6 0xdf //数码管6从左至右
#define display7 0xbf //数码管7从左至右
#define display8 0x7f //数码管8从左至右
sbit led=P1^5;
sbit DQ=P3^6; //根据实实际情况设定
sbit setth=P1^0;//设定 th
sbit up=P1^1;//加
sbit down=P3^2;//减
sbit beep= P3^3;
uchar tempint,f,bb,tempth,temptl,th,tl,beepflag; //温度整数部分和小数部分
int tempdf,c;
code unsigned char ledmap[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0xbf};
code unsigned char ledmap1[]={0x40,0x79,0x24,0x30,
0x19,0x12,0x02,0x78,0x00,0x10};
//7段数码管0~9数字的共阳显示代码和负号位代码(最后一位)
void set_ds18b20(); //初始化DS18B20子程序
void get_temperature(); //获得温度子程序
void read_ds18b20(); //读DS18B20子程序
void write_ds18b20(uchar command); //向DS18B20写1字节子程序
void delayms(uchar count); //延时count毫秒子程序
void disp_temp(tempint,tempdf); //显示温度子程序
//***********************初始化DS18B20子程序**********************************
//****************************************************************************
void set_ds18b20()
{
while(1)
{
uchar delay,flag;
flag=0;
DQ=1;
delay=1;
while(--delay);
DQ=0; //数据线置低电平
delay=250;
while(--delay); //低电平保持500us
DQ=1; //数据线置高电平
delay=30;
while(--delay); //高电平保持60us
while(DQ==0) //判断DS18B20是否发出低电平信号
{
delay=210; //DS18B20响应,延时420us
while(--delay);
if(DQ) //DS18B20发出高电平初始化成功,返回
{
flag=1; //DS18B20初始化成功标志
//初始化成功LED标志
break;
}
}
if(flag) //初始化成功,再延时480us,时序要求
{
delay=240;
while(--delay);
break;
}
}
}
//***********************获得温度子程序***************************************
//****************************************************************************
void get_temperature() //温度转换、获得温度子程序
{
set_ds18b20(); //初始化DS18B20
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0x44); //发温度转换命令
// delayms(750);
disp_temp(tempint,tempdf); //显示温度,等待AD转换
set_ds18b20();
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0xbe); //发出读温度命令
read_ds18b20(); //将读出的温度数据保存到tempint和tempdf处
}
//***********************读DS18B20子程序***************************************
//****************************************************************************
void read_ds18b20()
{
uchar delay,i,j,k,temp,temph,templ;
j=4; //读2位字节数据
do
{
for(i=8;i>0;i--) //一个字节分8位读取
{
temp>>=1; //读取1位右移1位
DQ=0; //数据线置低电平
delay=1;
while(--delay);
DQ=1; //数据线置高电平
delay=4;
while(--delay); //延时8us
if(DQ) //读取1位数据
temp|=0x80;
delay=25; //读取1位数据后延时50us
while(--delay);
}
if(j==4)
templ=temp;//读取的第一字节存templ
if(j==3)
temph=temp; //读取的第二字节存temph
if(j==2)
tempth=temp; //读取的第3字节存tempth TH的值
if(j==1)
temptl=temp; //读取的第4字节存tempth TL的值
}while(--j);
f=0;
if((temph & 0xf8)!=0x00) //若温度为负的处理,对二进制补码的处理
{
f=1; //为负温度f置1
temph=~temph;
templ=~templ;
k=templ+1;
templ=k;
if(k>255)
{
temph++;
}
}
tempdf=templ & 0x0f; //将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdf
c=(tempdf*625);
tempdf=c;
templ>>=4; //
temph<<=4; //转化成字节温度
tempint=temph|templ;//两字节合并为一个字节
if (tempint>th|tempint==th|tempint<tl|tempint==tl)
beepflag=1;
else
beepflag=0;
}
//***********************写DS18B20子程序***************************************
//****************************************************************************
void write_ds18b20(uchar command)
{
uchar delay,i;
for(i=8;i>0;i--) //将一字节数据一位一位写入
{
DQ=0; //数据线置低电平
delay=6; //延时12us
while(--delay);
DQ=command&0x01; //将数据放置在数据线上
delay=25; //延时50us
while(--delay);
command=command>>1; //准备发送下一位数据
DQ=1; //发送完一位数据,数据线置高电平
}
}
//***********************显示子程序***************************************
//****************************************************************************
void disp_temp( tempint,tempdf)
{
uchar tempinth,tempintl,tempinbai,shifen,baifen,gefen,qianfen;
if (bb==1)
{
tempinbai=th/100;
tempinth=(th%100)/10;
tempintl=th%10; //整数取模
gefen=0/1000;
shifen=0%1000/100;
baifen =0%100/10;
qianfen=0%10; //小数取模
}
else if(bb==2)
{ tempinbai=tl/100;
tempinth=(tl%100)/10;
tempintl=tl%10; //整数取模
gefen=0/1000;
shifen=0%1000/100;
baifen =0%100/10;
qianfen=0%10; //小数取模
}
else
{
tempinbai=tempint/100;
tempinth=(tempint%100)/10;
tempintl=tempint%10; //整数取模
gefen=tempdf/1000;
shifen=tempdf%1000/100;
baifen =tempdf%100/10;
qianfen=tempdf%10; //小数取模
}
if (f==0)
{
P0=display1; //符号位
P2=ledmap[0];
}
else
{
P0=display1; //符号位
P2=ledmap[10];
}
delayms(2);
P0=display2;
P2=ledmap[tempinbai]; //开百位
delayms(2);
P0=display3;
P2=ledmap[tempinth];//开十位
delayms(2);
P0=display4;
P2=ledmap1[tempintl];//开个位
delayms(2);
P0=display5;
P2=ledmap[gefen];//开个分位
delayms(2);
P0=display6;
P2=ledmap[shifen]; //开十分位
delayms(2);
P0=display7;
P2=ledmap[baifen]; //开百分位
delayms(2);
P0=display8;
P2=ledmap[qianfen];//开千分位
}
//*******************************************************************/
//* 蜂鸣器响一声 */
//*******************************************************************/
void beep_st()
{
if (beepflag==1)
{ beep=0;
delayms(1000) ;
beep=1;
}
else
beep=1;
}
//***********************延时count ms子程序***************************************
//****************************************************************************
void delayms(uchar count) //延时count ms子程序
{
uchar i,j;
do
{
for(i=5;i>0;i--)
for(j=98;j>0;j--);
}while(--count);
}
//****************************************************************************
void keyscan() //键盘扫描
{
if(setth==0)
{
delayms(1);
}
if(setth==0)
{
bb++;
while(!setth); //循环在此 非0=1
}
if(bb==1)
{
if(up==0)
{
delayms(1);
}
if(up==0)
{
disp_temp(th,tempdf);
if(th<125)
{th++;}
while(!up)//非0=1
{
disp_temp(th,tempdf);
}
}
if(down==0)
{
delayms(1);
}
if(down==0)
{
disp_temp(th,tempdf);
if(th!=0) //不等于0为真执行
{
th--;
while(!down) // down为(非0=1)循环执行
{
disp_temp(th,tempdf);
}
}
}
}
if(bb==2)
{
if(up==0)
{
delayms(1);
}
if(up==0)
{
disp_temp(tl,tempdf);
if(tl<125)
{tl++;}
while(!up)//非0=1
{
disp_temp(th,tempdf);
}
}
if(down==0)
{
delayms(1);
}
if(down==0)
{
disp_temp(th,tempdf);
if(tl!=0) //不等于0为真执行
{
tl--;
while(!down) // down为(非0=1)循环执行
{
disp_temp(tl,tempdf);
}
}
}
}
if(bb==3)
{bb=0;
set_ds18b20(); //初始化DS18B20
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0x4e); //发温度转换命令
write_ds18b20(th); //写TH 3
write_ds18b20(tl);
// write_ds18b20(0x7f);
set_ds18b20(); //初始化DS18B20
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0x48);
}
}
void main()
{ set_ds18b20();
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0xbe); //发出读温度命令
read_ds18b20(); //将读出的数据
th=tempth; //将TH读到单片机
tl=temptl;
SP=0x60; //设置堆栈指针
bb=0;
beepflag=0;
while(1)
{
keyscan();
get_temperature(); //获得温度
disp_temp(tempint,tempdf); //显示温度
beep_st();
}
}
#include <math.h> //Keil library
#include <stdio.h> //Keil library
#include <INTRINS.H>
#define uchar unsigned char
#define uint unsigned int
#define display1 0xfe //数码管1从左至右
#define display2 0xfd //数码管2从左至右
#define display3 0xfb //数码管3从左至右
#define display4 0xf7 //数码管4从左至右
#define display5 0xef //数码管5从左至右
#define display6 0xdf //数码管6从左至右
#define display7 0xbf //数码管7从左至右
#define display8 0x7f //数码管8从左至右
sbit led=P1^5;
sbit DQ=P3^6; //根据实实际情况设定
sbit setth=P1^0;//设定 th
sbit up=P1^1;//加
sbit down=P3^2;//减
sbit beep= P3^3;
uchar tempint,f,bb,tempth,temptl,th,tl,beepflag; //温度整数部分和小数部分
int tempdf,c;
code unsigned char ledmap[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90,0xbf};
code unsigned char ledmap1[]={0x40,0x79,0x24,0x30,
0x19,0x12,0x02,0x78,0x00,0x10};
//7段数码管0~9数字的共阳显示代码和负号位代码(最后一位)
void set_ds18b20(); //初始化DS18B20子程序
void get_temperature(); //获得温度子程序
void read_ds18b20(); //读DS18B20子程序
void write_ds18b20(uchar command); //向DS18B20写1字节子程序
void delayms(uchar count); //延时count毫秒子程序
void disp_temp(tempint,tempdf); //显示温度子程序
//***********************初始化DS18B20子程序**********************************
//****************************************************************************
void set_ds18b20()
{
while(1)
{
uchar delay,flag;
flag=0;
DQ=1;
delay=1;
while(--delay);
DQ=0; //数据线置低电平
delay=250;
while(--delay); //低电平保持500us
DQ=1; //数据线置高电平
delay=30;
while(--delay); //高电平保持60us
while(DQ==0) //判断DS18B20是否发出低电平信号
{
delay=210; //DS18B20响应,延时420us
while(--delay);
if(DQ) //DS18B20发出高电平初始化成功,返回
{
flag=1; //DS18B20初始化成功标志
//初始化成功LED标志
break;
}
}
if(flag) //初始化成功,再延时480us,时序要求
{
delay=240;
while(--delay);
break;
}
}
}
//***********************获得温度子程序***************************************
//****************************************************************************
void get_temperature() //温度转换、获得温度子程序
{
set_ds18b20(); //初始化DS18B20
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0x44); //发温度转换命令
// delayms(750);
disp_temp(tempint,tempdf); //显示温度,等待AD转换
set_ds18b20();
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0xbe); //发出读温度命令
read_ds18b20(); //将读出的温度数据保存到tempint和tempdf处
}
//***********************读DS18B20子程序***************************************
//****************************************************************************
void read_ds18b20()
{
uchar delay,i,j,k,temp,temph,templ;
j=4; //读2位字节数据
do
{
for(i=8;i>0;i--) //一个字节分8位读取
{
temp>>=1; //读取1位右移1位
DQ=0; //数据线置低电平
delay=1;
while(--delay);
DQ=1; //数据线置高电平
delay=4;
while(--delay); //延时8us
if(DQ) //读取1位数据
temp|=0x80;
delay=25; //读取1位数据后延时50us
while(--delay);
}
if(j==4)
templ=temp;//读取的第一字节存templ
if(j==3)
temph=temp; //读取的第二字节存temph
if(j==2)
tempth=temp; //读取的第3字节存tempth TH的值
if(j==1)
temptl=temp; //读取的第4字节存tempth TL的值
}while(--j);
f=0;
if((temph & 0xf8)!=0x00) //若温度为负的处理,对二进制补码的处理
{
f=1; //为负温度f置1
temph=~temph;
templ=~templ;
k=templ+1;
templ=k;
if(k>255)
{
temph++;
}
}
tempdf=templ & 0x0f; //将读取的数据转换成温度值,整数部分存tempint,小数部分存tempdf
c=(tempdf*625);
tempdf=c;
templ>>=4; //
temph<<=4; //转化成字节温度
tempint=temph|templ;//两字节合并为一个字节
if (tempint>th|tempint==th|tempint<tl|tempint==tl)
beepflag=1;
else
beepflag=0;
}
//***********************写DS18B20子程序***************************************
//****************************************************************************
void write_ds18b20(uchar command)
{
uchar delay,i;
for(i=8;i>0;i--) //将一字节数据一位一位写入
{
DQ=0; //数据线置低电平
delay=6; //延时12us
while(--delay);
DQ=command&0x01; //将数据放置在数据线上
delay=25; //延时50us
while(--delay);
command=command>>1; //准备发送下一位数据
DQ=1; //发送完一位数据,数据线置高电平
}
}
//***********************显示子程序***************************************
//****************************************************************************
void disp_temp( tempint,tempdf)
{
uchar tempinth,tempintl,tempinbai,shifen,baifen,gefen,qianfen;
if (bb==1)
{
tempinbai=th/100;
tempinth=(th%100)/10;
tempintl=th%10; //整数取模
gefen=0/1000;
shifen=0%1000/100;
baifen =0%100/10;
qianfen=0%10; //小数取模
}
else if(bb==2)
{ tempinbai=tl/100;
tempinth=(tl%100)/10;
tempintl=tl%10; //整数取模
gefen=0/1000;
shifen=0%1000/100;
baifen =0%100/10;
qianfen=0%10; //小数取模
}
else
{
tempinbai=tempint/100;
tempinth=(tempint%100)/10;
tempintl=tempint%10; //整数取模
gefen=tempdf/1000;
shifen=tempdf%1000/100;
baifen =tempdf%100/10;
qianfen=tempdf%10; //小数取模
}
if (f==0)
{
P0=display1; //符号位
P2=ledmap[0];
}
else
{
P0=display1; //符号位
P2=ledmap[10];
}
delayms(2);
P0=display2;
P2=ledmap[tempinbai]; //开百位
delayms(2);
P0=display3;
P2=ledmap[tempinth];//开十位
delayms(2);
P0=display4;
P2=ledmap1[tempintl];//开个位
delayms(2);
P0=display5;
P2=ledmap[gefen];//开个分位
delayms(2);
P0=display6;
P2=ledmap[shifen]; //开十分位
delayms(2);
P0=display7;
P2=ledmap[baifen]; //开百分位
delayms(2);
P0=display8;
P2=ledmap[qianfen];//开千分位
}
//*******************************************************************/
//* 蜂鸣器响一声 */
//*******************************************************************/
void beep_st()
{
if (beepflag==1)
{ beep=0;
delayms(1000) ;
beep=1;
}
else
beep=1;
}
//***********************延时count ms子程序***************************************
//****************************************************************************
void delayms(uchar count) //延时count ms子程序
{
uchar i,j;
do
{
for(i=5;i>0;i--)
for(j=98;j>0;j--);
}while(--count);
}
//****************************************************************************
void keyscan() //键盘扫描
{
if(setth==0)
{
delayms(1);
}
if(setth==0)
{
bb++;
while(!setth); //循环在此 非0=1
}
if(bb==1)
{
if(up==0)
{
delayms(1);
}
if(up==0)
{
disp_temp(th,tempdf);
if(th<125)
{th++;}
while(!up)//非0=1
{
disp_temp(th,tempdf);
}
}
if(down==0)
{
delayms(1);
}
if(down==0)
{
disp_temp(th,tempdf);
if(th!=0) //不等于0为真执行
{
th--;
while(!down) // down为(非0=1)循环执行
{
disp_temp(th,tempdf);
}
}
}
}
if(bb==2)
{
if(up==0)
{
delayms(1);
}
if(up==0)
{
disp_temp(tl,tempdf);
if(tl<125)
{tl++;}
while(!up)//非0=1
{
disp_temp(th,tempdf);
}
}
if(down==0)
{
delayms(1);
}
if(down==0)
{
disp_temp(th,tempdf);
if(tl!=0) //不等于0为真执行
{
tl--;
while(!down) // down为(非0=1)循环执行
{
disp_temp(tl,tempdf);
}
}
}
}
if(bb==3)
{bb=0;
set_ds18b20(); //初始化DS18B20
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0x4e); //发温度转换命令
write_ds18b20(th); //写TH 3
write_ds18b20(tl);
// write_ds18b20(0x7f);
set_ds18b20(); //初始化DS18B20
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0x48);
}
}
void main()
{ set_ds18b20();
write_ds18b20(0xcc); //发跳过ROM匹配命令
write_ds18b20(0xbe); //发出读温度命令
read_ds18b20(); //将读出的数据
th=tempth; //将TH读到单片机
tl=temptl;
SP=0x60; //设置堆栈指针
bb=0;
beepflag=0;
while(1)
{
keyscan();
get_temperature(); //获得温度
disp_temp(tempint,tempdf); //显示温度
beep_st();
}
}
追问
程式如何把温度资料寫入SDcard內储存, 多个18B20又如何!
追答
单片机驱动SD卡 就是把数据写入SD卡 多个DS18B20用总线连接 网上有现成的
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询