一、原理分析

 DS18B20是常用的数字温度传感器,其输出的是数字信号,温度转换时的延时时间为750ms

在蓝桥杯单片机资源包中,会提供一个关于DS18B20的底层驱动库文件,onewire.c文件和onewire.h文件。里面实际上只有DS18B20复位操作字节写操作字节读操作三个函数。温度传感器DS18B20是单总线通信器件,对总线的操作有很严格的时序要求。如果出现序列混乱,器件将不响应主机,因此DS18B20底层驱动程序中时序很重要。对于不同系统时钟的微处理器,其时序延时参数可能需要做适当的调整。

1、DS18B20的温度转换与读取流程

【1】DS18B20复位。

【2】写入字节0xCC,跳过ROM指令。

【3】写入字节0x44,开始温度转换。

【4】延时700~900ms。

【5】 DS18B20复位。

【6】写入字节0xCC,跳过ROM指令。

【7】写入字节0xBE,读取高速暂存器。

【8】读取暂存器的第0字节,即温度数据的LSB。

【9】读取暂存器的第1字节,即温度数据的MSB。

【10】DS18B20复位。表示读取数据结束。

【11】将LSB和MSB整合成为一个16位数据。

【12】判断读取结果的符号,进行正负温度的数据处理。

2、DS18B20的数据处理

 DS18B20以16位带符号位扩展的二进制补码形式读出。高5位为符号位,低4位为小数部分,中间7位为整数部分。

DS18B20的分辨率为0.0625。读出数据为正温度时,将LSB和MSB整合成的16位整数,直接乘以0.0625即可。读出数据为负温度时,则需要将LSB和MSB整合成的16位整数,取反加1后,再乘以0.0625。

举一个例子来给大家说明这个处理的具体过程:
假设DS18B20的温度采样结果是:LSB = 0x96,MSB = 0x01
温度数据变量T_dat为16位无符号int整型,初始值为0x0000
执行T_dat = MSB;语句后, T_dat 的值为:0x0001
执行T_dat <<= 8;语句后, T_dat 的值为:0x0100
执行T_dat = T_dat | LSB;语句后, T_dat 的值为:0x0196
通过高5位的符号扩展位判断,进行正温度的处理算法,正常来说,应该是:
如果要求温度结果保留1位小数,为了简化在单片机中的运算,可以放大10倍进行整型处理,保留两位小数则放大100倍。

如果要求温度结果只显示整数部分,那就不用这么罗嗦,直接显示整数部分即可:
T_dat >>= 4;即 T_dat = 0x0019 = 25 摄氏度。

二、程序编写 

<1> 先将 onewire.c文件和onewire.h文件拷贝到当前工程下。
<2> 打开 onewire.h文件,检查文件代码是否完整,并确认总线引脚定义是否和CT107D的硬件对应,即P1^4。如果不对应,则将其修改过来。
<3> 打开 onewire.c文件, 研读各个底层驱动代码的具体实现,初步判断是时序的延时是否合理,如有明显错误,则将其修改过来。(IAP15F2K60S2的运算速度比51要快12倍,给的底层驱动代码一般是51的,使用发现温度不准,只需要把onewire.c驱动代码中的延时增大10倍或者12倍就可以了。)
<4> 根据DS18B20的工作原理和操作流程,编写读取温度结果和处理温度数据的函数,这是进行DS18B20应用开发中最重要的一个环节。
<5> 根据得到的温度结果,刷新数码管显示。这个部分,可以用MM模式来实现,可以用IO模式来实现。

1、用小数显示温度

main.c 

#include <reg52.h>
#include <onewire.h>

unsigned char  duanma[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char  duanma_x[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned int   temp=0; 
void Delay_SMG(unsigned int t)
{
	while(t--);
}
void DisplaySMG_Bit(unsigned char pos,unsigned char dat)
{
  P2=0xE0;P0=0xff;//先全部关掉数码管,避免显示不正常
  P2=0xC0;P0=0x01<<pos;
  P2=0xE0;P0=dat;	
}
void DisplaySMG_temp()
{
 	DisplaySMG_Bit(6,duanma[temp%10]);
	Delay_SMG(100);
	DisplaySMG_Bit(5,duanma_x[(temp/10)%10]);
	Delay_SMG(100);
	DisplaySMG_Bit(4,duanma[temp/100]);
	Delay_SMG(100);

	DisplaySMG_Bit(7,0xc6);
	Delay_SMG(100);
	DisplaySMG_Bit(3,0xff);
	Delay_SMG(100);
	DisplaySMG_Bit(2,0xff);
	Delay_SMG(100);
	DisplaySMG_Bit(1,0xff);
	Delay_SMG(100);
	DisplaySMG_Bit(0,0xff);
	Delay_SMG(100);

	P2=0xC0;P0=0xff;
    P2=0xE0;P0=0xff;	
}
void Delay(unsigned int t)
{
	 while(t--)
	 {
	 	 DisplaySMG_temp();
	 }
}
void Read_DS18B20_temp()
{
	 unsigned char LSB,MSB;

	 init_ds18b20();//DS18B20复位
	 Write_DS18B20(0xcc);//跳过ROM操作指令
	 Write_DS18B20(0x44); //开始温度转换

	 Delay(1000);//延时700ms左右,等待温度转换完成

	 init_ds18b20(); //DS18B20复位
	 Write_DS18B20(0xcc);//跳过ROM操作指令	
	 Write_DS18B20(0xbe); //开始读取高速暂存器

	 LSB=Read_DS18B20();//读取温度数据的低8位
	 MSB=Read_DS18B20();//读取温度数据的高8位

	 temp=MSB;
	 temp=(temp<<8)|LSB; //将LSB和MSB整合成为一个16位的整数
	//首先通过温度数据的高5位判断采用结果是正温度还是负温度
	
	 if((temp&0xf800)==0x0000)//正温度的处理办法

	 {
	 	  temp>>=4; //取出温度结果的整数部分
		  temp=temp*10;//放大10倍,然后加上小数部分
		  temp=temp+(LSB&0x0f)*0.625;
	 }
}
void main()
{
  P2=0x80;P0=0xff;
  while(1)
  {
  	 Read_DS18B20_temp();
	 DisplaySMG_temp();
  }
}

onewire.c 

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--);
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(50);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(50);
}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(50);
	}
	return dat;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(120);
  	DQ = 0;
  	Delay_OneWire(800);
  	DQ = 1;
  	Delay_OneWire(100); 
    initflag = DQ;     
  	Delay_OneWire(50);
  
  	return initflag;
}

 onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

unsigned char rd_temperature(void);  //; ;
bit init_ds18b20(void);
unsigned char Read_DS18B20(void);
void Write_DS18B20(unsigned char dat);
#endif

2、用整数显示温度

 

#include <reg52.h>
#include <onewire.h>

unsigned char  duanma[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char  duanma_x[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned int   temp=0; 
void Delay_SMG(unsigned int t)
{
	while(t--);
}
void DisplaySMG_Bit(unsigned char pos,unsigned char dat)
{
  P2=0xE0;P0=0xff;//先全部关掉数码管,避免显示不正常
  P2=0xC0;P0=0x01<<pos;
  P2=0xE0;P0=dat;	
}
void DisplaySMG_temp()
{
 	DisplaySMG_Bit(6,duanma[temp%10]);
	Delay_SMG(100);
	DisplaySMG_Bit(5,duanma[temp/10]);
	Delay_SMG(100);
	DisplaySMG_Bit(4,0xff);
	Delay_SMG(100);

	DisplaySMG_Bit(7,0xc6);
	Delay_SMG(100);
	DisplaySMG_Bit(3,0xff);
	Delay_SMG(100);
	DisplaySMG_Bit(2,0xff);
	Delay_SMG(100);
	DisplaySMG_Bit(1,0xff);
	Delay_SMG(100);
	DisplaySMG_Bit(0,0xff);
	Delay_SMG(100);

	P2=0xC0;P0=0xff;
    P2=0xE0;P0=0xff;	
}
void Delay(unsigned int t)
{
	 while(t--)
	 {
	 	 DisplaySMG_temp();
	 }
}
void Read_DS18B20_temp()
{
	 unsigned char LSB,MSB;

	 init_ds18b20();
	 Write_DS18B20(0xcc);
	 Write_DS18B20(0x44);

	 Delay(1000);

	 init_ds18b20();
	 Write_DS18B20(0xcc);
	 Write_DS18B20(0xbe);

	 LSB=Read_DS18B20();
	 MSB=Read_DS18B20();

	 temp=MSB;
	 temp=(temp<<8)|LSB;
	
	 temp>>=4;
	
}
void main()
{
  P2=0x80;P0=0xff;
  while(1)
  {
  	 Read_DS18B20_temp();
	 DisplaySMG_temp();
  }
}

用手摸温度传感器U5,温度上升

温度传感器ds18b20

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐