单片机常用芯片系列(二)——DS18B20详解(2)——寄生电源供电(包括调试中遇到的问题,编程思路)

我在蓝桥杯的板子上看到,他的是寄生电源供电,也就是没有外接电源,靠总线高电平供电,低电平电容放电。编程之处略有不同。

网上很多资料,我还是只说最难懂的点

一、注意事项

1.在这里插入图片描述温度转换命令【44h】后面要加延时,而且总线要置1,提供上拉电流。

send(0xcc);
send(0x44);
DAT = 1;
delay1s();

2.在这里插入图片描述在这里插入图片描述
为了提高可移植性,可以这样写

uchar way;
send(0xcc);
send(0xb4);
way = read();//读取温度状态
DAT = 1; //释放总线


if(way == 1)
{
	#define waibu
}

#ifdef waibu
......
#else
......
#endif
......

3.在这里插入图片描述注意:
每次命令都得初始化

常用命令
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
初始化时序:
总线拉低500微秒,再释放总线(拉高)。然后进入接收模式。如果设备正常会发送应答信号,也就是低电平把总线拉低200微秒。

uchar i = 0;
DAT = 1;
DAT = 0;
delay600us();
DAT = 1;
dealay100us();
while(DAT == 1)
{
	if(i == 5)
	{
		return 0;
	}
	i++
}
return 1;

写时序:
1.总线置一
2.总线置零
3.等5微秒
4.总线保持60微妙(写0)
总线拉高,保持60微秒(写1)
5.总线置1保持1微秒以上

DAT = 1;
DAT = 0;
delay5us();
DAT = 0;
//DAT = 1;  写1
delay60us();
DAT = 1;

在这里插入图片描述
读时序:
1.总线置一
2.总线置零
3.等4微秒
4.总线置一(释放总线)
5.等

读一个位:

DAT = 1;
DAT = 0;
delay();
DAT = 1;
delay();

uchar dat;
dat = DAT;

DAT = 1;

读一个字节:

uchar readByte()
{
	uchar i,dat=0;
	uchar da=0;
	
	for(i=0;i<8;i++)
	{
		DATA=0;
		_nop_();
		DATA=1;
		delay4us();
		da=DATA;
		da<<=7;
		dat=(dat>>1)|da;
		delay60us();
	}
	return dat;
}

温度换算是负温度减一取反乘精度
正温度直接乘精度

注意:在上电复位的时候,温度寄存器中的值为0x0550,即+85摄氏度。所以在应用开发中,有些朋友一直读到的数据都是85.5摄氏度,就说明DS18B20根本没有进行温度转换,你读到的是上电复位的初始值。

——————————————分割线————————————————

干货来了!!!!!!!!!!!!!!!!!!!!正式开始编程!

首先,先测试一下能不能用
那么就是初始化一下看看返回值是不是0

经过两天的测试,检测不到这个玩意。。
全文完

大家自己做,应该是可以的。代码没问题,

后来检测到了,大家继续往后看

#include "ds18b20.h"

////单总线延时函数
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

void Delay_OneWire1(unsigned int t)  
{
	while(t--);
}

void Delay_us(void)
{
	unsigned char i;

	i = 30;
	while (--i);
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);

}

//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
//	unsigned char index = 0;
  	   	
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1; 
	   	Delay_us();

		if(DQ)  
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}


//DS18B20初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;

  	Delay_OneWire(80); // 延时大于480us
  	DQ = 1;
  	Delay_OneWire(5);  // 14
  	initflag = DQ;     // initflag等于1初始化失败
  	Delay_OneWire(50);
  
  	return initflag;
}

————————分割线————————————————

更新于2020.3.29

服了,又可以了。我脑子瓦特了

在这里插入图片描述
箭头这里是电阻上拉的意思。所以不能等时间太久,不然就等不到,所以才显示的检测不到硬件。
在这里插入图片描述这里原来是50,我改成5了,立马就检测到了
返回值是0

然后我们检测一下供电方式。这里也是一个大坑,无力吐槽蓝桥杯这个板子的奇葩设计。。

uchar rd_temperature(void)
{
	uchar dq;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xb4);
	Delay_OneWire(5); 
	dq = DQ;
	return dq;
}

在这里插入图片描述看起来是寄生电源供电,实际上是外部电源供电。。。
因为寄生电源供电的话,vdd和gnd都接地,这个不是
所以这段代码的返回值是1。。。
在这里插入图片描述我都是用串口检测的

下一步开始测温度

int rd_temperature(void)
{
	uchar LOW = 0,HIGH = 0;
	int temp = 0;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay1000ms() ;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LOW = Read_DS18B20();
	HIGH = Read_DS18B20();
	
	temp = (HIGH << 8) | (LOW);
	return temp;
}

主函数这里数据处理一下

	int GOODORNOT = 0;
	Init();
	uartInit();
	
	while(1)
	{	
		GOODORNOT = rd_temperature();
		GOODORNOT = GOODORNOT*0.0625+0.5;
		uartSendByte((uchar)(GOODORNOT/10)+'0');
		uartSendByte((uchar)(GOODORNOT%10)+'0');
		delay(50000);
	}

在这里插入图片描述成功

全文完

有问题的可以留言评论

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章