DS1820与单片机如何读取温度?

 我来答
amwjie72
2011-02-15 · TA获得超过331个赞
知道答主
回答量:44
采纳率:0%
帮助的人:40.4万
展开全部
我来回答吧,上个学期, 我做的课程设计就是基于单片机的数据温度计。

以下是我写出一程序,如果看不懂的话,就发邮件给我,amwjie72@163.com

#include<reg52.h>
#include<intrins.h>
#include<math.h>
#include<absacc.h>

#define uint unsigned int
#define uchar unsigned char

uchar table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; // 用于共阳 低电平有效 不带小数点
uchar table1[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; // 带小数点 用于第三位

sbit w1 =P2^7;
sbit w2 =P2^6;
sbit w3 =P2^5; //此处要用带小数点的共阳编码
sbit w4 =P2^4;
sbit dat=P3^5; //P3^5为DS18B20的数据线

void delay_ds18b20(uint t) reentrant; //用于ds18b20的延时程序
bit reset_ds18b20(void); //用于复位ds18b20
void wr_bit(bit i); //用于向ds18b20写入一个bit
void wr_byte(uchar d); //用于向ds18b20写入一个byte
uchar rd_bit(void); //用于从ds18b20读出一个bit
uchar rd_byte(void); //用于从ds18b20读出一个byte
void start_ds18b20(void) small; //用于启动ds18b20的温度转换
void read_temperature(); //用于读取ds18b20的温度
void shift(); //用于转换读取的温度值
void obtain_temp(); //更新一次温度值
void delay();

uchar temph; //保存温度高八位
uchar templ; //保存温度低八位
bit nagetiveflag; //如果此bit为1表示温度为负
uint integral; //转换温度的整数部分
uint radix_point; //转换温度的小数点部分

void main()
{

while(1)
{
if(nagetiveflag==1)
{
P0=0xbf;
}
else if(integral/100==0)
{
P0=0xff;
}
else
{
P0=table[integral/100];
}
w1=0;
delay();
w1=1;

if((integral%100)/10==0)
{
P0=0xff;
}
else
{
P0=table[(integral%100)/10];
}
w2=0;
delay();
w2=1;

P0=table1[integral%10];
w3=0;
delay();
w3=1;

P0=table[radix_point];
w4=0;
delay();
w4=1;

obtain_temp();

}

}
/*
///////////////////////////////
函数: delay_ds18b20
功能: ds18b20延时函数
参数: t 为定时时间长度
返回: 无
说明: 延时公式:15*t+15(近似),晶振12Mhz
//////////////////////////////
*/
void delay_ds18b20(uint t)reentrant
{
for( ;t>0;t--)
{
_nop_;_nop_;_nop_;_nop_;
}
_nop_;_nop_;
}

/*
///////////////////////////////
函数: reset_ds18b20
功能: 复位ds18b20
参数: 无
返回: 1:复位成功 0:复位失败
说明: 拉低总线至少480us;可用于检测ds18b20, 晶振12Mhz
//////////////////////////////
*/
bit reset_ds18b20()
{
bit ret=1;
dat=0; //拉低总线
delay_ds18b20(32); //为保险起见,延时495us
dat=1; //释放总线
delay_ds18b20(4); //需要等待15~60us ,这里延时75us,保证接收的是存在脉冲
ret=dat;
delay_ds18b20(14); //让ds18b20释放总线。
dat=1;
return(~ret);
}

/*
///////////////////////////////
函数: wr_bit
功能: 向ds18b20写入一个bit
参数: i
返回: 无
说明: 拉低总线至少1us;并在0~15us内向总线写入要写入的bit 持续60us, 晶振12Mhz
//////////////////////////////
*/
void wr_bit(bit i)
{
dat=0; //拉低总线产生写时序
_nop_();
_nop_();
dat=i; //延时大于1us,并在15us内写入数据
delay_ds18b20(3);//延时60us 等待ds18b20采样读取
dat=1; //释放总线
}
/*
///////////////////////////////
函数: wr_byte
功能: 向ds18b20写入一个byte
参数: d
返回: 无
说明: 通过调用wr_bit(bit i)从低往高位写
//////////////////////////////
*/
void wr_byte(uchar d)
{
uchar i=0;
while(i++<8)
{
wr_bit(d&0x01); //此处&为按位与,但结果会传给一个bit 所以不会产生错误
d>>=1;
}
}
/*
///////////////////////////////
函数: rd_bit
功能: 从ds18b20读出一个bit
参数: 无
返回: bit
说明: 总线从高拉低总线,持续至少1us以上,再释放总线。产生读时序
//////////////////////////////
*/
uchar rd_bit()
{
uchar retu;
dat=0; //拉低总线
_nop_;_nop_;
dat=1; //释放总线
_nop_;_nop_;
_nop_;_nop_;
retu=dat; //读取数据
delay_ds18b20(3);
dat=1; //释放总线
return retu;
}
/*
///////////////////////////////
函数: rd_byte
功能: 从ds18b20读出一个byte
参数: 无
返回: ucahr
说明: 通过调用8次rd_bit()达到读出一个byte
//////////////////////////////
*/
uchar rd_byte()
{
uchar i;
uchar da;
for(i=0;i<8;i++)
{
da>>=1; //选读最低位
if(rd_bit())//读出来的是0可不用做或运算
{
da|=0x80;
}
}
return da;
}

/*
///////////////////////////////
函数: start_ds18b20
功能: 启动ds18b20
参数: 无
返回: 无
说明: 复位后,写入0xcc跳过对rom的操作,并写入0x44来启动温度转换
//////////////////////////////
*/
void start_ds18b20() small
{
dat=1;
reset_ds18b20();
wr_byte(0xcc); //跳过对rom的操作
wr_byte(0x44); //启动温度转换
}
/*
///////////////////////////////
函数: read_temperature
功能: 读取温度
参数: 无
返回: 无
说明: 复位后,写入0xcc跳过对rom的操作,并写入0xbe来读取温度。读两个字节
//////////////////////////////
*/
void read_temperature()
{
int temp;
reset_ds18b20();
wr_byte(0xcc); //跳过对rom的操作
wr_byte(0xbe); //发读取命令
templ=rd_byte();
temph=rd_byte();
}
/*
///////////////////////////////
函数: shift
功能: 温度转换
参数: 无
返回: 无
说明: 在读出温度后,用来将温度信息转换为对应该的温度数值大小
radix_point为小数点部分 integral整数部分
//////////////////////////////
*/
void shift()
{
if(temph>15)
{
nagetiveflag=1;
}
else
{
nagetiveflag=0;
}
radix_point=((float)(templ&0x0f))/1.6;
integral=(temph&0x07)*16+(templ>>4);
}
/*
///////////////////////////////
函数: delay
功能: 动态扫描延时
参数: 无
返回: 无
说明: 无
//////////////////////////////
*/
void delay()
{
uint k,j;
for(k=50;k>0;k--)
for(j=5;j>0;j--);
}
/*
///////////////////////////////
函数: obtain_temp
功能: 复位DS18B20读取温度值并对其进行转换
参数: 无
返回: 无
说明: 更新radix_point(小数点部分) integral(整数部分)
//////////////////////////////
*/
void obtain_temp()
{
start_ds18b20();
read_temperature();
shift();
}
emtianshi999
推荐于2016-03-29 · TA获得超过5342个赞
知道大有可为答主
回答量:3001
采纳率:81%
帮助的人:898万
展开全部
网上有很多这样的例程啊。给你一个STC的,STC的下载程序方便,上手也比较快

CPU:STC12C5A48S2

#include "18B20.h"
#include<intrins.h>
#include <math.h> //要用到取绝对值函数abs()
/**************************************
延时X微秒(STC12C5A60S2@12M)
不同的工作环境,需要调整此函数
此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同
**************************************/
sbit DQ=P1^0; //定义18B20数据脚为P1.0端口

void DelayXus(uint n)
{
while (n--)
{
_nop_();
_nop_();
}
}
void getTmp_Update()
{
uint TPL,TPH,tmpvalue,value;
float t;

Room_tmep=0;
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0x44); //开始转换命令

while (!DQ){}; //等待转换完成
DS18B20_Reset(); //设备复位
DS18B20_WriteByte(0xCC); //跳过ROM命令
DS18B20_WriteByte(0xBE); //读暂存存储器命令
TPL = DS18B20_ReadByte(); //读温度低字节
TPH = DS18B20_ReadByte(); //读温度高字节
tmpvalue = TPH;
tmpvalue <<= 8;
tmpvalue |= TPL;
value = tmpvalue;

t = value * 0.0625; //使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度
/* 如果将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入, 如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度,
如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度 */
Room_tmep= t; //得到最终温度
}
/**************************************
复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset()
{
uchar i=0;
CY = 1;
while (CY)
{

DQ = 0; //送出低电平复位信号
DelayXus(240); //延时至少480us
DelayXus(240);
DQ = 1; //释放数据线
DelayXus(60); //等待60us
CY = DQ; //检测存在脉冲
DelayXus(240); //等待设备释放数据线
DelayXus(180);
i++;
if (i>50){AD_Error_code=1;return;}else{if (AD_Error_code==1) {AD_Error_code=0;}}
}
}
/**************************************
从DS18B20读1字节数据
**************************************/
uint DS18B20_ReadByte()
{
uchar i;
uchar dat = 0;
for (i=0; i<8; i++) //8位计数器
{
dat >>= 1;
DQ = 0; //开始时间片
DelayXus(1); //延时等待
DQ = 1; //准备接收
DelayXus(1); //接收延时
if (DQ) dat |= 0x80; //读取数据
DelayXus(60); //等待时间片结束
}
return dat;
}
/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte(uint dat)
{
uchar i;
for (i=0; i<8; i++) //8位计数器
{
DQ = 0; //开始时间片
DelayXus(1); //延时等待
dat >>= 1; //送出数据
DQ = CY;
DelayXus(60); //等待时间片结束
DQ = 1; //恢复数据线
DelayXus(1); //恢复延时
}
}
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
yangkun10015
推荐于2018-03-11 · TA获得超过241个赞
知道小有建树答主
回答量:571
采纳率:0%
帮助的人:364万
展开全部
/*************************************************
程序功能:用DS18B20测量室温并在数码管上显示。
-------------------------------------------------
测试说明:观察显示温度数值。
*************************************************/
#include <msp430x16x.h>
#include "BoardConfig.h"
#include "DS18B20.h"

//包括要显示的4位温度数字
uchar dN[6];
//数码管七段码;0--f
uchar scandata[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//数码管位选变量
uchar cnt = 0;

void Disp_Numb(uint temper);

/****************主函数****************/
void main(void)
{
uchar i;

WDTCTL=WDTPW+WDTHOLD;

/*------选择系统主时钟为8MHz-------*/
BCSCTL1 &= ~XT2OFF; //打开XT2高频晶体振荡器
do
{
IFG1 &= ~OFIFG; //清除晶振失败标志
for (i = 0xFF; i > 0; i--); //等待8MHz晶体起振
}
while ((IFG1 & OFIFG)); //晶振失效标志仍然存在?
BCSCTL2 |= SELM_2 + SELS; //MCLK和SMCLK选择高频晶振

BoardConfig(0x38);
P4DIR = 0xff;
P4OUT = 0xff;

BoardConfig(0x30); //打开数码管

//设置看门狗定时器,初始化控制数码管的IO
WDTCTL = WDT_ADLY_1_9;
IE1 |= WDTIE;
//P4DIR = 0xff;

//P4OUT = 0x00;

//设置DS18B20的IO状态
P2DIR |= BIT4;
P2OUT |= BIT4;
//计数时钟选择SMLK=8MHz,1/8分频后为1MHz
TACTL |= TASSEL_2 + ID_3;
//打开全局中断
_EINT();
//循环读数显示
while(1)
{
Disp_Numb(Do1Convert());
}
}
/*******************************************
函数名称:watchdog_timer
功 能:看门狗定时器中断服务函数,进行数码
管动态扫描
参 数:无
返回值 :无
********************************************/
#pragma vector = WDT_VECTOR
__interrupt void watchdog_timer(void)
{
BoardConfig(0x10);
P4OUT = 0x0f;
BoardConfig(0x10);
P4OUT &= ~(1<<cnt);
BoardConfig(0x20);
P4OUT = scandata[dN[5-cnt]];
if(cnt==1) P4OUT |= 0x80; //在第二位显示小数点

cnt++;
if(cnt == 4) cnt = 0;
}
/*******************************************
函数名称:Disp_Numb
功 能:将从DS18B20读取的11bit温度数据转换
成数码管显示的温度数字
参 数:temper--11bit温度数据
返回值 :无
********************************************/
void Disp_Numb(uint temper)
{
uchar i;

for(i = 0;i < 6;i++) dN[i] = 0; //初始化显示变量

//数值转换
if(temper & BIT0)
{
dN[0] = 5;
dN[1] = 2;
dN[2] = 6;
}
if(temper&BIT1)
{
dN[1] += 5;
dN[2] += 2;
dN[3] += 1;
}
if(temper & BIT2)
{
dN[2] += 5;
dN[3] += 2;
if(dN[2] >= 10)
{
dN[2] -= 10;
dN[3] += 1;
}
}
if(temper&BIT3)
{
dN[3] += 5;
}
if(temper & BIT4)
{
dN[4] += 1;
}
if(temper & BIT5)
{
dN[4] += 2;
}
if(temper & BIT6)
{
dN[4] += 4;
}
if(temper & BIT7)
{
dN[4] += 8;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
}
if(temper & BIT8)
{
dN[4] += 6;
dN[5] += 1;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
}
if(temper & BIT9)
{
dN[4] += 2;
dN[5] += 3;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
}
if(temper & BITA)
{
dN[4] += 4;
dN[5] += 6;
if(dN[4] >= 10)
{
dN[4] -= 10;
dN[5] += 1;
}
if(dN[5] >= 10)
{
dN[5] -= 10;
}
}
}
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
nongjianjun
2011-02-15 · TA获得超过831个赞
知道小有建树答主
回答量:3761
采纳率:0%
帮助的人:885万
展开全部
通过编写程序控制DS18B20读与写而得到温度的,不懂的再来找我啦
本回答被提问者采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
病毒8号
2011-02-15 · 超过31用户采纳过TA的回答
知道答主
回答量:115
采纳率:0%
帮助的人:0
展开全部
去下载一个ds18b20的资料看看就知道了 这是一个单总线的温度测量元件
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
收起 更多回答(3)
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式