硬件设计

单片机小白学习之路(三十一)---DS18B20数字温度计(二)

2018-10-03  本文已影响0人  飞向深空

目标: DS18B20数字温度计(二)

2.温度读取操作

DS18B20 时序包括如下几种:初始化时序、写(0和1)时序、(0和1)时序。DS18B20发送所有的命令和数据都是字节的低位在前。


和I2C的寻址类似,1-Wire总线开始也需要检测这条总线上是否存在DS18B20这个器件。如果这条总线上存在DS18B20,总线会根据时序要求返回一个低电平脉冲,如果不存在的话,也就不会返回脉冲,即总线保持为高电平,所以习惯上称之为检测存在脉冲。

此外,获取存在脉冲不仅仅是检测是否存在DS18B20,还要通过这个脉冲过程通知DS18B20准备好,单片机要进行操作它了

初始化时序

大家注意看图,实粗线是我们 单片机IO口拉低这个引脚,虚粗线是 DS18B20拉低这个引脚,细线是单片机和DS18B20释放总线后,依靠上拉电阻的作用把IO口引脚拉上去的。这个我们前边提到过了,51单片机释放总线就是给高电平即可。

存在脉冲检验过程,首先我们单片机要拉低这个引脚,持续时间在480us---960us(实粗线),然后单片机释放总线,就是给这个引脚高电平,持续时间在15--60us(细弧线),然后ds18b20会主动拉低这个引脚持续60--240us(虚粗线),然后ds18b20会主动释放总线,该引脚就会被上拉电阻拉成高电平


uchar Ds18b20Init()  //ds18b20的初始化
{
    uchar i;
    DSPORT = 0;
    delay_10tus(50); //延时约500us(实粗线)    
    DSPORT = 1; //单片机释放总线就是给其高电平
    delay_10tus(6); //延时是60us(细弧线)
    while(DSPORT)
    {
        delay_1ms(1);
        i++;
        if(i>3) return0; //又等了3ms DSPROT还是高电平则返回0表示初始化失败
    }
    return 1; //DSPROT是低电平(虚粗线)表示初始化成功
}

程序中细弧线处明明是延时15--60us,为什么我们却延时60us呢?举个例子,你妈喊你去吃饭,说在15到60分钟内弄好饭,那什么时候去才能稳稳的吃到饭呢?当然是在60分钟后,饭一定弄好了,这也是同样的道理,60u后一定可以判断DSPROT的状态了。



前60us是写入0 , 后60us是写入1。

当给ds18b20写入0时单片机直接将引脚拉低60--120us即可。图中的意思是单片机先拉低15us后,ds18b20会在15--60us之间来读取这一位,最早会在15us处读取,所以图中MIN对应的15us处,典型值是30us的时刻读取(TYP处),最多不会超过60us(MAX处),DS18B20必然读取完毕,所以持续时间超过60us即可。

当要给DS18B20写入‘1’的时候,单片机先将这个引脚拉低,拉低时间大于1us,然后马上释放总线,即拉高引脚,并且持续时间也要大于60us。和写‘0’类似的是,DS18B20会在15到60us之间来读取这个‘1’。

可以看出来,DS18B20的时序比较严格,写的过程中最好不要有中断打断,但是在两个“位”之间的间隔,是大于1小于无穷的,那在这个时间段,我们是可以开中断来处理其他程序的。发送一个字节的数据程序如下。


void Ds18b20WriteByte(uchar dat)
{

    EA = 0;  //关闭总中断
    uint i,j;
    for(j=0;j<8;j++){
        DSPORT = 0;
        _nop_();
        _nop_();   //写入1时最少1us所以直接延时2us
        DSPORT = dat&0x01;   //判断数值最后一位是0还是1
        delay_10tus(6); //延时60us
        DSPORT = 1; //释放总线,至少1us给总线恢复时间才能接着写入第二个数值
        dat >>= 1; //数值向右移一位为下次判断最后一位是0还是1做准备
    }
    EA = 1; //开启总中断
}


当要读取DS18B20的数据的时候,我们的单片机首先要拉低这个引脚,并且至少保持1us的时间,然后释放引脚,释放完毕后要尽快读取。从拉低这个引脚到读取引脚状态,不能超过15us。
大家从图可以看出来,主机采样时间,也就是控制器采样,是在15us之内必须完成的。


uchar Ds18b20ReadByte() //单片机读取ds18b20的数据
{
    uchar byte,bi;
    uint i ,j;
    EA = 0;
    for(j=0;j<8;j++){
        DSPROT = 0;     //先拉低总线
        _nop_();
        _nop_();        //延时2us
        DSPROT = 1;     //释放总线
        _nop_();
        _nop_(); //延时2us等待数据稳定
        bi = DSPROT;    //读取数据,从最低位开始读取,不能延时太久不然数据会失效
        byte = (byte>>1) | (bi<<7);
        delay_10tus(6);  //读取完之后等待60us再接着读取下一个数
    }
    return byte;
    EA = 1;     
}

byte = (byte>>1) | (bi<<7);是什么意思?比如一开始byte 是0000 0000,bi得到的是数据的最低位假如是1 则是0000 0001,那么byte>>1是0000 0000, bi<<7是1000 0000,两个一或成了1000 0000.

那么假如第二次bi还是拿到了1,是0000 0001,那么byte>>1由上面可知变成0100 0000,那么(byte>>1) | (bi<<7)是1100 0000,然后1100 0000又给了byte,这样循环8次,直到最先获取的1移到最后一位位置,for循环正好停止



上一篇下一篇

猜你喜欢

热点阅读