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

📄 ds18b20.c

📁 经精心修改后
💻 C
字号:
//文件名:ds18b20.c
//功能:实现温度显示
//硬件连接:外部电源供电,且只有1个DS18B20
//原理:单总线协议(读取温度七步骤,如程序注释)
//注意:此程序晶振为12M,其他晶振需跟据DS18B20资料修改
//编写:王晓荣
//日期:20070626
////////////////////////////////////////////////////////////////////////////

#include <REGX51.H>	 
#include <intrins.h>	 //	声明_nop_()  便于实现延时
#define DS18B20 P1_0 
unsigned char xdata LEDSEG _at_ 0xfeff;	  //P2.0
unsigned char xdata LEDBIT _at_ 0xfdff;	  //P2.1
unsigned char code LEDMAP[] =
{
	0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d,  
	0x07, 0x7f, 0x6f, 0x00, 0x79, 0x46, 0x40,
	//                 灭    "E"   "+"   "-"
};
bit DS18B20_FLG = 0;    //“1”:DS18B20存在 ;“0”:不存在
bit TEMP_FLG = 0;       //“1”:温度为负
bit T1S_FLG = 0;		//“1”:1秒钟到
unsigned int t1s; 
unsigned char LEDBuf[6];

//定时中断
Timer0() interrupt 1
{
	t1s++;
	if(4000 == t1s)
	{
		t1s =0;	
		T1S_FLG = 1;	
	}
}

void delay(unsigned int i)
{
	while(i--);
}

//显示子函数
display()
{
	unsigned char i;
	unsigned char outbit;
	outbit = 0x01;  // 从右边开始显示
	for (i = 0; i < 4; i++)
	{
		LEDBIT = 0x00;     // 关所有LED
		LEDSEG = LEDMAP[LEDBuf[i]];
		LEDBIT = outbit;
		delay(100);
		outbit <<= 1;     // 显示下一位
	}
}

/////////////////////////////////////////////////////////////////////////////
//DS18B20驱动 

//初始化DS18B20步骤:
//    1)总线拉低,并延时480us-960us
//    2)总线拉高,等待回应,如DS18B20为“0”则初始化成功,
//       如等待60us仍无回应,则DS18B20不存在
Init_DS18B20(void)
{
	bit re = 0;
	unsigned char temp = 30;	
	DS18B20 = 1;    
	_nop_();  		//无需精确
	_nop_();
	DS18B20 = 0;    //拉低
	delay(80); 		// ★务必在480us-960us之间
	DS18B20 = 1;    //拉高总线
	delay(1);		//无需精确
	while(temp--)	//等待60us以上
	{
		re = DS18B20;      //如果x=0则初始化成功
		if(0 == re)
		{
			DS18B20_FLG = 1;
			delay(20);	  //无需精确
			return(0);	
		}
	} 	  
}

//读DS18B20一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i = 0;
	unsigned char d = 0;
	for (i=8;i>0;i--)
	{
		DS18B20 = 0; // 给脉冲信号
		d >>= 1;
		_nop_();
		DS18B20 = 1; // 给脉冲信号
		_nop_();	 //	需延时10us-14us
		_nop_();
		_nop_();
		_nop_();
		_nop_();	 
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		if(DS18B20 == 1)
		{
			d = d | 0x80;
		}
		delay(10);		       //	需延时60us以上
	}
	delay(10);	
	return(d);
}

//写一个字节
Write_DS18B20(unsigned char d)
{
	unsigned char i=0;
	for (i=8; i>0; i--)
	{
		DS18B20 = 1;
		_nop_();
		_nop_();
		DS18B20 = 0;
		_nop_();	//	需延时15us-60us
		_nop_();
		_nop_();
		_nop_();	// ?奇怪:当此处延时超过30us时,会出错
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();					
		DS18B20 = d & 0x01;
		delay(7);			  //	需延时60us-120us
		d >>= 1;
	}
	DS18B20 = 1;
	delay(7);
}

//温度返回值被放大100倍
unsigned int TurnTemp(unsigned int temp)
{ 	
	int t;	
	if(temp > 32768)		 //当读取的温度为负时
	{
	 	t = (~temp + 1) * 25 / 4;
		TEMP_FLG = 1;
	}
	else					 //当读取的温度为正时
	{
	 	t = temp * 25 / 4;
		TEMP_FLG = 0;
	}
	return(t);	
}

//读取温度
int ReadTemp(void)
{
	unsigned char tempLowChar = 0;
	unsigned char tempHighChar = 0;
	unsigned int  tempInt = 0;
	int temp = 0;

	DS18B20_FLG = 0;
	Init_DS18B20();	  			//步骤1:初始化
	if(DS18B20_FLG == 0)		//如果没有检测到DS18B20返回
	{		
		return(0);	
	}	

	Write_DS18B20(0xCC);  		//步骤2:跳过读序号操作(单个DS18B20适用)
	Write_DS18B20(0x44);  		//步骤3:启动温度转换

	TL0 = 256 - 250;			//利用定时器实现1s延时
	TH0 = TL0;
	TR0 = 1;
	T1S_FLG = 0;		
	while(!T1S_FLG)		        //步骤4:等待温度转换完成(必须大于500ms)
	{
		display();	
	}	  
	
	TR0 = 0;
	
	DS18B20_FLG = 0;
	Init_DS18B20();	  			//步骤5:初始化
	if(DS18B20_FLG == 0)		//如果没有检测到DS18B20返回
	{		
		return(0);	
	}
	Write_DS18B20(0xCC); 			//步骤6:跳过读序号操作(单个DS18B20适用)
	Write_DS18B20(0xBE);     		//步骤7:读取温度寄存器设置(共可读9个寄存器,前两个就是温度) 
	
	tempLowChar = Read_DS18B20();	//步骤8:读取温度数据低8位
	tempHighChar = Read_DS18B20();	//步骤8:读取温度数据高4位
	tempInt = tempHighChar;
	tempInt <<= 8;
	tempInt = tempInt | tempLowChar; 
	temp = TurnTemp(tempInt); 	
	return(temp);
}
//DS18B20驱动
/////////////////////////////////////////////////////////////////////////////

//实现四位LED温度显示,其中最高位LED显示温度正负,最低位为温度的一位小数
main()
{	
	unsigned int t  =0;
		
	IE = 0x82;		 //开1#中断
	TMOD = 0x02;	 //定时工作方式2	
	while(1)
	{ 
		t = ReadTemp();//读温度
		if(DS18B20_FLG == 0)
		{
			LEDBuf[3] = 10;		 
			LEDBuf[2] = 10;
			LEDBuf[1] = 11;
			LEDBuf[0] = 0;		 //显示“E0”
			
		}
		else
		{
			if(TEMP_FLG)
			{
				if(t > 5500)
				{
					LEDBuf[3] = 10;
					LEDBuf[2] = 10;
					LEDBuf[1] = 11;
					LEDBuf[0] = 1;		//显示“E1”
				}
				else
				{
					LEDBuf[3] = 13;             //显示“-”
					LEDBuf[2] = t/1000;			//显示温度的十位
					LEDBuf[1] = (t/100)%10;		//显示温度的个位
					LEDBuf[0] = (t/10)%10;		//显示温度的小数位
				}								
			}
			else
			{
				if(t > 20000)
				{
					LEDBuf[3] = 10;
					LEDBuf[2] = 10;
					LEDBuf[1] = 11;
					LEDBuf[0] = 1;		//显示“E2”
				}
				else
				{
					LEDBuf[3] = 12;				 //显示“+”
					LEDBuf[2] = t/1000;			 //显示温度的十位
					LEDBuf[1] = (t/100)%10;		 //显示温度的个位
					LEDBuf[0] = (t/10)%10;		 //显示温度的小数位
				}								
			}			
		}			
		display();			
	}
}


⌨️ 快捷键说明

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