打印

DS18B20

[复制链接]
3417|23
手机看帖
扫描二维码
随时随地手机跟帖
沙发
yunan0808| | 2013-7-27 17:00 | 只看该作者
你有现成的代码吗?

使用特权

评论回复
板凳
whmryq| | 2013-7-27 17:06 | 只看该作者
给你一个现成的代码,自己试着调一下,我原来试过的,可以用,稍微改一下串口

#include<reg52.h>
sbit ds18b20_pin=P1^7;                        //单总线引脚

void ds18b20_init();                        //ds18b20初始化
bit  ds18b20_reset();                        //ds18b20复位
void ds18b20_write_dat(unsigned char dat);//些数据到ds18b20
unsigned char ds18b20_read_dat();//读数据

/****************************************
*DS18B20 初始化
*函数名称:ds18b20_init()
*说明:本初始化程序可以不要,因为18B20在出厂时就被配置为12位精度了
*****************************************/
void ds18b20_init()
{
        ds18b20_reset();
        ds18b20_write_dat(0xcc);                //跳过ROM       
        ds18b20_write_dat(0x4e);                //写暂存器
        ds18b20_write_dat(0x20);                //往暂存器的第三字节中写上限值
        ds18b20_write_dat(0x00);                //往暂存器的第四字节中写下限值
        ds18b20_write_dat(0x7f);                //将配置寄存器配置为12位精度
        ds18b20_reset();
}


/*********************************************
*DS18B20复位及存在检测(通过存在脉冲可以判断DS18B20是否损坏
*函数名称:ds18b20_reset()
*说明:函数返回一个位标量(0或1)flag=0存在,反之flag=1不存在
**********************************************/
bit ds18b20_reset()
{
        unsigned char i;
        bit flag;

        ds18b20_pin=0;                                        //拉低总线
        for(i=240;i>0;i--);                                 //延时480微秒,产生复位脉冲
        ds18b20_pin=1;                                        //释放总线
        for(i=40;i>0;i--);                                //延时80微秒对总线采样
        flag=ds18b20_pin;                                //对数据脚采样
        for(i=200;i>0;i--);                                //延时400us等待总线恢复
        return (flag);

}
/********************************************
*写数据到DS18B20
*函数名称:ds18b20_write_dat()
*********************************************/
void ds18b20_write_dat(unsigned char dat)
{
        unsigned char i,j;
        for(i=8;i>0;i--)
        {
                 ds18b20_pin=0;                                //拉低总线,产生写信号
                for(j=2;j>0;j--);                        //延时4us
                ds18b20_pin=dat&0x01;                //发送1位
                for(j=30;j>0;j--);                        //延时60us,写时序至少要60us
                ds18b20_pin=1;                                //释放总线,等待总线恢复
                dat>>=1;                                        //准备下一位数据的传送
        }
}
/**********************************************
*从DS18B20中读数据
*函数名称:ds18b20_read_dat()
*
**********************************************/

unsigned char ds18b20_read_dat()
{
        unsigned char i,j,tempdat;
        for(i=8;i>0;i--)
        {
         tempdat>>=1;
         ds18b20_pin=0;                                        //拉低总线,产生读信号
         for(j=2;j>0;j--);                                //延时4us
         ds18b20_pin=1;                                        //释放总线,准备读数据
         for(j=4;j>0;j--);                                //延时8us读数据
         if(ds18b20_pin==1)
                 {       
                        tempdat|=0x80;
                }
          for(j=30;j>0;j--);                        //延时60us
          ds18b20_pin=1;                                //拉高总线,准备下一位数据的读取
        }
        return(tempdat);                                //返回读到的数据
}

使用特权

评论回复
地板
ningling_21| | 2013-7-27 20:27 | 只看该作者
LZ先拿楼上的代码试试...

使用特权

评论回复
5
logokfu| | 2013-7-27 20:44 | 只看该作者
搭车问个问题,今天我也弄了个18b20,发现这个时序有点杂。不像iic那样,网上看了下发现大多数都这个写法,发现这样中间会有大量的delay延时,这样会影响程序的实时性啊。比如我的程序除了这个温度传感器,还要对38k的红外进行解码,还要扫矩阵键盘,驱动lcd等,这样的程序如果改为用定时器累计延时的话,时序就不好写了。有朋友这样做过吗。

使用特权

评论回复
6
zuoxuqi| | 2013-7-27 21:08 | 只看该作者
可以用定时器延时来实现,DS18B20读取有几个阶段,分开执行

使用特权

评论回复
7
logokfu| | 2013-7-28 06:42 | 只看该作者
zuoxuqi 发表于 2013-7-27 21:08  可以用定时器延时来实现,DS18B20读取有几个阶段,分开执行

这个定时订多久为宜呢。

使用特权

评论回复
8
林志财|  楼主 | 2013-7-28 10:18 | 只看该作者
我跟着时序写但是还是返回不了温度值,所以连到底通讯了没有也 不知道啊,首先是复位信号,然后读写,读温度,也不知道那步不行

使用特权

评论回复
9
ningling_21| | 2013-7-28 10:20 | 只看该作者
**kfu 发表于 2013-7-28 06:42
这个定时订多久为宜呢。

这要看18B20的资料,尽量符合手册的规定
例如:可以定一个最小的时基例如500US,其它延时都在这个基础上计数就可以了

使用特权

评论回复
10
林志财|  楼主 | 2013-7-28 10:21 | 只看该作者
一般怎么调试呢,这种器件

使用特权

评论回复
11
logokfu| | 2013-7-28 10:39 | 只看该作者
林志财 发表于 2013-7-28 10:18  我跟着时序写但是还是返回不了温度值,所以连到底通讯了没有也 不知道啊,首先是复位信号,然后读写,读温 ...

复位信号其实最简单了,用示波器可以看出来,如果复位成功,18b20会把数据线强制拉低的,表现为波形会出现略微低于0v电平的。

使用特权

评论回复
12
logokfu| | 2013-7-28 10:48 | 只看该作者
ningling_21 发表于 2013-7-28 10:20  这要看18B20的资料,尽量符合手册的规定  例如:可以定一个最小的时基例如500US,其它延时都在这个基础上 ...

18b20比较特殊,看了时序,定时500us显然是达不到要求的,因为中间有些延时单步是100us左右,还有的是几十us,只有开始的复位信号需要至少480us。如果写个函数来做这个功能的话,显然要多次调用这个函数才能达到目的。但是这个函数究竟多久调用一次比较合适呢。因为我的系统还要刷数码管,扫矩阵键盘,红外解码,定时器定的时间短了虽然可以完成温度功能但是其他任务怕是做不完了,反之,温度功能即使可以做到恐怕也会影响程序的实时性啊。

使用特权

评论回复
13
ningling_21| | 2013-7-28 10:51 | 只看该作者
**kfu 发表于 2013-7-28 10:48
18b20比较特殊,看了时序,定时500us显然是达不到要求的,因为中间有些延时单步是100us左右,还有的是几 ...

我只是举例,不是一定是500US,可以根据具体情况来定。
几十US的,直接调用延时程序也不会影响实时性。

使用特权

评论回复
14
logokfu| | 2013-7-28 10:55 | 只看该作者
zuoxuqi 发表于 2013-7-27 21:08  可以用定时器延时来实现,DS18B20读取有几个阶段,分开执行

我的意思就是分几个阶段执行,定时时间长了不行,短了的话,由于还有其他任务,怕是不能把所有的任务执行完啊,之前做的都是一个系统需要扫矩阵键盘,同时还要刷段式lcd屏,还要检测50hz工频,同时还要模拟出时序控制可控硅,程序实时性都很好,现在这个温感器不是很好搞啊

使用特权

评论回复
15
logokfu| | 2013-7-28 11:16 | 只看该作者
ningling_21 发表于 2013-7-28 10:51  我只是举例,不是一定是500US,可以根据具体情况来定。  几十US的,直接调用延时程序也不会影响实时性。 ...

几十us不影响,这个我知道,比如模拟iic读取eeprom,这个我都是直接delay做的,100k的通信速率。但是这个18b20就不那么好做了,时序要求还是比较严格的,我之前有做过,定时100us来做的。然后中间小于100us的延时我都是在这100us的定时之间直接delay的,大于100us的,比如开头有个不小于480us的初始化,这个我是用了5个100us分5次来做的。但是发现不是很好掌握,调试了一天也没搞出来,网上的代码都是直接delay写的也没见有谁分步做的。额,这个有点麻烦这个。另外我的这个程序里面用到pid算法了,我做温控算法,现在就是卡在这个定时时间上面了。

使用特权

评论回复
16
林志财|  楼主 | 2013-7-28 11:27 | 只看该作者
是分步来做可能比较好。要有示波器。先看复位信号行不行先

使用特权

评论回复
17
ningling_21| | 2013-7-28 11:30 | 只看该作者
480us 可以长点,但不能短。
另就是配合状态机来实现...
if(x==0)
{
   复位
   x =1;
}
else if(x==1)
{
  启动温度转换
  x=2;
}
......

使用特权

评论回复
18
logokfu| | 2013-7-28 14:15 | 只看该作者
ningling_21 发表于 2013-7-28 11:30  480us 可以长点,但不能短。  另就是配合状态机来实现...  if(x==0)

我还要做pid运算啊

使用特权

评论回复
19
andyding| | 2013-7-28 16:39 | 只看该作者
3楼代码我试试看

使用特权

评论回复
20
林志财|  楼主 | 2013-7-28 17:59 | 只看该作者
试的怎么样

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

392

帖子

0

粉丝