DS18B20的传输距离.是否有超过12M的?我用的线是3股平行的细导线。M16.11.0592MHz。请
以下程序为DS18B20 M16 11.0592MHz 情况下5M以内通信正常的程序,我按照1,2,3,5,10M测量的,目的是想测量一下它的通信距离。这个程序是我调试的比较好的程序了,反应也非常灵敏。
现在我在调试10M,实际是11.8M,近12M的距离,莫非是它通信不到了?
一直显示95,我想应该是没有转换完毕吧,但是无论我把转换时间改为多少【从200ms到1250ms】返回的数据都是95,是否有网友通信的距离超过12M?我用的线是3股平行的细导线。
//-----------------延时程序------------------
void delay_us(unsigned int n) //N us延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
asm("nop");
}
//----------------DS18B20温度读取程序-----------------
//OneWire.c文件,用于操作DS18B20/DS2401等单总线器件
//注意实际硬件工作的频率
void OneWire_Init(void) //复位,不检测从机设备是否存在(只要没有虚焊就肯定存在的)
{
Set_Dir_OneWire;
Set_OneWire;
CLR_OneWire;
delay_us(960); //480~960us
Set_OneWire;
CLR_Dir_OneWire;
delay_us(60); //15~60us
while(Check_OneWire);
Set_Dir_OneWire;
Set_OneWire;
delay_us(240); //60~240us
}
void Write_OneWire(unsigned char Data) //向单总线的从机写入数据(先写低位再写高位,与SPI相反)
{
unsigned char i;
for(i=0;i<8;i++)
{
CLR_OneWire;
if(Data&(1<<i))Set_OneWire;//写数据了,先写低位的!
else CLR_OneWire;
delay_us(60); //15~60us
Set_OneWire;
}
Set_OneWire;
}
unsigned char Read_OneWire(void)
{
unsigned char data_L,n;
unsigned char temp_OneWire_Data=0;
for(n=0;n<8;n++)
{
CLR_OneWire;
Set_OneWire;
CLR_Dir_OneWire;
data_L=(Check_OneWire); //读数据,从低位开始
if(data_L)temp_OneWire_Data|=(1<<n);
else temp_OneWire_Data&=~(1<<n);
delay_us(120); //60~120us
Set_Dir_OneWire;
}
return temp_OneWire_Data;
}
void read_temperature(void) //读取温度值
{
unsigned char OneWire_DataL;
unsigned char OneWire_DataH;
unsigned char _T=1; //正负温度标志:<16为正 >15为负
switch(process_read_t)
{
case 0: OneWire_Init(); //复位DS18B20
Write_OneWire(0xcc); //跳过ID码匹配,适用于一个DS18B20
Write_OneWire(0x44); //启动温度转换
sign_read_t=1;
process_read_t=1;
break;
case 1: if(counter_read_t==counter_500ms)
{
OneWire_Init();
Write_OneWire(0xcc); //跳过ID码匹配,适用于一个DS18B20
Write_OneWire(0xbe); //通知DS18B20,准备读数据
OneWire_DataL=Read_OneWire(); //读取第一个数据(温度低字节)
OneWire_DataH=Read_OneWire(); //读取第二个数据(温度高字节)
if(OneWire_DataH<16)_T=1;
Data_T=OneWire_DataH*256+OneWire_DataL;//合并后得到原始温度数据
if(!_T) Data_T=(~Data_T+1)/16;
else Data_T/=16; //计算实际温度 -55~+125 器件以0.0625摄氏度递增
//如果温度为正 则T的最高位的4位都为0 否则为1; 负温度的计算:原始数据取反 加1 再乘以0.0625;正温度的计算:原始数据乘以0.0625
if(Data_T==85)Data_T=last_t; //稳定温度,不让通信中的错误数据掺杂进来干扰正常温度
if(last_t!=Data_T)sign_changet=1;//温度发生变化,串口重新上传一次数据,使得上位机的数据实时更新
if(_T) //显示温度函数,温度精度能够达到0.0625摄氏度
{
Data_T=Data_T%100;
data_T_bai=Data_T/100;
data_T_shi=Data_T/10;
data_T_ge=Data_T%10;
}
process_read_t=0;
sign_read_t=0;
last_t=(unsigned char)Data_T;
}
break;
default: break;
}
}
请各位朋友指点。 200米也可以 那在请问如何实现的?
可否介绍一下您的DS18B20通信时序上的各个时间是采用的什么值,代表多少时间。谢谢。 采用标准时序就可以,关键是加强驱动能力,去maxim网站上找找 我将上拉电阻减到3K,还是不行。我去找个三芯的屏蔽线去 应该是没有强上拉。数据表上要求用mos的。 哎,测试完成,最多走6M,6M和10M甚至几十M的现象是一样的,显示都是95.呵呵,唉。。。谁有高见,可以提高他的传输距离,请在后面跟帖,小弟,先谢过。
注:1.我在后级DS18B20的VCC和GND已经加了104电容;
2.我也曾试图减小过上拉电阻,目的增加点驱动电流,可是白费力气。
3.一根20M的好线【包开皮,里面是3芯的平行线,每芯直径1mm】,被我割成1.2.3.5.9M的散线,测试的,最后得出的结论是只能传6M,再远就全是95,显示不变了。 加三极管驱动,maxim有介绍 您说的这个吧:
http://www.maxim-ic.com.cn/appnotes.cfm/appnote_number/4255
这个和手册上说的都是采用寄生电源“走远距离”时候的方法。
不过还是要谢谢您的跟帖回复! 我以前做的10米可以啊,4.7K上拉 那在请问楼上如何实现的?
可否介绍一下您的DS18B20通信时序上的各个时间是采用的什么值,代表多少时间。谢谢。 我每个延时都是拿示波器精确延时的,然后调用,接了10米长屏蔽线,音响用的那种,那时不是因为怕干扰而用的,而是手头只有那种线,而且线是捆成一卷,没有拉直,程序我改天要找一下才行 几年前做过这个试验,100m或300m,记不太清了,用四芯双绞线,电源和地一对,信号线和地一对,程序我不懂,但应该是按数据手册做的,至少100m没问题 行还是不行,请尽量不要看软件测到的结果。
要用示波器直接测试CPU和1820端的信号波形,如果波形的上升沿变慢,就有问题了。
也可以测试上拉电阻和分布电容的大小,再计算RC的波形。
我以前做过温度和湿度的,湿度是频率信号,由于导线互相靠的很近,有干扰,也可以传20米以上。 不光上拉要强,下拉也要强才能做很远。
ULN2803+MOSFET做到500米以上稳定通信,最长好像接到了700米都可以,再远就没有试过了。 http://www.maxim-ic.com.cn/pdfserv/cn/an/AN857C.pdf
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_397913.JPG
(原文件名:18b20.JPG) 我用30M线,寄生电源,上拉电阻2K,可以工作,但是奇怪的是用AT89C2051可以,STC1052不行,只能到3M左右。都是SMT的。
注意就是普通的护套线。不要上拉也能,不过偶尔会有一次错误的。时序也不用那么精确,我都试过了,虽然用2051修改程序很麻烦。 http://www.maxim-ic.com.cn/appnotes.cfm/an_pk/244
我说的是这个,绝对可以 好,我现在就尝试一下! 未果!
网友:wswh2o 水之影 在17楼的那个网页我仔细的看了,但是还是不理解怎么在DS18B20上如何连接,所以尚未采用此电路。
我尝试网友 pcs3
“不光上拉要强,下拉也要强才能做很远。
ULN2803+MOSFET做到500米以上稳定通信,最长好像接到了700米都可以,再远就没有试过了。 ”
我这没有MOS,用的BJT做的下拉,尝试了几种方式,均不好使,还是只能传6M,再远返回的全是95.
还有哪位网友有成熟的见解。
再次感谢各位仁兄的建议。请继续跟帖发表高见。 1-Wire网络的可靠性在很大程度上取决于主机与1-Wire从机器件之间所采用的通信驱动电路的性能。本文介绍了一种1-Wire主机端接口,采用精细的阻抗匹配和"智能" (软件控制)强上拉等方法,保证网络在轻载到重载范围内均能可靠工作,且通信距离可达500m。关于创建可靠的1-Wire网络指南,请参见应用笔记148。
保证网络在轻载到重载范围内均能可靠工作,且通信距离可达500m 用快点的三极管也行,8050 8550之类 应用笔记148,我去下载,8050我也有的,非常感谢您的快速回复,我马上试验。 啊,这段话我说怎么这么熟呢,原来是那个网页的第一段。
应用笔记148,我也已经下载过了。
您的意思是不是按照
http://www.maxim-ic.com.cn/images/appnotes/244/2082Fig01.gif
这个电路图的右上角蓝色这一部分搭接,我先按照这种理解去做一个测试。
此贴我及时刷新。 哎,不好意思,老总请客吃饭,难得呀,先去吃,大约1点左右,我在继续测试。非常感谢wswh2o 水之影 一直跟帖回复。
如果我测得更远距离,一定附上全部资料,及说明方法,供“像我一样的新手”参考,以答谢各位网友的帮助。 应该是我理解有误,我没有按照http://www.maxim-ic.com.cn/images/appnotes/244/2082Fig01.gif 这个图调试出来。
想试验一下15楼的电路,这个电路是从1-WIRE可靠设计指南.PDF中截取出来的。下面这段话是书中原话:
带有摆率控制的 FET 驱动器 和100Ω上拉电阻的微控制器接口能支持中型网络 使用这种接口能可靠支持的网络半径和总长度均可达到200m 参见附录 B也就是15楼的图。
可是请各位大侠给小弟扫一下盲,什么是“摆率控制 ”,我又如何实现它呢?
途中输入输出是2个引脚,莫非还要我分开来接,那岂不是2-wire?
关键是我就剩下一个引脚了,无法这样测试。 mark 我实际应用150米没问题~~~~ 结果呢 结果是没有搞那么远.
还是请搞过20多米,150米,200米,等等更远的高手出来,说清楚那些"传说"的东西是怎么办到的吧.
愿意细说的,能够说明白的,能让我这种菜鸟都看懂的,请不吝赐教.先表示感谢.
后记:楼主位的程序,仅适合玩玩. 可以肯定的告诉你,你的时序有问题(我看你延迟的是 uS),也可能是你的18B20有问题 持续关注中 DS18B20的数据书是20米,我实际做到了75米通讯的距离,不需要增加任何驱动,能正常工作。可以看看http://shop37274795.taobao.com,这有技术支持。 我150米也正常, 记住把上拉接在18B20处 我用CVAVR生成的函数可以做到200m,自己写的居然只能做到5m以内,悲剧
ps,不加任何驱动电路 呵呵.具体能够达到多少米.光说无凭.
等我有时间.我再写一个相对[再]严格时序的程序来.
到时候附在后面.喜欢讨论的,不防也拿出你们的严格时序的程序来.否则.不光我不服.这么多的看客,也不服.您说是不是. 我自已做的线具体多长我没有量过,但是肯定超过6米了,估计将近十米,通信地很好。我做了两个,一个短线的,就几十公分长,另外一个很长,估计有8~10米,没有碰到你的问题。你是不是线的质量不行?我用的线材是相当好的线材,航空产品。 MARK 关注大家的方案 单总线的DS18B20确实方便了我们开发产品的应用,但是牵扯到最大传输距离的问题,不知道可不可靠,还请各位赐教! 同样关注 18B20的质量应该也有问题,买来的比较贵的那种,两线30米没有问题。便宜的没有试过,但是买了一个封装好的用那种不锈钢外壳,也不贵,结果是两线就算是只有1米,也不能工作,上拉等等都调过,时序也调了,最后还是恢复原来的时序,用3线,就没有问题了。 mark 18b20 主楼不是说了上传代码吗,主楼怎么还不上传代码啊?好几个月都过去了 【43楼】 xiaoxuanfeng
不好意思,没时间. 你换换好的线试试,注意接地的位置,还有电源的质量也要考虑。 mark 莫非这么好的帖子要沉了,太可惜了,我做过最远的也只有10米左右,上拉4.7K,普通的双绞线,如果有人做过更远的,可以出来秀下,毕竟技术无国界嘛! mark 收藏。 复位部分,最后检测到18b20的低电平后,再拉高,总的时间要求不小于480us,你的时间不够吧?
http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_665926DF4N80.JPG
(原文件名:复位.JPG) 读代码中
for(n=0;n<8;n++)
{
CLR_OneWire;
此处延时10us
Set_OneWire;
此处延时10us
CLR_Dir_OneWire;
data_L=(Check_OneWire); //读数据,从低位开始
if(data_L)temp_OneWire_Data|=(1<<n);
else temp_OneWire_Data&=~(1<<n);
delay_us(120); //60~80us此处为60多
Set_Dir_OneWire;
} 时序特别严格就可以传的很远吗?不理解.. 关注 我最近测试,时序很严格也不能传很远,偶尔也出错,一上电的几次读取都是85度,如何让第1次就能读取正确的温度呢?并且现在超过4m会出错。
楼主的的代码更不能读取到4m。
我把自己程序上传,大家研究:
M128+11.0592M
////////////////////////////////////////////////////////////////////
#define B18B201_DIRDDRC
#define B18B201_PORTPORTC
#define B18B201_PIN PINC
#define B18B201_BIT1
#define B18B201_INI{\
B18B201_DIR |= 1<<B18B201_BIT;\
\
B18B201_PORT |= 1<<B18B201_BIT;\
}
#define DQ1_OUT_1 B18B201_PORT |= (1<<B18B201_BIT)
#define DQ1_OUT_0 B18B201_PORT &=(~ (1<<B18B201_BIT))
#define DQ1_DIR_IN B18B201_DIR &=(~(1<<B18B201_BIT))
#define DQ1_DIR_OUT B18B201_DIR |= (1<<B18B201_BIT)
#define DQ1_IN_PIN ((B18B201_PIN>>B18B201_BIT)&(0x01))
/////////////////////////////////////////////////////
/*************************************************************************************/
//6us i=1
void delay_tmp1(unsigned int i)//延时函数
{
unsigned int k1=0,k2=0;
for(k2=0;k2<i;k2++);
//for(k1=0;k1<6;k1++);
}
/***************************************************************************************/
//18b20初始化函数
void Init_DS18B201(void)
{
unsigned char x=0;
wdc1_eat_all();
DQ1_DIR_OUT ;
DQ1_OUT_1; //DQ复位
delay_tmp1(12);
DQ1_OUT_0; //单片机将DQ拉低
delay_tmp1(900); //11.0592M 精确延时 大于480us 500us
delay_tmp1(105);//61.1us//11.0592M
DQ1_OUT_1; //拉高总线
DQ1_DIR_IN;
delay_tmp1(105);//11.0592M61.1us
delay_tmp1(2);//5.2us//11.0592M
delay_tmp1(2);//5.2us//11.0592M
//x=DQ1_IN_PIN; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败,有效信号60--240
while(DQ1_IN_PIN) ;//检测是否数据线被拉低,拉低表示18b20存在
DQ1_DIR_OUT;//增加设置方向输出
DQ1_OUT_1; //输出1,拉高总线
wdc1_eat_all();
delay_tmp1(545);//11.0592M300us
delay_tmp1(400);//221us//11.0592M
wdc1_eat_all();
}
//读1bit//返回0或1
unsigned char ReadOneBit1(void)
{
unsigned char i=0;
unsigned char dat = 0;
unsigned char k1=0;
wdc1_eat_all();
DQ1_DIR_OUT ;
DQ1_OUT_0; // 给脉冲信号0
delay_tmp1(2);//11.0592 5.2us
delay_tmp1(2);//11.0592 5.2us
DQ1_OUT_1; // 给脉冲信号1,准备读
delay_tmp1(2);//11.0592 5.2us
delay_tmp1(2);//11.0592 5.2us
DQ1_DIR_IN ;
if(DQ1_IN_PIN)
dat|=0x01;
DQ1_DIR_OUT ;
DQ1_OUT_1; // 给脉冲信号1//
delay_tmp1(105);//11.0592M61.1us
return(dat);
}
//读一个字节
unsigned char ReadOneChar1(void)
{
unsigned char i=0;
unsigned char dat = 0;
unsigned char k1=0;
wdc1_eat_all();
for (i=8;i>0;i--)
{
DQ1_DIR_OUT ;
DQ1_OUT_0; // 给脉冲信号
delay_tmp1(2);//11.0592 5.2us
delay_tmp1(2);//11.0592 5.2us
dat>>=1;
DQ1_OUT_1; // 给脉冲信号
delay_tmp1(2);//11.0592 5.2us
delay_tmp1(2);//11.0592 5.2us
DQ1_DIR_IN ;
if(DQ1_IN_PIN)
dat|=0x80;
DQ1_DIR_OUT ;
DQ1_OUT_1; // 给脉冲信号1
delay_tmp1(105);//11.0592M61.1us
}
return(dat);
}
//写一个字节
void WriteOneChar1(unsigned char dat)
{
unsigned char i=0;
DQ1_DIR_OUT ;
for (i=8; i>0; i--)
{
DQ1_OUT_0;
delay_tmp1(2);//11.0592 5.2us
if(dat&0x01==1) DQ1_OUT_1;
else
DQ1_OUT_0;
delay_tmp1(105);//11.0592M61.1us
DQ1_OUT_1;
delay_tmp1(2);//11.0592 5.2us
dat>>=1;
}
DQ1_OUT_1;//输出为高,表示数据完成
delay_tmp1(105);//11.0592M61.1us
wdc1_eat_all();
}
//读取温度
int ReadTemperature1(void)
{
unsigned char a=0;
unsigned char b=0;
int t=0;
unsigned char tmperature1;
unsigned char k1=0;
unsigned char c=0;
Init_DS18B201();
WriteOneChar1(0xCC); // 跳过读序号列号的操作
WriteOneChar1(0x44); // 启动温度转换
while(ReadOneBit1()==0) ;
Init_DS18B201();
WriteOneChar1(0xCC); //跳过读序号列号的操作
WriteOneChar1(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
for(k1=0;k1<9;k1++)
tmperature1=ReadOneChar1();
a=tmperature1;
b=tmperature1;
c=(tmperature1>>4)&0x01;
b=(b&0x07)<<4;
b+=(a&0xf0)>>4;
t=b;
a=(a&0x0f)*10/16;//小数*10
b201_tmp1=t*10+a; //实际温度*10
if(c==1)t=(-1)*t;
return(t);
} (1)根据实际测试,读一个字节时,置0后等待5.2us,置1后等待5.2us然后读取,而不是我上面说的等待10.4us
//读一个字节
unsigned char ReadOneChar1(void)
{
unsigned char i=0;
unsigned char dat = 0;
unsigned char k1=0;
wdc1_eat_all();
for (i=8;i>0;i--)
{
DQ1_DIR_OUT ;
DQ1_OUT_0; // 给脉冲信号
delay_tmp1(2);//11.0592 5.2us
dat>>=1;
DQ1_OUT_1; // 给脉冲信号
delay_tmp1(2);//11.0592 5.2us
DQ1_DIR_IN ;
if(DQ1_IN_PIN)
dat|=0x80;
DQ1_DIR_OUT ;
DQ1_OUT_1; // 给脉冲信号1
delay_tmp1(105);//11.0592M61.1us
}
return(dat);
}
(2)最关键的是启动转换后,等待900ms以上再去读结果,可以延时等待或者用中断,类似楼主的处理方法,这样即使第1次转换结果也是正确的。
我上面检测转换结束的方法是看是否数据线读到的为1,如果为1,转换理论上是结束的,这个手册上有讲,但是我实际对此处进行计时,实际这段时间最大才400ms就变成1了,但是12位精度的转换时间要750ms。经过测试说明楼上我用的测试是否读到为1的方法不可靠。还是用延时900ms读吧。
现在距离5m应该没问题,有时间找根12m以上的线测试一下看能不能读到。 mark 我记得每次在18b20复位的时候都有一个85出现,不知道怎么弄掉这个复位值
我用3*0.5的屏敝线做的2卷线(95m一卷)没问题 学习一下.... 记号,好好参考 复杂... 最近老板让我好好研究研究这个距离问题看完大家的,感觉已经懵圈了{:funk:} 我听别人说300以上 chaojikoushuige 发表于 2015-2-7 14:56
我听别人说300以上
呵呵,两线制,接多个1Wire,已经做到800米了,时序和电路都要做专门调整
页:
[1]