找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 16795|回复: 10
收起左侧

最全面DS18B20中文资料

  [复制链接]
ID:290321 发表于 2018-3-11 11:08 | 显示全部楼层 |阅读模式
DS18B20
14.1概念 .
这一章 是关于 DS18B20 实时温 度传感器。 相信有学过 c51 单片机 的朋友都对 他不陌生
吧。我恰恰也学习过,不过当初并没有掌握好。学习板搭配的 DS18B20,一般上给人的
感觉有点 像三极管,其实 DS18B20 的内部结 构与原理也挺猥 琐的,但是我们使 用也是
为了实现温度传感的功能而已,基本上不会介绍过度深入。



14.2DS18B20介绍


DS18B20 有三只引脚,VCC,DQ ,和 VDD。




而 HJ-2G 板子上,采用了外部供电的链接方式,而总线必须链接上拉电阻。这一目的告 诉我们,一线总线在空置状态时,都是一直处于高电平。





DS18B20 的 内 部 有 64 位 的ROM 单元,和 9 字节的暂存器单 元 。 64 位 ROM 包 含 了 ,DS18B20 唯一的序列号(唯一的名字)。



以上是内部 9 个字节的暂存单元(包括 EEPROM)。
字节 0~1 是转换好的温度。
字节 2~3 是用户用来设置最高报警和最低报警值。这个可以用软件来实现。
字节 4 是用来配置转换精度,9~12 位。
字节 5~8 就不用看了。


14.3字节 0~1:转换好的温度



DS18B20 的温度操作是使用 16 位,也就是说分辨率是 0.0625。BIT15~BIT11 是符号位,
为了就是表示转换的值是正数还是负数。看看数据手册给出的例子吧。







要求出正数的十进制值,必须将读取到的 LSB 字节,MSB 字节进行整合处理,然后乘 以 0.0625 即可。



Eg:假设从,字节 0 读取到 0xD0 赋值于 Temp1,而字节 1 读取到 0x07 赋值于 Temp2, 然后求出十进制值。



unsigned int Temp1,Temp2,Temperature;


Temp1=0xD0;               // 低八位
Temp2=0x07;               // 高八位


Temperature = ((Temp2<<8 ) | Temp1 ) * 0.0625;
// 又或者
Temperature = (Temp1 + Temp2 *256) * 0.0625;              //Temperature=125


在这里我们遇见了一个问题,就是如何求出负数的值呢?很遗憾的,单片机不像人脑那 样会心算,我们必须判断 BIT11~15 是否是 1,然后人为置一负数标志。



Eg. 假设从,字节 0 读取到 0x90 赋值于 Temp1,而字节 1 读取到 0xFC 赋值于 Temp2, 然后求出该值是不是负数,和转换成十进制值。


  1. unsigned int Temp1,Temp2,Temperature;
  2. unsigned char Minus_Flag=0;


  3. Temp1=0x90;               // 低八位
  4. Temp2=0xFC;               // 高八位


  5. //Temperature = (Temp1 + Temp2 *256) * 0.0625;              //Temperature=64656
  6. // 很明显不是我们想要的答案
  7. if(Temp2&0xFC)              // 判断符号位是否为 1
  8. {
  9. Minus_Flag=1;              // 负数标志置一
  10. Temperature = ((Temp2<<8 ) | Temp1 )              // 高八位第八位进行整合
  11. Temperature= ((~Temperature)+1);               // 求反,补一
  12. Temperature*= 0.0625;              // 求出十进制
  13. }              //Temperature=55;
  14. else
  15. {
  16. Minus_Flag=0;
  17. Temperature = ((Temp2<<8 ) | Temp1 ) * 0.0625;
  18. }
复制代码




那个人为的负数标志,是真的很有用处的。这个要看你你自己的想象力了,如何去利用它。




继续继续,以上我们是求出没有小数点的正数。如果我要求出小数点的值的话,那么我 应该这样做。



Eg:假设从,字节 0 读取到 0xA2 赋值于 Temp1,而字节 1 读取到 0x00 赋值于 Temp2, 然后求出十进制值,要求连同小数点也求出。

  1. unsigned int Temp1,Temp2,Temperature;


  2. Temp1=0x90;               // 低八位
  3. Temp2=0xFC;               // 高八位

  4. // 实际值为 10.125
  5. //Temperature = ((Temp2<<8 ) | Temp1 ) * 0.0625;              //10,无小数点
  6. Temperature = ((Temp2<<8 ) | Temp1 ) * (0.0625 * 10) ;       //101 ,一位小数点
  7. //Temperature = ((Temp2<<8 ) | Temp1 ) * (0.0625 * 100) ;   //1012,二位小数点
复制代码


如以上的例题,我们可以 先将 0.0625 乘以 10,然后再乘以整合后的 Temperature 变量 , 就可以求出后面 一个小数点的值(求出更多的小数 点,方法都是以此类推 )。得出的结 果是 101,然后再利用简单的算法,求出每一位的值。



unsinged char Ten,One,Dot1


Ten=Temperature/100;                  //1
One=Temperature%100/10;          //0
Dot1=%10;                                //1


求出负数的思路也一样,只不过多出人为置一负数标志,求反补一的动作而已。自己发 挥想象力吧。




14.4字节 2~3THTL配置
TH 与 TL 就是所 谓的温度最 高界限,和 温度最低界 限的配置。 其实这些可 以使用软件
来试验,所以就无视了。



14.5字节 4:配置寄存器




BIT7 出厂的时候就已经设置为 0,用户不建议去更改。而 R1 与 R0 位组合了四个不同 的转换精度, 00 为 9 位转换精度而转换时间是 93.75ms,01 为 10 位转换精度而转换 时 间是 187.5ms,10 为 11 位转换精度而转换时间是 375ms,11 为 12 位转换精度而转换时 间是 750ms(默认)。该寄存器还是留默认的好,毕竟转换精度表示了转换的质量。





14.6字节 5~78:保留位,CRC
无视,无视吧。



14.7单片机访问 DS18B20
DS18B20 一 般 都是 充 当 从 机的 角 色 , 而单 片 机 就 是主 机 。 单 片机 通 过 一 线总 线 访 问
DS18B20 的话,需要经过以下几个步骤:

1.DS18B20 复位。
2.执行 ROM 指令。
3.执行 DS18B20 功能指令(RAM 指令)。


补充一下 。一般上我们都 是使用单点,也就 是说单线总线上 仅有一个 DS18B20 存在而 已。所以 我们无需刻意读 取 ROM里边的序 列号来,然后匹 配 那个 DS18B20?而是更 直接的,跳过 ROM 指令,然后直接执行 DS18B20 功能指令。


DS18B20 复位,在某种意义上就是一次访问 DS18B20 的开始,或者可说成是开始信号。


ROM 指令,也就是访问,搜索,匹配,DS18B20 个别的 64 位序列号的动作。在单点情 况下,可以直接跳过 ROM 指令。而跳过 ROM 指令的字节是 0xCC。



DS18B20 功能指令有很多种,我就不一一的介绍了 ,数据手册里有更详细的介绍。这里 仅列出比较常用的几个 DS18B20功能指令。


0x44:开始转换温度。转换好的温度会储存到暂存器字节 0 和 1。
0xEE :读暂存指令。读暂存指令,会从暂存器 0 到 9,一个一个字节读取,如果要停止
的话,必须写下 DS18B20 复位。



14.8DS18B20复位



DS18B20 的复位时序如下:
1.单片机拉低总线 480us~950us, 然后释放总线(拉高电平)。
2.这时 DS18B20 会拉低信号,大约 60~240us 表示应答。
3.DS18B20 拉低电平的 60~240us 之间,单片机读取总线的电平,如果是低电平,那么表示复位成功。
4.DS18B20 拉低电平 60~240us 之后,会释放总线。




C 语言代码:


//DS1302 复位 函数
void DS1302_Res et()

{

DDRA|=BIT(DQ);              //DQ 为输 出状态 PORTA&=~BIT(DQ);               //输出 低电平Delay_1us (500);              //延迟 500 微妙 PORTA|=BIT(DQ);              //示范 总线 Delay_1us(60);              //延迟 60 微妙 DDRA&=~BIT(DQ);               //DQ 位输 出状态

while(PINA&BIT (DQ));               //等待 从机 DS18B20 应答 (低电 平有效 )
while(!(PINA&BIT(DQ)));              //等待 从机 DS18B20 释放 总线
}



14.9DS18B20读写逻辑 01







DS18B20 写逻 辑 0 的步 骤如下 :
1.单片 机拉低 电平大 约 10~15us ,。
2.单片 机持续 拉低电 平大约 20~45us 的时 间。
3.释放 总线
DS18B20 写逻 辑 1 的步 骤如下 :
1.单片 机拉低 电平大 约 10~15us ,。
2.单片 机拉高 电平大 约 20~45us 的时 间。
3.释放 总线


DS18B20 读逻 辑 0 的步 骤如下 :
1.在读 取的时 候单片 机拉低 电平大 约 1us
2.单片 机释放 总线, 然后读 取总线 电平。
3.这时 候 DS18B20 会拉 低电平 。
4.读取 电平过 后,延 迟大约 40~45 微妙
DS18B20 读逻 辑 1 的步 骤如下 :
1.在读 取的时 候单片 机拉低 电平大 约 1us
2.单片 机释放 总线, 然后读 取总线 电平。
3.这时 候 DS18B20 会拉 高电平 。
4.读取 电平过 后,延 迟大约 40~ 45 微妙




如果要读或者写 一个字节,就要重复以上的步骤八 次。如以下的 C 代码,使用 for 循环,和数据变 量的左移和或运算,实现一个字节读与写。

  1. //DS18B20 写字 节函数
  2. void DS1302_Write(uns igned char Data)

  3. {
  4. unsigned char i;
  5. DDRA|=BIT(DQ);              //DQ 为输 出
  6. for(i=0;i<8;i++)

  7. {
  8. PORTA&=~BIT(DQ);               //拉低 总线
  9. Delay_1us (10);              //延迟 10 微妙 (最大 15 微妙 )


  10. if(Data&0x01) PORTA|=BIT(DQ);

  11. els e PORTA&=~BIT(DQ);
  12. Delay_1us (40);              //延迟 40 微妙 (最大 45 微妙 )


  13. PORTA|=BIT(DQ);              //释放 总线
  14. Delay_1us (1);              //稍微 延迟
  15. Data>>=1;

  16. }
  17. }


  18. //DS18B20 读字 节函数
  19. unsigned char DS1302_Read()

  20. {
  21. unsigned char i,Temp;


  22. for(i=0;i<8;i++)

  23. {
  24. Temp>>=1;               //数据 右移


  25. DDRA|=BIT(DQ);              //DQ 为输 出状态
  26. PORTA&=~BIT(DQ);               //拉低 总线, 启动输 入 PORTA|=BIT(DQ);              //释放 总线 DDRA&=~BIT(DQ);              //DQ 为输 入状态


  27. if(PINA&BIT(DQ)) Temp|=0x80;
  28. Delay_1us (45);              //延迟 45 微妙 (最大 45 微妙 )
  29. }

  30. return Temp;
  31. }
复制代码



就是这么建档而已 ,不过这里有一个注意点,就是 Delay_1us(); 函数延迟的时间, 必须模拟非常准
确,因为单线总线对时序的要求敏感点。




14.10简单归纳 实验开始之前,简单的归纳一些重点。单线总线高电平为闲置状态。单片机访问 DS18B20 必须遵守, DS18B20 复位-->执行 ROM 指令-->执行 DS18B20 功能指令。而在单点上, 可以直接跳过 ROM 指令。DS18B20 的转换精度默认为 12 位,而分辨率是 0.0625。


DS18B20 温度读取函数参考步骤:

DS18B20 开始转换:
1.DS18B20 复位。
2.写入跳过 ROM 的字节命令,0xCC。
3.写入开始转换的功能命令,0x44。
4.延迟大约 750~900 毫秒

DS18B20 读暂存数据:
1.DS18B20 复位。
2.写入跳过 ROM 的字节命令,0xCC。
3.写入读暂存的功能命令,0xee。
4.读入第 0 个字节 LS Byte,转换结果的低八位。
5.读入第 1 个字节 MS Byte,转换结果的高八位。
6.DS18B20 复位,表示读取暂存结束。

数据求出十进制:
1.整合 LS Byte 和 MS Byte 的数据
2.判断是否为正负数(可选)
3.求得十进制值。正数乘以 0.0625,一位小数点乘以 0.625,二位小数点乘以 6.25。
4.十进制的“个位”求出。



14.11实验:利用 DS18B20实现单点温度测量,结果输出在数码管。



DS18B20 接口               ATMega 16 对应引脚


实验的要求是以 DS18B20 默认的配置,亦即 12 位的转换精度。然而输出的结果为两个 小数点 xx.xx。HJ-2G 板子上设计得DS18B20 的接口和典型,没有什么特别需要注意的。 而 DS18B20 DQ 引脚对应的链接是 PA5。



源码:
  1. ===================================================================
  2. //1400-DS18B20.c
  3. //简单 的驱动 程式
  4. //akuei2 08-01-10


  5. #include "iom16v.h"

  6. #include "macros .h"

  7. #include "LED7.h"


  8. #define DQ PA5


  9. //微妙 级延迟 函数
  10. void Delay_1us (unsigned int x)

  11. {

  12. unsigned int i;
  13. x=x*5/4;

  14. for( i=0;i<x;i++);

  15. }


  16. //DS1302 复位 函数
  17. void DS1302_Res et()

  18. {

  19. DDRA|=BIT(DQ);              //DQ 为输 出状态 PORTA&=~BIT(DQ);               //输出 低电平 Delay_1us(500);              //延迟 500 微妙 PORTA|=BIT(DQ);              //示范 总线 Delay_1us (60);              //延迟60 微妙 DDRA&=~BIT(DQ);               //DQ 位输 出状态
  20. while(PINA&BIT (DQ));               //等待 从机 DS18B20 应答 (低电 平有效 )
  21. while(!(PINA&BIT(DQ)));              //等待 从机 DS18B20 释放 总线
  22. }


  23. //DS1302 写字 节函数
  24. void DS1302_Write(uns igned char Data)

  25. {
  26. unsigned char i;
  27. DDRA|=BIT(DQ);              //DQ 为输 出
  28. for(i=0;i<8;i++)

  29. {
  30. PORTA&=~BIT(DQ);               //拉低 总线
  31. Delay_1us (10);              //延迟 10 微妙 (最大 15 微妙 )


  32. if(Data&0x01) PORTA|=BIT(DQ);

  33. els e PORTA&=~BIT(DQ);
  34. Delay_1us (40);              //延迟 40 微妙 (最大 45 微妙 )


  35. PORTA|=BIT(DQ);              //释放 总线
  36. Delay_1us (1);              //稍微 延迟
  37. Data>>=1;

  38. }

  39. }


  40. //DS1302 读字 节函数
  41. unsigned char DS1302_Read()

  42. {

  43. unsigned char i,Temp;


  44. for(i=0;i<8;i++)

  45. {
  46. Temp>>=1;               //数据 右移


  47. DDRA|=BIT(DQ);              //DQ 为输 出状态
  48. PORTA&=~BIT(DQ);               //拉低 总线, 启动输 入 PORTA|=BIT(DQ);              //释放 总线 DDRA&=~BIT(DQ);               //DQ为输 入状态


  49. if(PINA&BIT(DQ)) Temp|=0x80;
  50. Delay_1us (45);              //延迟 45 微妙 (最大 45 微妙 )
  51. }


  52. return Temp;
  53. }


  54. //读温 度函数
  55. unsigned int Read_Temperature()

  56. {
  57. unsigned int Temp1,Temp2;


  58. DS1302_Res et();               //DS1302 复位
  59. DS1302_Write(0xCC);              //跳过 ROM DS1302_Write(0x44);              //温度 转换


  60. DS1302_Res et();               //DS1302 复位
  61. DS1302_Write(0xCC);              //跳过 ROM DS1302_Write(0xbe);              //读取 RAM


  62. Temp1=DS1302_Read();               //读低 八位, LS Byte, RAM0
  63. Temp2=DS1302_Read();               //读高 八位, MS Byte, RAM1
  64. DS1302_Res et();               //DS1302 复位 ,表示 读取结 束


  65. return (((Temp2<<8)|Temp1)*6.25); //0.0625=xx, 0.625=xx.x, 6.25=xx.xx




  66. }


  67. void main()

  68. {

  69. unsigned int Temp;
  70. LED7_Init();              //初始 化数码 管引脚
  71. while(1)

  72. {
  73. Temp=Read_Temperature();               //调用 读取温 度函数 Number_Show(Temp);               //显示 温度Delay_1us (100);              //稍微 延迟
  74. }


  75. }



  76. LED7.h 的头文件
  77. ===================================================================
  78. //LED7.H
  79. // 数码管显示


  80. // 数组声明并定义在存储数据区 code
  81. //0~9


  82. #pragma data:code
  83. unsigned              char              const
  84. Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,}; unsigned char const Number_Dot[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};


  85. // 延迟函数
  86. void Delay(unsigned long x)
  87. {
  88. while(x--);
  89. }


  90. // 数码管显示函数
  91. void Number_Show(unsigned int Num)
  92. {

  93. unsigned char Ten,One,Dot1,Dot2; Ten=Num/1000;                             // 取十位 One=Num%1000/100;                             // 取个位Dot1=Num%100/10;              // 取点数位 Dot2=Num%10;              // 取点数位


  94. // 显示十位

  95. PORTB=Number[Ten]; // 送模码 PORTA|=BIT(PA3);              //PA3 高电平PORTA&=~BIT(PA3);                            //PA3 低电平
  96. PORTB=~BIT(0);              //送位选
  97. PORTA|=BIT(PA4);              //PA3 高电平
  98. PORTA&=~BIT(PA4);              //PA3 低电平
  99. Delay(600);              // 稍微延迟


  100. // 显示个位
  101. PORTB=Number_Dot[One];              // 送模码
  102. PORTA|=BIT(PA3);              //PA3 高电平
  103. PORTA&=~BIT(PA3);              //PA3 低电平


  104. PORTB=~BIT(1);              //送位选
  105. PORTA|=BIT(PA4);              //PA3 高电平
  106. PORTA&=~BIT(PA4);              //PA3 低电平
  107. Delay(600);              // 稍微延迟


  108. // 显示点数位 1
  109. PORTB=Number[Dot1];              //送模码
  110. PORTA|=BIT(PA3);              //PA3 高电平
  111. PORTA&=~BIT(PA3);              //PA3 低电平


  112. PORTB=~BIT(2);              //送位选
  113. PORTA|=BIT(PA4);              //PA3 高电平
  114. PORTA&=~BIT(PA4);              //PA3 低电平
  115. Delay(600);              // 稍微延迟


  116. // 显示点数位 2
  117. PORTB=Number[Dot2];              //送模码
  118. PORTA|=BIT(PA3);              //PA3 高电平
  119. PORTA&=~BIT(PA3);              //PA3 低电平


  120. PORTB=~BIT(3);              //送位选
  121. PORTA|=BIT(PA4);              //PA3 高电平
  122. PORTA&=~BIT(PA4);              //PA3 低电平
  123. Delay(600);              // 稍微延迟


  124. // 显示`
  125. PORTB=0x63;              // 送模码
  126. PORTA|=BIT(PA3);              //PA3 高电平
  127. PORTA&=~BIT(PA3);              //PA3 低电平


  128. PORTB=~BIT(4);              //送位选
  129. PORTA|=BIT(PA4);              //PA3 高电平






  130.         

  131. PORTA&=~BIT(PA4);Delay(600);
  132.         
  133. //PA3 低电平
  134. // 稍微延迟
  135. // 显示 C
  136.         

  137. PORTB=0x39;PORTA|=BIT(PA3);PORTA&=~BIT(PA3);
  138.         
  139. // 送模码
  140. //PA3 高电平
  141. //PA3 低电平

  142. PORTB=~BIT(5);
  143.         
  144. //送位选

  145. PORTA|=BIT(PA4);PORTA&=~BIT(PA4);Delay(1000);
  146.         
  147. //PA3 高电平
  148. //PA3 低电平
  149. // 稍微延迟

  150. }
  151.         
  152.         

  153. //IO 初始化函数
  154. void LED7_Init()
  155. {
  156. DDRA|=BIT(PA3);              //PA3 状态为输出
  157. DDRA|=BIT(PA4);              //PA4 状态为输出
  158. DDRB|=0xff;              //PB 状态为输出
  159. }
复制代码



以上的程式只有一个注意点就是 :DS18B20 的转启动换频率不要超过 750ms。其他的没 有什么需要特别注意了。




14.12一个多点测温的假想




以上是多点测温的一个假想,就是利用 GND 作于片选的角色。该方法有一个好处就是可以省去猥琐
的 ROM 指令,但是最为代价需要牺牲 IO 口,而且还控制好每一个 DS18B20 的执行次序。

DS18B20中文资料--最全版.doc

50 KB, 下载次数: 60, 下载积分: 黑币 -5

z

最全面DS18B20中文资料.pdf

340.54 KB, 下载次数: 123, 下载积分: 黑币 -5

z

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:259979 发表于 2018-3-11 21:35 来自手机 | 显示全部楼层
谢谢分享。。
回复

使用道具 举报

ID:296540 发表于 2018-3-28 15:07 | 显示全部楼层
谢谢谢谢
回复

使用道具 举报

ID:412309 发表于 2018-10-19 15:39 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:118535 发表于 2018-10-31 21:42 | 显示全部楼层
感谢LZ的无私分享~~
回复

使用道具 举报

ID:434779 发表于 2018-11-29 15:51 | 显示全部楼层
学习AVR不错的教材!
回复

使用道具 举报

ID:26864 发表于 2018-12-3 13:34 | 显示全部楼层
感谢楼主分享,好新鲜的日期
回复

使用道具 举报

ID:155151 发表于 2019-5-17 21:33 | 显示全部楼层
不错,感谢分享
回复

使用道具 举报

ID:480627 发表于 2020-1-26 18:31 | 显示全部楼层
WORD里面怎么图片都没了哦。。。
回复

使用道具 举报

ID:627832 发表于 2020-3-16 22:34 | 显示全部楼层
word里没有图片啊
回复

使用道具 举报

ID:701939 发表于 2020-3-23 17:34 | 显示全部楼层
感谢,非常感谢楼主的热心
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表