⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ds18b20.c

📁 Keil C 写的51单片机DS18B20温度传感器的驱动
💻 C
字号:
/*******************************************************************************
*
*file: DS18B20.c
*
*功能描述:DS18B20温度传感器的驱动
*编写人员:传承科技 吴明显
*编写日期:2009/01/10
*
*第一次修改人员:
*第一次修改日期:
********************************************************************************/

#include<reg51.h>
#include"inc/define.h"		//数据类型定义
#include"inc/exactdly.h"	//精确延时函数
#include"inc/ds18b20.h"

/*给ROM命令字取个易记的名称 */
#define DS18B20_READ_ROM 	0x33		//读取ROM中的64位序列号及CRC
#define DS18B20_MATCH_ROM 	0x55		//让总线控制器选取多个DS18B20中的特定一个
#define DS18B20_SKIP_ROM 	0xCC		//跳过ROM命令字直接对RAM进行操作
#define DS18B20_SEARCH_ROM 	0xF0		//用以获取总线上所有DS18B20的64位序列号及CRC
#define DS18B20_ALARM_SEARCH 	0xEC	//搜索有报警的所有DS18B20
/*给RAM命令字取个易记的名称 */
#define DS18B20_CONVERT_TEMPERT 0x44	//开始温度转换
#define DS18B20_RD_SCRATCHPAD 0xBE		//读取暂存器和CRC中的值,共9个字节
#define DS18B20_WR_SCRATCHPAD 0x4E		//把字节写入暂存器的地址2和3--报警触发
#define DS18B20_CP_SCRATCHPAD 0x48		//把暂存器内容(报警触发)拷贝到非易失的EEPROM
#define DS18B20_RECALL_EEPROM 0xB8		//把EEPROM中值召回暂存器
#define DS18B20_RD_POWER_MODE 0xB4		//用以判断DS18B20的供电方式


/*The DS18B20s' ROM Serial NUmbers    */
u8 code DS18B20_NO[DS18B20_MAX_COUNT][8] = 
			   {{0x28,0x30,0xC5,0xB8,0x00,0x00,0x00,0x8E},		
				{0x28,0xE5,0xE0,0xC9,0x01,0x00,0x00,0x07}};
							 									
u8 gActive_DS18B20  = 0;

/*******************************************************************
*功能描述:DS18B20复位及存在检测(通过存在脉冲判断有无正常工作的DS1820)
*函数名称:Reset
*函数参数:
*返回值:  0 存在正常工作的DS18B20;其他 不存在正常工作的	DS18B20
*注意事项:
********************************************************************/
u8  Reset()
{
	u8 flag=0;
	    
 	DS18B20_DQ = 0;		//单片机拉低总线以产生复位脉冲
	Delay200us();		//延时480us--960us完成复位
	Delay200us();
	Delay200us();
 	DS18B20_DQ = 1;  	//单片机释放总线
 	Delay50us(); 		//等待60--240us
	Delay10us();
 	flag=DS18B20_DQ;	//低电平表示有DS18B20回应
 	Delay200us(); 		//延时至少240us等待总线恢复
	Delay200us();

 	return flag;  
}

/**********************************************************
*功能描述:写一个字节数据到DS18B20
*函数名称:InputByte
*函数参数:
*返回值:
*注意事项:
**********************************************************/
void InputByte(u8 ibyte)
{
	u8 i;
	u8 delay;

	for (i=8;i>0;i--)
	{
		DS18B20_DQ = 0;  	//拉低总线,产生写信号
		for(delay=2;delay>0;delay--) ; 	//延时4us
		DS18B20_DQ = ibyte&01; 		//发送1位
		Delay50us(); 		//写时序至少要60us--120us
		Delay50us();
		DS18B20_DQ = 1;  	//释放总线,等待总线恢复
		ibyte>>=1; 			//准备下一位数据的传送
	}
}

/**********************************************************
*功能描述:从DS18B20中读出一个字节数据
*函数名称:OutputByte
*函数参数:
*返回值:
*注意事项:
**********************************************************/
u8 	 OutputByte()
{
	u8 i,delay;
	u8 obyte=0;

	for (i=8;i>0;i--)
  	{
  		obyte>>=1;

		DS18B20_DQ = 0;   	//拉低总线,产生读信号
	  	for(delay=2;delay>0;delay--); 	//延时4us
	   	DS18B20_DQ = 1; 	//释放总线,准备读数据
	  	for (delay=4;delay>0;delay--); 	//延时8微秒读数据
	   	if (DS18B20_DQ == 1)
	    	obyte |= 0x80;
		Delay50us(); 		//延时100us
		Delay50us();
	  	DS18B20_DQ = 1;  	//拉高总线,准备下一位数据的读取   			
	}

	return obyte;//返回读到的数据
}

/**********************************************************
*功能描述:从单总线上所有DS18B20中选中一个进行后续操作
*函数名称:SelectOne
*函数参数:
*返回值:
*注意事项:在总线上只有一个DS18B20时,可以用不提供序列号使用
*         此器件,只要置同文件中的宏ONLY_ONE为1即可
**********************************************************/
void SelectOne( )
{
	u8 i;

	if(1==ONLY_ONE)
	{
		Reset();    //复位
		InputByte(DS18B20_SKIP_ROM); 	//跳过ROM命令,当总线上只有一个DS18B20时此命令可简化操作
	}
	else
	{
	 	Reset();    //复位
		InputByte(DS18B20_MATCH_ROM); 	//DS18B20匹配,后跟64位序列号用以选中总线上特定DS18B20
		for(i=0;i<8;i++)
			InputByte(DS18B20_NO[gActive_DS18B20 ][i]);
	}	 
}

/**********************************************************
*功能描述:从给定的一组数据产生一个8位的CRC码
*函数名称:CRCGenerate
*函数参数:
*返回值:
*注意事项:要把给定数据的低字节存在数组的低地址
**********************************************************/
u8 CRCGenerate(u8 * to_data,u8 num)
{
	u8 i;
	u8 crc_data;

	crc_data=0;
	for(i=0;i<num * 8;i++)
	{
		u8 xor_l,xor_m,xor_r;
		xor_r=((to_data[i/8] >> i%8) & 0x01) ^ (crc_data & 0x01);
		xor_l=((crc_data >> 4) & 0x01) ^ xor_r;
		xor_m=((crc_data >> 3) & 0x01) ^ xor_r;
		
		crc_data >>=1;
		if(1==xor_r)
			crc_data |= 0x80;
		else
			crc_data &= 0x7F;
	   	if(1==xor_l)
			crc_data |= 0x08;
		else
			crc_data &= 0xF7;
		if(1==xor_m)
			crc_data |= 0x04;
		else
			crc_data &= 0xFB;
	}
	
	return crc_data;		
}

/**********************************************************
*功能描述:获取暂存器中的所有数据--包括CRC
*函数名称:GetRAMData
*函数参数:ramData 指向接收暂存器数据数组的指针
*返回值:
*注意事项:从DS18B20中读出的值全以unsigned char 形式保存在数
*		  组中,有符号数一补码形式存储
**********************************************************/
void GetRAMData(u8 * ramData)
{
	u8 i,j;
			
	SelectOne();
	InputByte(DS18B20_CONVERT_TEMPERT); 	//温度转换命令
	for(i=100;i>0;i--)			//完成温度转换至少需要750ms
		for(j=50;j>0;j--)
		Delay200us();
			
	SelectOne();
	InputByte(DS18B20_RD_SCRATCHPAD); 	//读DS1820温度暂存器命令
	for(i=0;i<9;i++)
		ramData[i]=OutputByte();	//获取温度数据和报警设置
}

/**********************************************************
*功能描述:获取当前温度并根据参数决定是否进行CRC校验
*函数名称:GetTempert
*函数参数:do_crc 赋值1时进行CRC校验,否则不进行
*返回值:获取温度方法1:
*			tempert_value = tempert/16.0 
*		获取温度方法2:
*			tempertH = tempert/16;		//温度值整数部分
*			tempertL = tempert & 0x0F	//温度值小数部分
*注意事项:	DS18B20的有效温度值为-55——128;本函数以返回
*			-64即-0x8400表示CRC验证未通过,即获取的温度错误
**********************************************************/	
s16 GetTempert(u8 do_crc)
{ 
	s16 tempert;
	u8 crc_data=0;
	u8 ramData[9]={0};

	GetRAMData(ramData);
	tempert =(ramData[1] << 8) + ramData[0]; //提取温度数据	
	
	if(1 == do_crc)
	{
		crc_data=CRCGenerate(ramData,8);
		if(crc_data == ramData[8])
			return tempert;
		else
			return -0x8400;
	}

	return tempert;  
}				 
/**********************************************************
*功能描述:设置报警温度上限值和下限值
*函数名称:SetAlarm
*函数参数:Alarm_H 当温度高于这个值时触发报警
*         Alarm_L 当温度低于这个值时触发报警
*返回值:
*注意事项:
**********************************************************/
void SetAlarm(s8 Alarm_H,s8 Alarm_L)
{
	u8 i;

	SelectOne(); 	
	InputByte(DS18B20_WR_SCRATCHPAD); 	//将温度报警触发写入暂存器的地址2、3
	InputByte(Alarm_H);
	InputByte(Alarm_L);

	SelectOne();
	InputByte(DS18B20_CP_SCRATCHPAD); 	//将暂存器中的报警触发值写入ROM相应位置
  	for(i=50;i>0;i--)
		Delay200us();			//写ROM需要一定时间

	SelectOne();
	InputByte(DS18B20_RECALL_EEPROM); 	//将ROM中报警触发值召回到暂存器				  
}
/**********************************************************
*功能描述:获取当前总线上唯一DS18B20的序列号
*函数名称:ReadSerialNO
*函数参数:serialNO 用以传递64位序列号
*		  do_crc 赋值1时进行CRC校验,否则不进行
*返回值:返回0表示校验正确,1为不正确;不进行校验时总返回0
*注意事项:本函数是一个工具函数,可以在总线上只有一个DS18B20时
*   	  获取他的64位序列号
************************************************************/ 
u8 GetSerialNO(u8 * serialNO,u8 do_crc)
{
	u8 i;
	u8 crc_data;

	Reset();    		//复位
	InputByte(DS18B20_READ_ROM); 
	for(i=0;i<8;i++)
		serialNO[i]=OutputByte();
	
	if(1 == do_crc)
	{
	 	crc_data=CRCGenerate(serialNO,7);
		if(crc_data == serialNO[7])
			return 0;
		else 
			return 1;	
	}

	return 0;	
} 
/*
void DS18B20_alarmSearch()
{
	bit search_direction =0;
	bit last_device_flag =0;
	bit last_discrepancy =0;
	bit id_bit,id_bit_cmp;
	u8 id_bit_num;
	u8 last_zero=0;
	byte Rom_Value[8] = {0};

	Reset();	
	InputByte(0xF0); 	//Search ROM命令
	for(id_bit_num=1;id_bit_num !=64;id_bit_num++)
	{
		id_bit=DS18B20_outputBit();
		id_bit_cmp=DS18B20_outputBit();
		if(1==id_bit && 1==id_bit_cmp)	//总线上没有传感器了
		{
			break;
		}
		else if(1==id_bit && 0==id_bit_cmp)	//参与搜索传感器的ROM 相应位为1
		{
			search_direction=1;
		}
		else if(0==id_bit && 1==id_bit_cmp)	//参与搜索传感器的ROM 相应位为0
		{
			search_direction=0;
		}
		else if(0==id_bit && 0==id_bit_cmp)	//参与搜索传感器的ROM 相应位既有0 又有1
		{
			search_direction=0;
		}

		if(0==search_direction)
			Rom_Value[id_bit_num/8] |= 0<<(id_bit_num%8);
		else
			Rom_Value[id_bit_num/8] |= 1<<(id_bit_num%8);
		DS18B20_inputBit(search_direction);
	}			
} */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -