首页 > 其他 > 详细

单片机控制单总线协议DS18B20之模块编程

时间:2014-03-15 08:25:20      阅读:664      评论:0      收藏:0      [点我收藏+]

这里将我编写的STC12C5A60S2单片机控制单总线协议温度传感器ds18b20的程序共享一下,是希望前辈们给予斧正 。

(补充:以下代码只需要修改.h文件中含有 “选择” 字样的部分,就可以达到复用的效果)

对于LCD1602模块,请参考我的另一篇文章《单片机控制LCD1602液晶屏之模块化编程

 

    经过测试,本程序适合11.0592MHZ和12.00MHZ晶振情况,同时本程序合适proteus仿真(需要修改ds18b20.c中的宏TEST的值即可用于proteus仿真)

 

实验步骤1:修改ds18b20.c中的宏,即可适用于硬件

#define  	 TEST  1	/*1:硬件实验   0 :proteus仿真实验*/

bubuko.com,布布扣
 

实验步骤2:修改ds18b20.c中的宏,即可适用于proteus仿真

#define  	 TEST  0	/*1:硬件实验   0 :proteus仿真实验*/

bubuko.com,布布扣

 


测试程序: 

#include <reg52.h>
#include <intrins.h>
#include "common.h"
#include "lcd1602.h"
#include "ds18b20.h"



void main(void)
{

	int temp,j ;
	float f ;
	UB8 dat[]={0,0,0,0,0,0,0,0,0,0};

	P1=0x00;//leds


	#if 0 //临时测试DS18B20的存在与否,用于检测ds18b20Init()函数
		if(ds18b20Init() == 0) //存在
		{
			P1 = 0x01 ;
		}
		else
			P1=0xf8;
		while(1)
			;
	#endif


	lcd1602Init() ;
	lcd1602WriteCommand(0x0c);/*为了显示时消除光标显示,暂时修改,也可以在lcd1602模块函数中修改*/
	lcd1602AddressWriteString(LCD1602_ROW0,0,"Chip : DS18b20") ;	
	
	while(1)
	{

		temp = ds18b20ReadTemperature() ;
			
		
		if((temp & (0xf8<<8)) ==(0xf8<<8)) //温度为负
		{
		  	lcd1602AddressWriteByte(LCD1602_ROW1,0,‘-‘);
			temp-=1 ;
			temp =~temp ;
			f= temp ;
			temp = f*0.0625*10+0.5;/*乘以10,并加0.5(用于四舍五入),用以后续的保留1位小数做准备*/
		}
		else 
		{
		   lcd1602AddressWriteByte(LCD1602_ROW1,0,‘+‘);
		    temp &=~(0xf8<<8);
			f = temp ;
			temp = f*0.0625*10+0.5;
		}

		
		dat[0] = temp / 1000 +‘0‘ ;/*温度百位*/
		dat[1]=  temp %1000/100 +‘0‘;/*温度十位*/
		dat[2] = temp %100 /10 +‘0‘ ;/*温度个位*/
		dat[3] = ‘.‘ ;
		dat[4] = temp %10 +‘0‘;/*温度小数点后第一位,是进行了四舍五入操作后的数据*/
		

			for(j=0 ; j<5 ; j++)
			{
				lcd1602AddressWriteByte(1,j+1, dat[j]);
			}
	
	}

	while(1);

}


 

/*################ds18b20.h start################*/

#ifndef __DS18B20_H__
#define __DS18B20_H__

#include <reg52.h>

sbit ds18b20_io_bit	= P3^7 ;/*根据硬件选择*/

//Rom command
#define DS18B20_SEARCH_ROM		0xf0
#define DS18B20_READ_ROM		0x33
#define DS18B20_MATCH_ROM		0x55
#define DS18B20_SKIP_ROM		0xcc
#define DS18B20_ALARM_SEARCH	0xec

//Function command
#define DS18B20_CONVERT_TEMPERATURE	0x44
#define DS18B20_WRITE_SCRATCHPAD	0x4e
#define DS18B20_READ_SCRATCHPAD		0xbe
#define DS18B20_COPY_SCRATCHPAD		0x48
#define DS18B20_RECALL_E2			0xb8
#define DS18B20_READ_POWER_SUPPLY	0xb4

#define DS18B20_EXISTENCE			0 /*存在DS18B20*/
#define DS18B20_NOT_EXISTENCE		-1/*不存在DS18B20*/

extern SB8 ds18b20Init(void);
extern int ds18b20ReadTemperature(void) ;


#endif /*__DS18B20_H__*/


 

/*################ds18b20.h end################*/

 

/*################ds18b20.c start################*/

/***************************************************************************
Module	:ds18b20.c

Purpose	:Implementation of ds18b20 module.

Version	:0.01							2014/03/14 12:00(OK)

Complier:Keil 8051 C complier V9.01

MCU		:STC12C5A60S2(开发板)
		 AT89C51	 (proteus仿真)


Author	:yangrui

Email	:yangrui90s@163.com


Modification:
=================
	2014/02/24 23:44
	Reason:
		1.该程序适合11.0592MHZ和12.0MHZ晶振环境,还适用于protes仿真
		,但注意在仿真时修改delay15usForDs18b20()和delay720usForDs18b20()
		和函数ds18b20ReadTemperature的预编译命令即可。

		为了简化修改过程,只需要修改程序中的TEST值即可!!

		2.该程序默认使用12位转换精度.(精确到0.0625摄氏度)

=================



***************************************************************************/

#include <reg52.h>
#include <intrins.h>
#include "common.h"
#include "ds18b20.h"

#define  	 TEST  1	/*1:硬件实验   0 :proteus仿真实验*/

/******************************************************
Function	:delay15usForDs18b20
Input		:N/A
Output		:N/A
Return		:N/A
Description	:N/A
Note		:1.这里的延时是由STC-ISP V6.66(软件延时计算器)
				生成。

			 2.这里的延时由两个版本,一个用于ds18b20开发板,
			 一个用于ds18b20的proteus仿真,因为DS118B20对
			 时间要求较高,所以需要需要根据具体实验选择。

******************************************************/
void delay15usForDs18b20(void)	//11.0592MZH
{
#if  (TEST==1) 	//用于开发板
	unsigned char i;

	_nop_();
	_nop_();
	i = 38;
	while (--i);
#elif (TEST==0)	 //用于porteus仿真
	unsigned char i;

	i = 4;
	while (--i);
#endif
}

/******************************************************
Function	:delay720usForDs18b20
Input		:N/A
Output		:N/A
Return		:N/A
Description	:N/A
Note		:1.这里的延时是由STC-ISP V6.66(软件延时计算器)
				生成。

			 2.这里的延时由两个版本,一个用于ds18b20开发板,
			 一个用于ds18b20的proteus仿真,因为DS118B20对
			 时间要求较高,所以需要需要根据具体实验选择。

******************************************************/
void delay720usForDs18b20(void)	//11.0592MZH
{
#if  (TEST==1) //用于开发板
	unsigned char i, j;

	_nop_();
	i = 18;
	j = 187;
	do
	{
		while (--j);
	} while (--i);
#elif (TEST==0)	//用于proteus仿真
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 70;
	do
	{
		while (--j);
	} while (--i);
#endif 
}

/******************************************************
Function	:ds18b20Init
Input		:N/A
Output		:N/A
Return		:N/A
Description	:N/A
Note		:经过测试在11.0592MHZ和12.00MHZ条件下都可以
			检测到ds18b20的存在。
******************************************************/
SB8 ds18b20Init(void)
{

	SB8 existenceFlag ; 
	UB8 i=0 ;
	
	ds18b20_io_bit = HIGH_LEVEL ;
	_nop_() ; 
	_nop_() ;	

	/*master transmit the reset pulse */
	ds18b20_io_bit = LOW_LEVEL ;
	delay720usForDs18b20();

	/*rising edge*/
	ds18b20_io_bit = HIGH_LEVEL ;

	/*ds18b20 wait 15us to 60us then transmit a presence pulse by 
	pulling the 1-wire low for 60us to 240 us */

	delay15usForDs18b20();
	delay15usForDs18b20(); 
	delay15usForDs18b20();
	delay15usForDs18b20();

	
	if( ! ds18b20_io_bit)
	{/*ds18b20 eixstence*/
		existenceFlag = DS18B20_EXISTENCE;
	}
	else
	{/*no ds18b20*/	
		existenceFlag = DS18B20_NOT_EXISTENCE;			   
	}

	while((!ds18b20_io_bit) && (i<250))
	{
		i++;/*wait*//*暂时,具体见调试*/
		/*经过测试,这里的250对于11.0592MHZ和12MHZ都远远足够了*/
	}

	return existenceFlag ;
}

/******************************************************
Function	:ds18b20WriteByte
Input		:the data which ready to write to ds18b20
Output		:N/A
Return		:N/A
Description	:write byte-data to ds18b20
Note		:N/A
******************************************************/
void ds18b20WriteByte(UB8 dataCode)
{
	UB8 i ;

	for(i=0 ; i<8 ; i++)
	{
		ds18b20_io_bit = HIGH_LEVEL ;
		_nop_();
		_nop_();
		ds18b20_io_bit = LOW_LEVEL ;
		_nop_();
		_nop_();
		
		ds18b20_io_bit = dataCode &  0x01;
		dataCode>>=1;
	
		delay15usForDs18b20() ;
		delay15usForDs18b20() ;
		delay15usForDs18b20() ;
		delay15usForDs18b20() ;
	

		/*试验中发现这一句不可以少,尽管下一个循环的第一句也是同样的内容???*/
		ds18b20_io_bit = HIGH_LEVEL ;
		_nop_();
		_nop_();

	}
}

/******************************************************
Function	:ds18b20ReadByte
Input		:N/A
Output		:N/
Return		:the data form ds18b20
Description	:N/A
Note		:N/A
******************************************************/
UB8 ds18b20ReadByte(void)
{
	UB8 dataCode = 0x00 ;
	UB8 i ;

	for(i=0 ; i<8 ; i++)
	{
		ds18b20_io_bit = HIGH_LEVEL ;
		_nop_();
		_nop_();
		ds18b20_io_bit = LOW_LEVEL ;
		_nop_();
		_nop_();
		ds18b20_io_bit = HIGH_LEVEL ;
		_nop_();
		_nop_();
	
		if(ds18b20_io_bit)
		{
			dataCode |= (0x01 << i) ;
		}
	
		delay15usForDs18b20() ;
		delay15usForDs18b20() ;
		delay15usForDs18b20() ;
		delay15usForDs18b20() ;
	}

	return dataCode ;
}

/******************************************************
Function	:delay750ms
Input		:N/A
Output		:N/A
Return		:N/A
Description	:用于ds18b20的内部操作时间等待
Note		:N/A
******************************************************/
void delay750ms(void)
{
/*
发现数据最开始上电时为85,但是过一会变成23.063,,而且
感觉温度没有那么高,用于后期调试
*/
	unsigned char i, j, k;

	i = 32;
	j = 133;
	k = 87;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

/******************************************************
Function	:ds18b20ReadTemperature
Input		:N/A
Output		:N/A
Return		:the temperature of environment
Description	:N/A
Note		:N/A
******************************************************/
int  ds18b20ReadTemperature(void)
{
	int temperatureCode ;
	UB8 temperature_th , temperature_tl ;

	ds18b20Init() ;
	ds18b20WriteByte(DS18B20_SKIP_ROM) ;/*跳过ROM操作*/
	ds18b20WriteByte(DS18B20_CONVERT_TEMPERATURE) ;/*转换温度命令*/
	#if (TEST==1)
		delay750ms();
	#endif
	/*这里如果没有延时,温度也能够测出来,不过刚上电时,
	会显示85摄氏度(默认),如果有足够的延时,这里的就会错过这段时间*/
	//while(!ds18b20_io_bit);
	
	ds18b20Init() ;
	ds18b20WriteByte(DS18B20_SKIP_ROM) ;
	ds18b20WriteByte(DS18B20_READ_SCRATCHPAD) ;
	
	temperature_tl = ds18b20ReadByte() ;
	temperature_th = ds18b20ReadByte() ;
	temperatureCode = (temperature_th << 8) | temperature_tl ;

	return temperatureCode ;
}

 

/*################ds18b20.c end################*/

 

补充:common.h

#ifndef __COMMON_H__
#define __COMMON_H__

typedef unsigned char UB8 ;
typedef unsigned short int UW16 ;
typedef unsigned long UL32 ;

typedef char SB8;
typedef short int SW16 ;
typedef long SL32 ;
	
#define HIGH_LEVEL 1	
#define LOW_LEVEL  0


#endif	/*__COMMON_H__*/


 

单片机控制单总线协议DS18B20之模块编程,布布扣,bubuko.com

单片机控制单总线协议DS18B20之模块编程

原文:http://blog.csdn.net/yagnruinihao/article/details/21258583

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!