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

目标: DS18B20数字温度计(二)
2.温度读取操作
DS18B20 时序包括如下几种:初始化时序、写(0和1)时序、(0和1)时序。DS18B20发送所有的命令和数据都是字节的低位在前。
  • 初始化
【单片机小白学习之路(三十一)---DS18B20数字温度计(二)】和I2C的寻址类似,1-Wire总线开始也需要检测这条总线上是否存在DS18B20这个器件。如果这条总线上存在DS18B20,总线会根据时序要求返回一个低电平脉冲,如果不存在的话,也就不会返回脉冲,即总线保持为高电平,所以习惯上称之为检测存在脉冲。
此外,获取存在脉冲不仅仅是检测是否存在DS18B20,还要通过这个脉冲过程通知DS18B20准备好,单片机要进行操作它了
单片机小白学习之路(三十一)---DS18B20数字温度计(二)
文章图片
初始化时序
大家注意看图,实粗线是我们 单片机IO口拉低这个引脚,虚粗线是 DS18B20拉低这个引脚,细线是单片机和DS18B20释放总线后,依靠上拉电阻的作用把IO口引脚拉上去的。这个我们前边提到过了,51单片机释放总线就是给高电平即可。
存在脉冲检验过程,首先我们单片机要拉低这个引脚,持续时间在480us---960us(实粗线),然后单片机释放总线,就是给这个引脚高电平,持续时间在15--60us(细弧线),然后ds18b20会主动拉低这个引脚持续60--240us(虚粗线),然后ds18b20会主动释放总线,该引脚就会被上拉电阻拉成高电平
  • 第一步,拉低DS18B20这个引脚,持续500us;
  • 第二步,延时60us;
  • 第三步,读取存在脉冲,并且等待存在脉冲结束。
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的状态了。
  • 写时序

    单片机小白学习之路(三十一)---DS18B20数字温度计(二)
    文章图片
    写时序脉冲
前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小于无穷的,那在这个时间段,我们是可以开中断来处理其他程序的。发送一个字节的数据程序如下。
  • 第一步,拉低DS18B20这个引脚,持续2us;
  • 第二步,判断输入的数据是0还是1,并延时60--120us
  • 第三步,释放总线
  • 第四步,数据右移
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数字温度计(二)
    文章图片
    读时序脉冲
当要读取DS18B20的数据的时候,我们的单片机首先要拉低这个引脚,并且至少保持1us的时间,然后释放引脚,释放完毕后要尽快读取。从拉低这个引脚到读取引脚状态,不能超过15us。
大家从图可以看出来,主机采样时间,也就是控制器采样,是在15us之内必须完成的。
  • 第一步,拉低DS18B20这个引脚,持续2us;
  • 第二步,立马释放总线,进行读取操作
  • 第三步,读取数据,从最低位开始
  • 第四步,数据位置调整
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循环正好停止

    推荐阅读