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

📄 ds18b20.c

📁 DS18B20最全驱动.包含CRC8算法.ROM Search等.主机采用AVR mega16或者mega32.原创作品.
💻 C
字号:
#include "system.h"

//----------------DS18B20温度读取程序-----------------
//OneWire.c文件,用于操作DS18B20/DS2401等单总线器件
//注意实际硬件工作的频率


volatile unsigned char EnableOneWireFlag=1;		//用户设置的DS18B20使能标志
volatile unsigned char OneWireConnectFlag=1;	//DS18B20连接标志
volatile unsigned int  DataT=150;				//实际测得的温度值
volatile unsigned char _T=1;					//正负温度标志:<16为正 >15为负
volatile unsigned char DataT_shi=0;				//温度的十位
volatile unsigned char DataT_ge=0;				//温度的个位
volatile unsigned char ProcessReadT=_ConvertT;	//读取DS18B20温度时的进程,0:启动(复位)DS18B20; 1:读取温度并计算数值
volatile unsigned char ReadTFlag=0;				//读取DS18B20温度时,启动温度转化等待200ms,开启计数器的标志
volatile unsigned char ReadTCounter=0;			//读取DS18B20温度时,启动温度转化等待200ms计数器
volatile unsigned char TChangeFlag=0;			//温度变化标志位
volatile unsigned char LastT=150;				//上一次测得的温度值
volatile unsigned char TWarningFlag=0;			//温度警告标志
volatile unsigned char OneWireID[8];			//DS18B20	ROM	ID
volatile unsigned char TemperatrueBuffer[6];	//百位.十位.个位..十分位.百分位.千分位.
volatile unsigned int  CheckDS18B20Counter=0;	//重检DS18B20计时器
volatile unsigned char CheckDS18B20TimeoutFlag=0;	//重检DS18B20定时到时标志


prog_uchar Crc8Table[256]={
0,94, 188,226,97,63,221,131,194,156,126,32,163,253,31, 65,
157,195,33,127,252,162,64,30,95,1,227,189,62,96,130,  220,
35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,  98,
190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,  255,
70,24,250,164,39,121,155,197,132,218,56,102,229,187,89, 7,
219,133,103,57,186,228,6,88,25,71,165,251,120,38,196, 154,
101,59,217,135,4,90,184,230,167,249,27,69,198,152,122, 36,
248,166,68,26,153,199,37,123,58,100,134,216,91,5,231, 185,
140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
202,148, 118,40,171,245,23,73,8,86,180,234,105,55,213,139,
87,9,235,181,54,104,138,212,149,203,41,119,244,170,72, 22,
233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53};
//#define   Crc8Table(i)		(pgm_read_byte(Crc8Table+(i)))


unsigned char CRC8(unsigned char *checkbuf,unsigned char checkbyte)
{
	unsigned char i;
	unsigned char crcdata;
	for(i=0;i<checkbyte;i++)
	{
		crcdata=pgm_read_byte(Crc8Table+(crcdata^(*(checkbuf+i))));
	}
    return crcdata;
}

void OneWireInit(void)		//复位
{
	unsigned int i=0;
	OneWireDDR	|= (1<<DS18B20);
	OneWirePORT	|= (1<<DS18B20);
	OneWirePORT	&=~(1<<DS18B20);
	_delay_us(200);			//480~960us
	_delay_us(200);
	_delay_us(200);
	_delay_us(100);
	OneWirePORT	|= (1<<DS18B20);
	OneWireDDR	&=~(1<<DS18B20);
	_delay_us(90);			//15~60us
	while(OneWirePIN&(1<<DS18B20))	//注意此处如果检测不到DS18B20,那会产生温度报警,但是不能影响正常工作.
	{
		i++;
		if(i>=500)					//注意此处i的大小要根据测温器件与系统的连接线的长短而定
		{
			OneWireConnectFlag=0;
			return;
		}
	}
	OneWireConnectFlag=1;
	OneWireDDR	|= (1<<DS18B20);
	OneWirePORT	|= (1<<DS18B20);
	_delay_us(240);			//60~240us
}

void ReadOneWireID(void)
{
	unsigned char i;
	OneWireInit();
	WriteOneWire(0x33);		//ReadROM(读ROM) [33h]
	for(i=0;i<8;i++)
	{
		OneWireID[i]=ReadOneWire();
	}
}

void WriteOneWire(unsigned char Data)	//向单总线的从机写入数据(先写低位再写高位,与SPI相反)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		OneWirePORT&=~(1<<DS18B20);
		if(Data&(1<<i))OneWirePORT|=(1<<DS18B20);//写数据了,先写低位的!
		else OneWirePORT&=~(1<<DS18B20);
		_delay_us(60);			//15~60us
		OneWirePORT|=(1<<DS18B20);
	}
	OneWirePORT|=(1<<DS18B20);
	_delay_us(3);
}

unsigned char ReadOneWire(void)
{
	unsigned char temp;
	unsigned char n;
	unsigned char OneWireData=0;
	for(n=0;n<8;n++)
	{
		OneWirePORT	&=~(1<<DS18B20);
		OneWirePORT	|= (1<<DS18B20);
		OneWireDDR	&=~(1<<DS18B20);
		temp=(OneWirePIN&(1<<DS18B20));		//读数据,从低位开始
		if(temp)OneWireData	|= (1<<n);
		else OneWireData	&=~(1<<n);
		_delay_us(120);				//60~120us
		OneWireDDR	|= (1<<DS18B20);
	}
	return OneWireData;
}

void ReadTemperature(void)		//读取温度值 
{
	unsigned char i;	
	unsigned char OneWireData[8];

	if(ProcessReadT==_ConvertT)
	{
		OneWireInit();			//复位DS18B20 
		WriteOneWire(0xcc);	//跳过ID码匹配,适用于一个DS18B20 
		WriteOneWire(0x44);	//启动温度转换 
		ReadTFlag=1;
	}
	else if(ProcessReadT==_ReadT)
	{
		ProcessReadT=_ConvertT;
		OneWireInit();
		WriteOneWire(0xcc);	//跳过ID码匹配,适用于一个DS18B20 
		WriteOneWire(0xbe);	//通知DS18B20,准备读数据 

		for(i=0;i<8;i++)
		{
			OneWireData[i]=ReadOneWire();
			//TEMPERATURELSB	0
			//TEMPERATUREMSB	1
			//TH/USERBYTE1		2
			//TL/USERBVTE2		3
			//RESERVED			4
			//RESERVED			5
			//COUNTREMAIN		6
			//COUNTPER			7
			//CRC				8
		}
		/*
		UartSendByte(OneWireData,8);
		OneWireData[7]=CRC8(OneWireData,7);
		UartSendByte(OneWireData,8);
		_delay_ms(3);
		OneWireInit();
		ReadOneWireID();
		UartSendByte(OneWireID,8);
		OneWireID[7]=CRC8(OneWireID,7);
		UartSendByte(OneWireID,8);
		*/
//		if(OneWireData[7]==CRC8(OneWireData,7))
		{
			if(OneWireData[1]<16)
			{
				_T=1;
			}
			DataT=OneWireData[1]*256+OneWireData[0];//合并后得到原始温度数据 
			if(_T)	//+
			{
				DataT=DataT/16;
			}
			else 	//-
			{
				DataT=(~DataT+1)/16;
			}
			//计算实际温度 -55~+125 器件以0.0625摄氏度递增
			//如果温度为正 则T的最高位的4位都为0 否则为1;
			//负温度的计算:原始数据取反 加1 再乘以0.0625;正温度的计算:原始数据乘以0.0625 
			
			if((DataT!=85)&(DataT!=95))
			{
				TemperatrueBuffer[0]=DataT/100;		//100 
				TemperatrueBuffer[1]=DataT/10%10;	//10  
				TemperatrueBuffer[2]=DataT%10;		//1 
				DataT%=0xff;
				DataT*=625;
				TemperatrueBuffer[3]=DataT/100%10;	//.1
				TemperatrueBuffer[4]=DataT/10%10;	//0.01
				TemperatrueBuffer[5]=DataT%10;		//0.001
			}
			else
			{
				for(i=0;i<8;i++)
				{
					TemperatrueBuffer[i]=0;
				}
				UartSendString((unsigned char *)"测温异常!");
				UartSendString((unsigned char *)"\r\n");
			}
		}
	}
}


//温度处理函数,按照用户设定,有温度报警时,可以有一个IO进行开启或关闭操作.
//目前软件设定是一个加热设备.低温开启IO,高温关闭IO.
//在参数设置中,可以设置是否启用温度报警IO机制
void TemperatureProcessing(void)
{
	unsigned char temp[10]={'\0'};
	
	UartSendString((unsigned char *)"当前温度是:");
	if(_T)	//+
	{
		if(TemperatrueBuffer[0])		//最高百位
		{
			sprintf(temp,"%d%d%d.%d%d%d",TemperatrueBuffer[0]%256,TemperatrueBuffer[1]%256,TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
		}
		else if(TemperatrueBuffer[1])	//最高十位
		{
			sprintf(temp,"%d%d.%d%d%d",TemperatrueBuffer[1]%256,TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
		}
		else							//最高个位
		{
			sprintf(temp,"%d.%d%d%d",TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
		}
	}
	else	//-
	{
		if(TemperatrueBuffer[1])		//最高十位
		{
			sprintf(temp,"-%d%d.%d%d%d",TemperatrueBuffer[1]%256,TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
		}
		else							//最高个位
		{
			sprintf(temp,"-%d.%d%d%d",TemperatrueBuffer[2]%256,TemperatrueBuffer[3]%256,TemperatrueBuffer[4]%256,TemperatrueBuffer[5]%256);
		}
	}
	UartSendString(temp);
	UartSendString((unsigned char *)"℃");
	UartSendString((unsigned char *)"\r\n");
}


void DS18B20Processing(void)
{
	if(OneWireConnectFlag)
	{
		ReadTemperature();
		TemperatureProcessing();
	}
	else
	{
		if(EnableOneWireFlag)//如果的确设置的测温器件,那么隔ns检测一下器件是否重新连接
		{
			if(CheckDS18B20TimeoutFlag)
			{
				CheckDS18B20TimeoutFlag=0;
				OneWireInit();
			}
		}
	}
}

⌨️ 快捷键说明

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