DS18B20温度传感器

 

demo.c

/*****************************************************************************
* 步骤:
* 01、分文件把不同功能模块分开
* 02、定义管脚
* 03、定义temp.h文件,把一些全局参数和函数抽象出来,相当于接口
* 04、DS18B20初始化
* 05、DS18B20写数据
* 06、DS18B20读数据
* 07、DS18B20发送转换温度命令
* 08、DS18B20发送读取温度命令
* 09、DS18B20开始读取温度
* 10、处理温度数据(把温度数据包括负号拆分成数组用多个数码管显示)
* 11、动态数码管显示温度
******************************************************************************/

#include <reg52.h>
#include "temp.h"

// 138译码器管脚(动态数码管位选:即显示哪一个数码管)
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

// 动态数码管段选(即数码管显示什么数字)
uchar code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

/*****************************************************************************
* 用来保存温度数据,把温度 temp 拆分成数组:第0位是符号位(可正可负)
* 第1/2/3位是整数位(0-125℃),第4/5位是小数位
******************************************************************************/
uchar DisplayData[8];

/*******************************************************************************
* 函 数 名		: Delay
* 函数功能		: 延时函数,i=1时,大约延时10us
*******************************************************************************/
void Delay(uint i)
{
	while(i--);	
}

/*******************************************************************************
* 函 数 名			: DataPros
* 函数功能			: 数据处理函数,把温度 temp 拆分成数组
* 输    入			: 无
* 输    出			: 无
*******************************************************************************/
void DataPros(int temp)
{
	float tp;	// 温度
	if(temp<0)	// 如果温度为零下温度
	{
		DisplayData[0]=0x40;	// 负号-
		// 因为读取的温度是实际温度的补码,所以减1,再取反求出原码
		temp-=1;
		temp=~temp;
		tp=temp;
	}
	else
	{
		DisplayData[0]=0x00;	// 如果温度为正数,则去掉负号(即不显示)
		tp=temp;
	}
	/*
	留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
	后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
	算加上0.5,还是在小数点后面
	*/
	temp=tp*0.0625*100+0.5;	
	
	DisplayData[1]=smgduan[temp/10000];
	DisplayData[2]=smgduan[temp%10000/1000];
	DisplayData[3]=smgduan[temp%1000/100]|0x80;		// 0x80是小数点,对应七段码的dp管脚
	DisplayData[4]=smgduan[temp%100/10];
	DisplayData[5]=smgduan[temp%10];
}

/*******************************************************************************
* 函 数 名			: DigDisplay
* 函数功能			: 在动态数码管上显示温度
* 输    入			: 无
* 输    出			: 无
*******************************************************************************/
void DigDisplay()
{
	uchar i;
	for(i=0; i<6; i++)
	{
		switch(i)
		{
			case(0):
				LSA=0; LSB=0; LSC=0; break;	// 显示第0位
			case(1):
				LSA=1; LSB=0; LSC=0; break;	// 显示第1位
			case(2):
				LSA=0; LSB=1; LSC=0; break;	// 显示第2位
			case(3):
				LSA=1; LSB=1; LSC=0; break;	// 显示第3位
			case(4):
				LSA=0; LSB=0; LSC=1; break;	// 显示第4位
			case(5):
				LSA=1; LSB=0; LSC=1; break;	// 显示第5位
		}
		P0=DisplayData[5-i];	// 单个数码管的数据
		Delay(100);	// 间隔一段时间扫描	
		P0=0x00;	// 数码管消影
	}
}

/*******************************************************************************
* 函 数 名			: main
* 函数功能			: 主函数
* 输    入			: 无
* 输    出			: 无
*******************************************************************************/
void main()
{
	while(1)
	{
		DataPros(Ds18b20ReadTemp());		// 读取温度,数据处理
		DigDisplay();						// 显示温度
	}
}

temp.c

#include "temp.h"

/*******************************************************************************
* 函 数 名		: Delay1ms
* 函数功能		: 延时函数
* 输    入		: 无
* 输    出		: 无
*******************************************************************************/
void Delay1ms(uint y)
{
	uint x;
	for(; y>0; y--)
	{
		for(x=110; x>0; x--);
	}
}

/*******************************************************************************
* 函 数 名			: Ds18b20Init
* 函数功能			: 初始化
* 输    入			: 无
* 输    出			: 初始化成功返回1,失败返回0
*******************************************************************************/
uchar Ds18b20Init()	
{
	uchar i;
	DSPORT=0;			// 拉低总线
	// 延时642us,480us-960us范围都行
	i=70;	
	while(i--);
	DSPORT=1;			// 拉高总线
	i=0;				// 复位i
	while(DSPORT)		// 如果初始化成功,则Ds18b20会在15到60us之间返回0,失败则返回1
	{
		Delay1ms(1);
		i++;
		if(i>5)			// 如果初始化失败,开始计数,5ms后自动返回0
		{	
			return 0;	// 初始化失败
		}
	}
	return 1;			// 初始化成功
}

/*******************************************************************************
* 函 数 名			: Ds18b20ReadByte
* 函数功能			: 读取一个字节
* 输    入			: 无
* 输    出			: uchar
*******************************************************************************/
uchar Ds18b20ReadByte()
{
	uchar tmp, dat;
	uint i, j;
	for(i=0; i<8; i++)
	{
		DSPORT=0;					// 将数据线拉低“0”
		j++;						// 延迟1us				
		DSPORT=1;					// 将数据线拉高“1”,释放总线准备读数据
		// 延时6us等待数据稳定
		j++;
		j++;
		tmp=DSPORT;					// 读数据线的状态得到1个状态位,并进行数据处理
		// 先把dat右移1位,腾出最高位,再把tmp左移7位,留下最后一位x,相或后,x就变成了dat的最高位
		dat=(dat>>1)|(tmp<<7);		
		// 读取完之后等待48us再接着读取下一个数
		j=4;		
		while(j--);
	}
	return dat;						// 返回读取的字节数据
}

/*******************************************************************************
* 函 数 名			: Ds18b20WriteByte
* 函数功能			: 向18B20写入一个字节
* 输    入			: dat
* 输    出			: 无
*******************************************************************************/
void Ds18b20WriteByte(uchar dat)	
{
	uint i, j;
	for(i=0; i<8; i++)
	{
		DSPORT=0;			// 数据线先置低电平“0”
		j++;
		DSPORT=dat&0x01;	// 和0x01相与,最后一位由dat的最后一位来决定,0就是0,1就是1,其他位均为0
		// 延时68us,持续时间最少60us
		j=6;
		while(j--); 
		DSPORT=1;			// 将数据线拉到高电平
		dat>>=1;			// 最后一位已经写入,移出去,为下一次写入做准备
	}
}

/*******************************************************************************
* 函 数 名			: Ds18b20ChangTemp
* 函数功能			: 让18b20发出转换温度的命令
* 输    入			: 无
* 输    出			: 无
*******************************************************************************/
void Ds18b20ChangTemp()			
{
	Ds18b20Init();				// 初始化
	Delay1ms(1);				// 延迟1ms
	Ds18b20WriteByte(0xcc);		// 跳过ROM操作命令
	Ds18b20WriteByte(0x44);		// 温度转换命令
	//Delay1ms(100);			    // 等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}

/*******************************************************************************
* 函 数 名			: Ds18b20ReadTempCom
* 函数功能			: 发送读取温度命令
* 输    入			: 无
* 输    出			: 无
*******************************************************************************/
void Ds18b20ReadTempCom()			
{
	Ds18b20Init();				// 初始化
	Delay1ms(1);				// 延迟1ms
	Ds18b20WriteByte(0xcc);		// 跳过ROM操作命令
	Ds18b20WriteByte(0xbe);		// 发送读取温度命令
}

/*******************************************************************************
* 函 数 名			: Ds18b20ReadTemp
* 函数功能			: 读取温度
* 输    入			: 无
* 输    出			: 无
*******************************************************************************/
int Ds18b20ReadTemp()			
{
	int temp=0;				// 温度临时变量
	uchar tml, tmh;			// tml,tmh分别是温度数据的低8位和高8位,温度数据由两个字节构成,共16位
	Ds18b20ChangTemp();		// Ds18b20发出温度转换命令
	Ds18b20ReadTempCom();	// 发送读取温度命令
	tml=Ds18b20ReadByte();	// Ds18b20中低8位在前,高8位在后,所以先读低8位
	tmh=Ds18b20ReadByte();	// 再读高8位
	temp=tmh;				// 因为高8位的前5位是符号位(+/-),所以先处理高8位
	temp<<=8;				// 先把temp的16位中的前8位移出(因为初始化时高8位均为0,变成:tmh00000000)
	temp|=tml;				// 再和低8位相或,变成:tmhtml
	return temp;			// 返回完整的温度
}

temp.h

/*****************************************************************************
* 这里定义和 DS18B20 温度传感器相关的参数,
* 这个 .h 文件只定义标准参数,全局参数,相当于 Java 中的接口
******************************************************************************/

#ifndef _TEMP_H_
#define _TEMP_H_

#include <reg52.h>

#ifndef uint
#define uint unsigned int
#endif

#ifndef uchar
#define uchar unsigned char
#endif

// DS18B20 温度传感器管脚
sbit DSPORT=P3^7;

// 定义函数
uchar Ds18b20Init();					// Ds18b20 初始化
uchar Ds18b20ReadByte();				// Ds18b20 读数据
void  Ds18b20WriteByte(uchar dat);		// Ds18b20 写数据
void  Ds18b20ChangTemp();				// Ds18b20 发送转换温度命令
void  Ds18b20ReadTempCom();				// Ds18b20 发送读取温度命令
int   Ds18b20ReadTemp();				// Ds18b20 开始读取温度
void  Delay1ms(uint i);					// 延迟1ms

#endif

实验结果:

 

posted @ 2018-02-06 22:00  半生戎马,共话桑麻、  阅读(481)  评论(0)    收藏  举报
levels of contents