急求一篇关于AT89C51单片机与DS18B20温度采集系统设计(包括硬件和软件)

如题所述

http://download.csdn.net/source/1395968 先上这里看看硬件软件都有。下面是软件的:说明:本程序使用1602LCD显示。温度采集芯片已经集成,温度模拟信号已经在DS18B20内部转换成数字信号,只需要通过18B20的数据引脚读取即可,具体请详细阅读DS18B20数据手册。要看仿真结果请到个人空间。大同小异,注意时序,串行读写时序要求最严格,程序注释很详细了。
/************************************
硬件:M16,DS18B20,引脚连线:DQ-PD2,
仿真:要求M16晶振达8MHZ
Author:LCA from WHUT
Application: Temperature Measureing
Date:2007-10
*************************************/
#include "1602LCD.h"
#include "DS1302.h"
//#include "key.h"
#include <iom16v.h>
#include <macros.h>

//BIT在<macros.h>中已经定义#define BIT(x) (1 << (x))

#define DQ_DIR_IN() DDRD&=~BIT(2) //data input
#define DQ_DIR_OUT() DDRD|=BIT(2) //data output
#define DQ_BUS_L() PORTD&=~BIT(2) //Pin output high
#define DQ_BUS_H() PORTD|=BIT(2) //Pin output low
#define BUS_state() (PIND & 0x04) //检测 ds18b20返回信号

unsigned char wmh,wml,wm3,sign_flag=0;
//unsigned char table[]={"0123456789"};

void DS18B20_init()
{ DQ_DIR_OUT(); //设置PD2 为输出
DQ_BUS_H();
DQ_BUS_L(); //占领总线
delay_nus(480); //480us以上
DQ_BUS_H(); //释放总线
DQ_DIR_IN();
delay_nus(20); //15~60us
while(BUS_state()); //回读DS18B20返回信号
DQ_DIR_OUT();
DQ_BUS_H(); //释放总线
delay_nus(140); //60~240us

}

/**********************************
函数:write_18B20()
功能:往18B20中写入数据(命令)
输入参数:数据(命令)
返回参数:无
注意:延时
************************************/
void write_18B20(unsigned char x)
{
unsigned char m;
for(m=0;m<8;m++)
{
DQ_BUS_L(); //占领总线
if(x&(1<<m)) //写数据了,先写低位的
DQ_BUS_H();
else
{DQ_BUS_L();}
delay_nus(40); //15~60us
DQ_BUS_H(); //完毕后释放总线
}
DQ_BUS_H();
}

/************************************
函数:read_18B20()
功能:从18B20中读取数据
输入参数:无
返回参数:读取值
注意:延时
*************************************/

unsigned char read_18B20(void)
{
unsigned char temp,n;
temp=0;
for(n=0;n<8;n++)
{
DQ_BUS_L(); //拉低总线
DQ_BUS_H(); //置高总线
DQ_DIR_IN(); //data input
if(BUS_state()) //读数据,从低位开始
temp|=(1<<n);
else
temp&=~(1<<n);
delay_nus(50); //60~120us
DQ_DIR_OUT(); //data output
}
return (temp);
}

/************************************
函数:get_temper_value();
功能:从18B20中读取温度值
输入参数:无
返回参数:无(处理值wm3,wmh,wml-全局变量)
注意:正负温度的转换方法,手册中数据
存储格式为:高8位的高4位为符号位
**************************************/
void get_temper_value(void) //读取温度值
{
unsigned char temh,wm1;
unsigned char wm0,teml,wm2;
DS18B20_init(); //复位18b20
write_18B20(0xcc); //skip ROM
write_18B20(0x44); //发出转换命令
DS18B20_init();
write_18B20(0xcc); //skip rom
write_18B20(0xbe); //发出读命令
teml=read_18B20(); //读数据
temh=read_18B20();
wm0=teml>>4; //低8位的高四位,温度范围0~115啦!
wm1=temh<<4; //只要高8位的低四位
wm2=wm1+wm0 ; //16进制转10进制
if(wm1&0x80) //测试符号位,测温范围-55
{wm2=256-wm2; //求取补码 <br>sign_flag=1; <br>} //为负温度
else
{
sign_flag=0;
}
wm3=wm2/100; //百位
wmh=(wm2%100)/10; //出口参数了!wmh是显示的高位,wml使显示的低位 ,十位
wml=(wm2%100)%10; //个位
}

/************************************
函数:data_display();
功能:温度值显示(显示符号为,百位,十位,个位,小数点)
输入参数:无(全局变量wm3,wmh,wml)
返回参数:无
注意:显示地址的处理
**************************************/

void data_display(void)
{ unsigned char add=0;
add=LCD_display_string(0,0,"Tem:");
if(sign_flag)
{LCD_display_string(add++,0,"-");} //显示负号
if(!sign_flag) //负温度的时候不显示百位
{LCD_display_num(add++,0,table[wm3]);} //百位0
LCD_display_num(add++,0,table[wmh]); //十位
LCD_display_num(add++,0,table[wml]);
LCD_display_string(add++,0,".");
LCD_display_string(add++,0,"00");
LCD_display_string(add+1,0,"C");
}

void devices_init(void)
{
LCD_init();
DS18B20_init();
DS1302_init();
}

void main()
{unsigned char num=0; <br>devices_init(); <br>while(1) <br>{get_temper_value(); //获取温度值 <br>data_display(); //显示温度值 <br>get_time(); //读取时钟并显示 <br>// num=get_key(); <br>//if(num) <br>// {LCD_display_string(14,1,"keynum"); }

}
}
温馨提示:答案为网友推荐,仅供参考
相似回答