wisebaby 发表于 2008-9-1 14:42:36

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;
}
}

请各位朋友指点。

wswh2o 发表于 2008-9-1 14:55:10

200米也可以

wisebaby 发表于 2008-9-1 15:07:53

那在请问如何实现的?

可否介绍一下您的DS18B20通信时序上的各个时间是采用的什么值,代表多少时间。谢谢。

wswh2o 发表于 2008-9-1 15:45:07

采用标准时序就可以,关键是加强驱动能力,去maxim网站上找找

wisebaby 发表于 2008-9-1 16:11:29

我将上拉电阻减到3K,还是不行。我去找个三芯的屏蔽线去

kalo 发表于 2008-9-1 16:35:05

应该是没有强上拉。数据表上要求用mos的。

wisebaby 发表于 2008-9-1 17:19:29

哎,测试完成,最多走6M,6M和10M甚至几十M的现象是一样的,显示都是95.呵呵,唉。。。谁有高见,可以提高他的传输距离,请在后面跟帖,小弟,先谢过。

注:1.我在后级DS18B20的VCC和GND已经加了104电容;
    2.我也曾试图减小过上拉电阻,目的增加点驱动电流,可是白费力气。
    3.一根20M的好线【包开皮,里面是3芯的平行线,每芯直径1mm】,被我割成1.2.3.5.9M的散线,测试的,最后得出的结论是只能传6M,再远就全是95,显示不变了。

wswh2o 发表于 2008-9-1 17:55:09

加三极管驱动,maxim有介绍

wisebaby 发表于 2008-9-1 18:00:55

您说的这个吧:

http://www.maxim-ic.com.cn/appnotes.cfm/appnote_number/4255

这个和手册上说的都是采用寄生电源“走远距离”时候的方法。

不过还是要谢谢您的跟帖回复!

dongni 发表于 2008-9-1 18:18:43

我以前做的10米可以啊,4.7K上拉

wisebaby 发表于 2008-9-1 20:06:25

那在请问楼上如何实现的?

可否介绍一下您的DS18B20通信时序上的各个时间是采用的什么值,代表多少时间。谢谢。

dongni 发表于 2008-9-1 20:18:33

我每个延时都是拿示波器精确延时的,然后调用,接了10米长屏蔽线,音响用的那种,那时不是因为怕干扰而用的,而是手头只有那种线,而且线是捆成一卷,没有拉直,程序我改天要找一下才行

mldmldmld 发表于 2008-9-1 20:20:40

几年前做过这个试验,100m或300m,记不太清了,用四芯双绞线,电源和地一对,信号线和地一对,程序我不懂,但应该是按数据手册做的,至少100m没问题

gx_huang 发表于 2008-9-1 20:58:26

行还是不行,请尽量不要看软件测到的结果。
要用示波器直接测试CPU和1820端的信号波形,如果波形的上升沿变慢,就有问题了。
也可以测试上拉电阻和分布电容的大小,再计算RC的波形。

我以前做过温度和湿度的,湿度是频率信号,由于导线互相靠的很近,有干扰,也可以传20米以上。

pcs3 发表于 2008-9-1 22:30:54

不光上拉要强,下拉也要强才能做很远。
ULN2803+MOSFET做到500米以上稳定通信,最长好像接到了700米都可以,再远就没有试过了。

kalo 发表于 2008-9-2 07:48:02

http://www.maxim-ic.com.cn/pdfserv/cn/an/AN857C.pdf
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_397913.JPG
(原文件名:18b20.JPG)

xiaobendan 发表于 2008-9-2 08:12:47

我用30M线,寄生电源,上拉电阻2K,可以工作,但是奇怪的是用AT89C2051可以,STC1052不行,只能到3M左右。都是SMT的。
注意就是普通的护套线。不要上拉也能,不过偶尔会有一次错误的。时序也不用那么精确,我都试过了,虽然用2051修改程序很麻烦。

wswh2o 发表于 2008-9-2 08:48:12

http://www.maxim-ic.com.cn/appnotes.cfm/an_pk/244

我说的是这个,绝对可以

wisebaby 发表于 2008-9-2 09:48:31

好,我现在就尝试一下!

wisebaby 发表于 2008-9-2 11:22:30

未果!

网友:wswh2o 水之影 在17楼的那个网页我仔细的看了,但是还是不理解怎么在DS18B20上如何连接,所以尚未采用此电路。

我尝试网友 pcs3
“不光上拉要强,下拉也要强才能做很远。
ULN2803+MOSFET做到500米以上稳定通信,最长好像接到了700米都可以,再远就没有试过了。 ”

我这没有MOS,用的BJT做的下拉,尝试了几种方式,均不好使,还是只能传6M,再远返回的全是95.

还有哪位网友有成熟的见解。

再次感谢各位仁兄的建议。请继续跟帖发表高见。

wswh2o 发表于 2008-9-2 11:24:03

1-Wire网络的可靠性在很大程度上取决于主机与1-Wire从机器件之间所采用的通信驱动电路的性能。本文介绍了一种1-Wire主机端接口,采用精细的阻抗匹配和"智能" (软件控制)强上拉等方法,保证网络在轻载到重载范围内均能可靠工作,且通信距离可达500m。关于创建可靠的1-Wire网络指南,请参见应用笔记148。


保证网络在轻载到重载范围内均能可靠工作,且通信距离可达500m

wswh2o 发表于 2008-9-2 11:24:51

用快点的三极管也行,8050 8550之类

wisebaby 发表于 2008-9-2 11:29:18

应用笔记148,我去下载,8050我也有的,非常感谢您的快速回复,我马上试验。

wisebaby 发表于 2008-9-2 11:34:06

啊,这段话我说怎么这么熟呢,原来是那个网页的第一段。

应用笔记148,我也已经下载过了。

您的意思是不是按照

http://www.maxim-ic.com.cn/images/appnotes/244/2082Fig01.gif

这个电路图的右上角蓝色这一部分搭接,我先按照这种理解去做一个测试。

此贴我及时刷新。

wisebaby 发表于 2008-9-2 11:38:22

哎,不好意思,老总请客吃饭,难得呀,先去吃,大约1点左右,我在继续测试。非常感谢wswh2o 水之影 一直跟帖回复。

如果我测得更远距离,一定附上全部资料,及说明方法,供“像我一样的新手”参考,以答谢各位网友的帮助。

wisebaby 发表于 2008-9-2 13:07:46

应该是我理解有误,我没有按照http://www.maxim-ic.com.cn/images/appnotes/244/2082Fig01.gif 这个图调试出来。

想试验一下15楼的电路,这个电路是从1-WIRE可靠设计指南.PDF中截取出来的。下面这段话是书中原话:

带有摆率控制的 FET 驱动器 和100Ω上拉电阻的微控制器接口能支持中型网络 使用这种接口能可靠支持的网络半径和总长度均可达到200m 参见附录 B也就是15楼的图。

可是请各位大侠给小弟扫一下盲,什么是“摆率控制 ”,我又如何实现它呢?

途中输入输出是2个引脚,莫非还要我分开来接,那岂不是2-wire?

关键是我就剩下一个引脚了,无法这样测试。

dugutianma 发表于 2009-11-2 10:54:31

mark

st8051 发表于 2009-11-2 13:54:04

我实际应用150米没问题~~~~

dingwei 发表于 2009-11-3 19:37:02

结果呢

wisebaby 发表于 2009-11-11 10:44:31

结果是没有搞那么远.

还是请搞过20多米,150米,200米,等等更远的高手出来,说清楚那些"传说"的东西是怎么办到的吧.

愿意细说的,能够说明白的,能让我这种菜鸟都看懂的,请不吝赐教.先表示感谢.

后记:楼主位的程序,仅适合玩玩.

st8051 发表于 2009-11-12 00:08:13

可以肯定的告诉你,你的时序有问题(我看你延迟的是 uS),也可能是你的18B20有问题

bike 发表于 2009-11-12 17:29:04

持续关注中

cpu51 发表于 2009-11-12 20:49:01

DS18B20的数据书是20米,我实际做到了75米通讯的距离,不需要增加任何驱动,能正常工作。可以看看http://shop37274795.taobao.com,这有技术支持。

st8051 发表于 2009-11-12 21:51:19

我150米也正常, 记住把上拉接在18B20处

bike 发表于 2009-11-12 22:04:37

我用CVAVR生成的函数可以做到200m,自己写的居然只能做到5m以内,悲剧
ps,不加任何驱动电路

wisebaby 发表于 2009-11-17 16:24:24

呵呵.具体能够达到多少米.光说无凭.
等我有时间.我再写一个相对[再]严格时序的程序来.
到时候附在后面.喜欢讨论的,不防也拿出你们的严格时序的程序来.否则.不光我不服.这么多的看客,也不服.您说是不是.

liusoldier 发表于 2009-11-17 20:26:53

我自已做的线具体多长我没有量过,但是肯定超过6米了,估计将近十米,通信地很好。我做了两个,一个短线的,就几十公分长,另外一个很长,估计有8~10米,没有碰到你的问题。你是不是线的质量不行?我用的线材是相当好的线材,航空产品。

mutech 发表于 2010-4-2 11:37:19

MARK

nvchouaa 发表于 2010-4-19 15:37:07

关注大家的方案

tsw1987 发表于 2010-9-15 14:08:20

单总线的DS18B20确实方便了我们开发产品的应用,但是牵扯到最大传输距离的问题,不知道可不可靠,还请各位赐教!

pxlpxlpxl 发表于 2010-9-16 01:00:07

同样关注

xiaobendan 发表于 2010-9-18 20:17:54

18B20的质量应该也有问题,买来的比较贵的那种,两线30米没有问题。便宜的没有试过,但是买了一个封装好的用那种不锈钢外壳,也不贵,结果是两线就算是只有1米,也不能工作,上拉等等都调过,时序也调了,最后还是恢复原来的时序,用3线,就没有问题了。

rodger 发表于 2010-9-19 03:09:36

mark 18b20

xiaoxuanfeng 发表于 2010-10-22 17:06:35

主楼不是说了上传代码吗,主楼怎么还不上传代码啊?好几个月都过去了

wisebaby 发表于 2010-10-25 19:08:34

【43楼】 xiaoxuanfeng
不好意思,没时间.

zlj2008 发表于 2010-10-25 19:39:45

你换换好的线试试,注意接地的位置,还有电源的质量也要考虑。

taking 发表于 2010-10-26 17:33:44

mark

xiaolonghejing 发表于 2010-11-30 14:35:08

莫非这么好的帖子要沉了,太可惜了,我做过最远的也只有10米左右,上拉4.7K,普通的双绞线,如果有人做过更远的,可以出来秀下,毕竟技术无国界嘛!

Garbage614 发表于 2011-6-28 11:24:43

mark

xinjie1023 发表于 2011-8-9 18:29:16

收藏。

xinjie1023 发表于 2011-8-9 19:32:48

复位部分,最后检测到18b20的低电平后,再拉高,总的时间要求不小于480us,你的时间不够吧?
http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_665926DF4N80.JPG
(原文件名:复位.JPG)

xinjie1023 发表于 2011-8-10 19:09:44

读代码中
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;
}

lyi619 发表于 2011-8-11 14:03:56

时序特别严格就可以传的很远吗?不理解..

zjy9430 发表于 2011-8-11 14:51:30

关注

xinjie1023 发表于 2011-8-11 20:12:28

我最近测试,时序很严格也不能传很远,偶尔也出错,一上电的几次读取都是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);

}

xinjie1023 发表于 2011-8-12 20:56:55

(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以上的线测试一下看能不能读到。

zprs 发表于 2011-8-12 22:20:21

mark

yangzichen 发表于 2012-11-30 11:20:20

我记得每次在18b20复位的时候都有一个85出现,不知道怎么弄掉这个复位值

jsntzxh 发表于 2012-11-30 14:48:07

我用3*0.5的屏敝线做的2卷线(95m一卷)没问题

jz701209李 发表于 2013-4-9 14:06:16

学习一下....

林州 发表于 2013-12-23 22:14:00

记号,好好参考

mk_avatar 发表于 2014-8-23 16:52:30

复杂... 最近老板让我好好研究研究这个距离问题看完大家的,感觉已经懵圈了{:funk:}

chaojikoushuige 发表于 2015-2-7 14:56:02

我听别人说300以上

wincom 发表于 2020-11-16 20:25:25

chaojikoushuige 发表于 2015-2-7 14:56
我听别人说300以上

呵呵,两线制,接多个1Wire,已经做到800米了,时序和电路都要做专门调整
页: [1]
查看完整版本: DS18B20的传输距离.是否有超过12M的?我用的线是3股平行的细导线。M16.11.0592MHz。请