关于51单片机读取DS18B20温度采集系统,并将读取到的数据传输到数码管上;我们书写的程序总是读取到-000.06的状况,给出以下解决办法。

关于51单片机读取DS18B20温度采集系统,并将读取到的数据传输到数码管上;我们书写的程序总是读取到-000.06的状况,给出以下解决办法。

问题所在

DS18B20初始化描述
DS18B20初始化时序图

错误源代码为

/*******************************************************************************
* 函 数 名         : Ds18b20Init
* 函数功能		   : 初始化
* 输    入         : 无
* 输    出         : 初始化成功返回1,失败返回0
*******************************************************************************/
u8 Ds18b20Init()
{
	u8 i=0;
	DSPORT = 1;	
	delay6us();
	DSPORT = 0;			 //将总线拉低480us~960us
	delay500us();
	DSPORT = 1;			//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
	i = 0;
	while(DSPORT)	//等待DS18B20拉低总线
	{
		delay80us();
		i++;
		if(i>5)//等待>5MS
		{
			return 0;//初始化失败
		}	
	}
	return 1;//初始化成功
}

通过我的对比、观察,最后得到的是DS18B20程序的初始化程序有问题,
问题是:上文程序DS18B20在将 DSPORT 数据位拉低后, 未将 DSPORT 数据位拉高;
因此我将初始化程序进行了修改,修改后的程序就是下文的程序

正确源代码

/*******************************************************************************
* 函 数 名         : Ds18b20Init
* 函数功能		   : 初始化
* 输    入         : 无
* 输    出         : 初始化成功返回1,失败返回0
*******************************************************************************/
u8 Ds18b20Init()
{
	u8 i=0;
	DSPORT = 1;	
	delay6us();
	DSPORT = 0;			 //将总线拉低480us~960us
	delay500us();
	DSPORT = 1;			//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
	i = 0;
	while(DSPORT)	//等待DS18B20拉低总线
	{
		delay80us();
		i++;
		if(i>5)//等待>5MS
		{
			return 0;//初始化失败
		}	
	}
	DSPORT = 1;	
	return 1;//初始化成功
}

程序源码

下面我就将程序的源码展示给大家,以便大家阅读和解决问题;本程序分为两个模块,一个是DS18B20的读取模块,另一个是8位数码管的显示模块;

temp.c文件的程序

#include<temp.h>
#include <intrins.h>
/*******************************************************************************
* 函 数 名         : Delay1ms
* 函数功能		   : 延时函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Delay1ms(u16 y)
{
	u16 x;
	for( ; y>0; y--)
	{
		for(x=110; x>0; x--);
	}
}
void delay500us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=71;b>0;b--)
        for(a=2;a>0;a--);
}
void delay80us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=11;b>0;b--)
        for(a=2;a>0;a--);
}
void delay48us(void)   //误差 0us
{
    unsigned char a,b;
    for(b=9;b>0;b--)
        for(a=1;a>0;a--);
}
void delay6us(void)   //误差 0us
{
    unsigned char a;
    for(a=1;a>0;a--);
    _nop_();  
}
/*******************************************************************************
* 函 数 名         : Ds18b20Init
* 函数功能		   : 初始化
* 输    入         : 无
* 输    出         : 初始化成功返回1,失败返回0
*******************************************************************************/
u8 Ds18b20Init()
{
	u8 i=0;
	DSPORT = 1;	
	delay6us();
	DSPORT = 0;			 //将总线拉低480us~960us
	delay500us();
	DSPORT = 1;			//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低
	i = 0;
	while(DSPORT)	//等待DS18B20拉低总线
	{
		delay80us();
		i++;
		if(i>5)//等待>5MS
		{
			return 0;//初始化失败
		}	
	}
	DSPORT = 1;	
	return 1;//初始化成功
}
/*******************************************************************************
* 函 数 名         : Ds18b20WriteByte
* 函数功能		   : 向18B20写入一个字节
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Ds18b20WriteByte(u8 dat)
{
	u16 i, j;
	for(j=0; j<8; j++)
	{
		DSPORT = 0;	     	  //每写入一位数据之前先把总线拉低1us
		i++;                 //表示延迟1us
		DSPORT = dat & 0x01;  //然后写入一个数据,从最低位开始
		delay80us();
		DSPORT = 1;	//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值
		dat >>= 1;
	}
}
/*******************************************************************************
* 函 数 名         : Ds18b20ReadByte
* 函数功能		   : 读取一个字节
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
u8 Ds18b20ReadByte()
{
	u8 byte, bi;
	u16 i, j;	
	for(j=8; j>0; j--)
	{
		DSPORT = 0;//先将总线拉低1us
		i++;
		DSPORT = 1;//然后释放总线
		delay6us();
		bi = DSPORT;	 //读取数据,从最低位开始读取
		/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/
		byte = (byte >> 1) | (bi << 7);						  
		delay48us();
		DSPORT = 1;
	}				
	return byte;
}
/*******************************************************************************
* 函 数 名         : Ds18b20ChangTemp
* 函数功能		   : 让18b20开始转换温度
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void  Ds18b20ChangTemp()
{
	Ds18b20Init();
	Delay1ms(1);
	Ds18b20WriteByte(0xcc);		//跳过ROM操作命令		 
	Ds18b20WriteByte(0x44);	    //温度转换命令 
}
/*******************************************************************************
 1. 函 数 名         : Ds18b20ReadTempCom
 2. 函数功能		   : 发送读取温度命令
 3. 输    入         : 无
 4. 输    出         : 无
*******************************************************************************/
void  Ds18b20ReadTempCom()
{	

	Ds18b20Init();
	Delay1ms(1);
	Ds18b20WriteByte(0xcc);	 //跳过ROM操作命令
	Ds18b20WriteByte(0xbe);	 //发送读取温度命令
}
/*******************************************************************************
 5. 函 数 名         : Ds18b20ReadTemp
 6. 函数功能		   : 读取温度
 7. 输    入         : 无
 8. 输    出         : 无
*******************************************************************************/
int Ds18b20ReadTemp()
{
	int temp = 0;
	u8 tmh, tml;
	Ds18b20ChangTemp();			 	//先写入转换命令
	Ds18b20ReadTempCom();			//然后等待转换完后发送读取温度命令
	tml = Ds18b20ReadByte();		//读取温度值共16位,先读低字节
	tmh = Ds18b20ReadByte();		//再读高字节
	temp = tmh;
	temp <<= 8;
	temp |= tml;
	return temp;
}

temp.h文件的数据

#include"reg51.h"

#define u16 unsigned int
#define u8 unsigned char	
	
sbit DSPORT=P3^7;

void Delay1ms(u16 y);
void delay500us(void);
void delay80us(void);
void delay48us(void);
void delay6us(void);

u8 Ds18b20Init();
void Ds18b20WriteByte(u8 dat);
u8 Ds18b20ReadByte();
void  Ds18b20ChangTemp();
void  Ds18b20ReadTempCom();
int Ds18b20ReadTemp();

main.c文件的数据

/****************************************
*本程序是由8位数码管,读取DS18B20温度采集的程序
*
*本程序采用keil5编写,采用proteus8.9进行仿真
*
*此温度显示范围-50~+120,精度达到了0.05
*
*程序编写人 “莫拉”
*******************************************/
#include<reg51.h>
#include<temp.h>

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

u8 displaydata[8];

u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,
					0x6d,0x7d,0x07,0x7f,0x6f};
/****************************************
*函数名:delay
*函数功能:延时函数
*输入:当输入1时,大约延迟1us
*输出:无
*******************************************/										
void delay(u16 i)
{
 while(i--); 
}											
/****************************************
*函数名  :datapros
*函数功能:显示真实温度数据
*输入:DS18B20反馈的数据
*输出:无
*******************************************/
void datapros(int temp)
{
	float tp;
	if(temp<0){
		displaydata[0]=0x40;
		temp=temp-1;		
		temp=~temp;
		tp=temp;
		temp=tp*0.0625*100+0.5;
	}
	else
	{
		displaydata[0]=0x00;	
		tp=temp;
		temp=tp*0.0625*100+0.5;
	}
	displaydata[1] = smgduan[temp/10000];
	displaydata[2] = smgduan[temp % 10000 / 1000];
	displaydata[3] = smgduan[temp % 1000 / 100] | 0x80;
	displaydata[4] = smgduan[temp % 100 / 10];
	displaydata[5] = smgduan[temp % 10];
}
/****************************************
*函数名  :display
*函数功能:数码管显示
*输入:无
*输出:无
*******************************************/
void display( )
{
	u8 i;
	for(i=0;i<6;i++)
	{
		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; 
			case(3):LSA=1;LSB=1;LSC=0;break; 
			case(4):LSA=0;LSB=0;LSC=1;break; 
			case(5):LSA=1;LSB=0;LSC=1;break; 
			case(6):LSA=0;LSB=1;LSC=1;break; 
			case(7):LSA=1;LSB=1;LSC=1;break;   //显示7位
		}
		P0=displaydata[i];
		delay(100);
	}
}

void main()
{
	while(1)
	{
		datapros(Ds18b20ReadTemp());
		display();
		Delay1ms(10);
	}
}

下面是proteus的仿真图

DS18B20数码管显示仿真图
以上就是DS18B20的全部程序,希望在阅读完毕后,觉得有用的小伙伴给我点个赞,支持一下!!!
您的支持将会是我创作的动力!!!

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值