资讯详情

单片机Ds18b20温度传感器的学习(附踩雷清单)

主函数

#include"reg52.h" #include"temp.h"///这个头文件要写,否则会报错! typedef unsigned int u16; typedef unsigned char u8; sbit LSA=P2^2;//数码管用74LS138译码器被控制,所以有了这些东西 sbit LSB=P2^3; sbit LSC=P2^4; char num=0;//有用。在后面解释 u8 DisplayData[8];//工具数组,接受num转换后的16进制数传递给smg段数组 ///上面的数组要写成比5大的数字,因为要显示6位数字管,然后拼写注意! u8 code smgduan[10]={ 
       0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};///数字管段选择,0~9 void delay(u16 i) { 
         //粗延时函数  while(i--); } void datapros(int temp)//别忘了参数表!!!因为你的主函数调用这个函数是为了传入实参! { 
         float tp;//定义温度浮点数。由于数据处理中有小数点,温度被赋予浮点变量  if(temp<0)  { 
       //如果从温度传感器里读取的温度是负数   DisplayData[0]=0x40;//让数码管显示一个负号   ///因为读取的温度是实际温度的补码,所以减1,然后取出原码   temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。  //读取的温度经一顿转换后变为真正的10进制温度 } else//如果从温度传感器里读取的温度是0或者正数 { 
          DisplayData[0]=0x00;//那就不用在数码管最前头显示一个负号了 tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量 //如果温度是正的那么,那么正数的原码就是补码它本身 temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } DisplayData[1]=smgduan[temp/10000];//因为数码管我们只用右边的6位,而且我们让temp多×了100,所以这里/10000 //所以这里剥离temp的百位给DisplayData数组存着 数组下标为0的数字你已经占用了,这里必须为1开始 DisplayData[2]=smgduan[temp%10000/1000];//剥离temp的十位给DisplayData数组存着 DisplayData[3]=smgduan[temp%1000/100]|0x80; //注意这些数字要写对! //剥离temp的个位给DisplayData数组存着,因为还要显示小数点,所以 //我们必须让数码管的dp位亮着,就0x80(因为dp位为数码管段选位的最高位)即可。 DisplayData[4] = smgduan[temp % 100 / 10];//剥离temp的小数点后一位给DisplayData数组存着 DisplayData[5] = smgduan[temp % 10];//剥离temp的小数点后二位给DisplayData数组存着 } void DigDisplay() { 
          u8 i; for(i=0;i<6;i++)//这个要改成6,因为你要显示6位数码管!!!!!!! { 
          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];//发送disp数组里存着的num剥离出的位给P0管,注意,这里是5-i,因为 //数码管第0位是在最右侧,第7位在最左侧,所以遵循”千百十个小数点后1小数点后2“这样的从左至右顺序来让 //数码管显示数字 delay(100);//间隔1us扫描一次 P0=0x00;//数码管消隐 //从P0=DisplayData....到P0=0x00;这里,写在for循环里switch外!!!!记下 } } int main() { 
          while(1) { 
          datapros(DS18b20ReadTemp());//数据处理函数,实参是读取温度传感器里的温度 //调用datapros()函数的实参这个位置的函数读取温度值读取完毕,返回温度给datapro() DigDisplay();//数码管显示函数 } } 

temp.c文件

#include"temp.h" 
//#include "reg52.h"
void Delay1ms(uint y)
{ 
       
	uint x;
	for(;y>0;y--)
	{ 
       
		for(x=110;x>0;x--);
	}
}
//较为精确的延时1ms的函数
//下面为温度传感器初始化函数
uchar Ds18b20Init()
{ 
       //代码模拟温度传感器的初始化时序
	uchar i;
	DSPORT=0;//将总线(数据线)拉低480us~960us
	i=70;//为了延时642us,通过下面的while(i--);
	while(i--);
	DSPORT=1;//然后拉高总线,如果DS18B20温度传感器做出反应将会在15us~60us后将总线拉低
	i=0;//下面还用到这个i
	while(DSPORT)//等待DS18B20温度传感器自己拉低总线电位
	//如果温度传感器存在,证明可以自己拉低总线电位,则直接跳过while循环
	//返回一个1即可,证明温度传感器存在。否则就在while循环里返回一个0,证明不存在。
	{ 
       
		Delay1ms(1);//实参设置为1,就延时1个ms
		i++;
		if(i>5)//等待5ms(自定义愿意等待多少多长时间判定为超时),若5ms后温度传感器还没有作出反应,则初始化失败,证明
		//温度传感器不存在或者坏了。
		{ 
       
			return 0;//初始化失败
		}
	}
	return 1;//初始化成功,注意return1的位置!!别写while循环里!!
}//漏了个},注意
void Ds18b20WriteByte(uchar dat)
{ 
       //向温度传感器写入一个字节的数据的函数
//代码模拟温度传感器写入时序
	uint i=0,j;	//i=0是习惯,不初始化i也行
	for(j=0;j<8;j++)
	{ 
       
		DSPORT=0;//每写入一位数据之前,先把总线拉低1us(时序就是这样的)
		i++;
		//注意DSPORT的拼写!!!!
		DSPORT=dat&0x01;//然后写入一个数据,从最低位开始。只能一个一个位写入
		//温度传感器。所以你必须先让dat的其他位为0,然后根据循环8次让位一个一个写入
		i=6;//因为下面要用到i,你必须设定i
		while(i--);//延时68us,时序图上写着延时最少60us
		DSPORT=1;//然后释放(恢复)总线(拉高总线)。至少给总线1us的时间让总线拉高
		//才能接着写入第二个数值(执行一行代码就是1us,所以不必再写个延时代码huo
		//函数
		dat>>=1;//因为这一位写完了,你要写dat的下一位数据给温度传感器(dat传进
		//来的时候是8位),你就要给dat移位,把写完的这位给移走(写入位是从低位到
		//高位写(规定))
	}	
}
uchar Ds18b20ReadByte()
{ 
       
	//读取温度传感器的一个字节的函数
	uchar byte,bi;//下面解释定义两个无符号字符型的目的
	uint i,j;
	for(j=8;j>0;j--)//这个循环和写入函数那个循环含义一致
	//也是一位一位读(加起来相当于读了一个字节),从低位到高位读
	{ 
       
 		DSPORT=0;//先将总线拉低1us(时序图规定)
		i++;//执行一行代码就是1us
		DSPORT=1;//然后释放(恢复)总线(时序图规定)
		i++;
		i++;//大约延时6us等待数据稳定
		bi=DSPORT;//读取数据,从最低位开始读取。(根据时序图事实,此时DSPORT可能是0或者1)
		byte=(byte>>1)|(bi<<7);
		//先将byte右移一位,然后和左移7位后的bi或运算,移动byte后高位补0
		//举个例子,如果byte读取的是0000 0000,然后移位是0000 0000,然后bi是1,左移七位
		//就变成了1000 0000,然后这俩相或,存储在byte中,就变成了1000 0000
		//然后再循环下来,bi=1,byte先右移1位让之前存储在byte的字节给移开把位置
		//让给现在读取的位。然后bi又左移7位,然后再相或,byte就变成了1100 0000,
		//如此循环,读取的位顺着byte>>1就往低位走了,符合从最低位开始读取的规则。
		i=4;//读取完之后等待58us(下面的while循环可以实现)再接着读取下一个数
		while(i--);
	}
	return byte;//读取完毕,返回读取的一个字节
}
void Ds18b20ChangeTemp()
{ 
       //温度传感器数据转温度函数,让温度传感器开始转换温度
	Ds18b20Init();//初始化温度传感器
	Delay1ms(1);//根据需要延时1ms
	Ds18b20WriteByte(0xcc);//根据需要,跳过ROM操作命令
	Ds18b20WriteByte(0x44);//发送一个温度转换命令给温度传感器
	//Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}
void Ds18b20ReadTempCom()//函数名拼写问题。。。。所以会有警告,给老子注意!!!!!!!!!
{ 
       //发送读取温度传感器里的温度的命令
	Ds18b20Init();//初始化温度传感器
	Delay1ms(1); //根据需要延时1ms
	Ds18b20WriteByte(0xcc);//根据需要,跳过ROM操作命令
	Ds18b20WriteByte(0xbe);//发送读取温度传感器里的温度的命令
}
int DS18b20ReadTemp()
{ 
       //读取温度传感器里的温度。注意这些函数的功能!!!!
	int temp=0;
	uchar tmh,tml;//规定,只能这么分开存温度值,而且要接受读取温度传感器里的温度数据
	Ds18b20ChangeTemp();//先发送让温度传感器数据转成温度的命令
	//注意函数的拼写和变量的拼写!!!
	Ds18b20ReadTempCom();//等待数据转换成温度后发送读取温度传感器里温度的命令
	tml=Ds18b20ReadByte();//读取16位温度值,先读取温度的低8位给tml
	tmh=Ds18b20ReadByte();//再读取高8位给tmh
	temp=tmh;
	temp<<=8;//先让返回的温度值(真正的温度)接收高8位的温度二进制值
	//然后给把这高8位左移8位变成真正的高8位,以提供位置接收温度二进制值低8位
	temp|=tml;//或一下就可以了,很方便省事。也能保证高8位的安全,高8位数据不被篡改
	return temp;//读取温度值读取完毕,返回温度给主函数调用的地方。
}

temp.h文件

#ifndef _temp_H_
#define _temp_H_
#include"reg52.h"//这个别丢,很重要
#ifndef uchar //这少了c
#define uchar unsigned char
#endif

#ifndef uint
#define uint unsigned int
#endif
//两个重定义,ifndef 如果没有则定义的意思,然后下面就define,define完了别忘了endif
//来终止if(或说define),这个格式务必记好!!!
sbit DSPORT=P3^7;//定义温度传感器使用的IO口,这里DSPORT是温传器的名字
void Delay1ms(uint );
uchar Ds18b20Init();//温度传感器初始化函数
void Ds18b20WriteByte(uchar com);//写入温度传感器的数据函数
uchar Ds18b20ReadByte();//读取温度传感器里的一字节的数据函数
void Ds18b20ChangeTemp();//变换温度传感器数据的函数
void Ds18b20ReadTempCom();//发送读取温度传感器里的温度的命令
int DS18b20ReadTemp();//读取温度传感器里温度的数据函数
//这里定义为int是方便主函数的调用。
//以上声明全局函数
#endif

注意函数名的拼写,这里函数名又臭又长。 如果函数名在头文件、头文件附属c文件、主函数c文件不一致,则会报错:

*** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS SEGMENT: ?PR?DS18B20READTEMCOM?TEMP *** WARNING L1: UNRESOLVED EXTERNAL SYMBOL SYMBOL: DS18B20READTEMPCOM MODULE: temp.obj (TEMP) *** WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL: DS18B20READTEMPCOM MODULE: temp.obj (TEMP) ADDRESS: 05F1H 翻译: ***警告L16:未调用段,忽略覆盖过程

段:公关? DS18B20TEMPCOM ? TEMP

***警告L1:外部符号未解析

象征:DS18B20READTEMPCOM

模块:temp.obj(临时)

***警告L2:引用外部未解析

象征:DS18B20READTEMPCOM

模块:temp.obj(临时)

地址:05 f1h

气死,找这个bug找了半天!

标签: tp3231温度传感器ds18b20温度传感器参数

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台