温度传感器

测温度的方式:物理(汞柱、气压)、电子(金属电性能随温度变化)
早期:热敏电阻(模拟接口)
现代:专用sensor(数字接口,如I2C、DS18B20的单总线接口等)

DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点。

测温范围:-55°C 到 +125°C

通信接口:1-Wire(单总线)

其它特征:可形成总线结构、内置温度报警功能、可寄生供电。

引脚及应用电路:

单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线:

一根通信线:DQ,异步、半双工

单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线。

DS18B20的基本特征

  1. 内置集成ADC,外部数字接口
  2. 单总线数字接口,布线成本低
  3. 温度范围宽、精确率高(相对)
  4. 数字值温度分辨率位数可软件设置
  5. 温度阈值报警功能,且阈值可内置存储掉电不丢失
  6. 温度采集速度快(750ms)
  7. 内置唯一64位序列码,CPU可以单线串联无限多个DS18B20
  8. 支持VDD供电,或通过数据总线及内部电容实现寄生电源供电

综合评价:
DS18B20是很多年前的东西了
现在趋向于温度+湿度的综合传感器
现实应用一般低端用热敏电阻、热电偶,高端用精密传感器
学习重点和难点是单总线协议的时序编程实现

注意18B20直接读出绝对温度值不需要参考点。

单总线协议

  • 首先搞清楚你的系统是单点还是多点
  • DS18B20规定总线上的数据是LSB的(一个字节是从最低位开始传输的)
  • 单总线硬件连接要求:漏极开路式+5K欧姆的上拉电阻(见上方的图)
  • 总线低电平超过480us,从设备将被复位

1-Wire总线系统即一个总线主设备控制一个或多个从设备。DS18B20始终是一个从设备。当总线上只有一个从设备时,此系统被称为“单节点”系统;当总线上有多个从设备连接时,此系统被称之为“多节点”系统。

1-Wire总线上所有的命令或者数据的发送接收都是遵循低位先发送的原则。

单总线协议标准执行步骤

主机必须按照单总线协议设定好的完整序列和DS18B20通信,每个回合包含3个步骤:初始化+ROM操作指令+功能操作指令。顺序不能错也不能省略任何一个。

DS18B20自己本身不会主动去进行温度测量,而是需要主控CPU主动发起一个温度转换的过程,这么设计是因为温度转换本身是要耗电的,所以设计为平时待机等待温度转换命令后才去进行温度AD转换。
主控CPU和DS18B20之间的通信是分周期的,譬如我们要让DS18B20进行温度转换就是一个周期。这个周期包含一个初始化+N个命令。(每个周期的开始都要有一个初始化,然后跟着N个命令)

初始化过程主要是探测目标DS18B20是否存在,若存在将芯片初始化。

命令很重要。所以DS18B20是一个典型的“命令-响应”型外设。学习这种外设的关键是命令集。

ROM操作指令
DS18B20支持多个芯片串联在一根总线上,也就是所谓的单总线协议,所以必须要主控CPU要能够区分总线上多个18B20,因此有个ROM操作指令来完成这个任务。
ROM操作指令和温度采集一点关系都没有,所以当我们总线上只有一个18B20的时候ROM操作指令我们不需要去管。
一旦系统中单总线上有多个18B20,那么我们必须借助ROM操作指令来区分多个18B20,而且这个区分过程可能需要多条ROM指令来完成。
如果系统中只有一个18B20,那么就用一条skip rom命令(0xCC)就可以跳过这个阶段。

功能指令
ROM操作指令目的是为了在单总线上多个18B20中挑选到那个当前我们要操作的18B20,而功能指令是为了和选定的18B20通信从而获取温度。

初始化:

初始化就是:主设备先拉低数据总线超过480us以发出一个复位脉冲,然后从设备DS18B20收到复位脉冲后内部进行硬件复位,复位完成后回复主设备一个存在脉冲,主设备收到了存在脉冲后就认为从设备已经准备好,初始化完成。(确认设备存在)

ROM命令

当总线上的主设备检测到了存在脉冲后,就可以执行ROM命令。这些命令是对每个设备独一无二的64位ROM编码进行操作的,当总线上连接有多个设备时,可以通过这些命令识别各个设备。这些命令同时也可以使主设备确定该总线上有多少个什么类型的设备或者有温度报警信号的设备。总共包含有5种ROM命令,每个命令的长度都是8 Bit。主设备在执行DS18B20功能命令之前必须先执行一个适当的ROM命令。(找到具体的设备)

DS18B20功能命令

当总线上的主设备通过ROM命令确定了哪个DS18B20能够进行通信时,主设备可以向其中一个DS18B20发送功能命令。这些命令使得主设备可以向DS18B20的暂存寄存器写入或者读出数据,初始化温度转换及定义供电模式。(具体的操作)

DS18B20

详见:DS18B20数据手册-中文版 - 知乎

DS18B20采用严谨的1-Wire总线通信协议来保证数据的完整性。该协议定义多个信号形式:复位脉冲,存在脉冲,写0,写1,读0,读1。主设备执行除了存在脉冲外的所有其他信号。

初始化程序—复位和存在脉冲

与DS18B20所有的通信都是由初始化序列开始的,该序列包括从主设备发出的复位脉冲及从DS18B20响应的存在脉冲组成。当DS18B20响应复位信号的存在脉冲后,则其向主设备表明其在该总线上,并且已经做好操作命令。

在初始化序列期间,总线上的主设备通过拉低1-Wire总线超过480us来发送(TX)复位脉冲。之后主设备释放总线而进入接收模式(RX)。当总线释放后,5kΩ左右的上拉电阻将1-Wire总线拉至高电平。当DS18B20检测到该上升边沿信号后,其等待15us至60us后通过将1-Wire总线拉低60us至240us来实现发送一个存在脉冲。

读/写时段

主设备通过写时段向DS18B20中写入数据,通过读时段从DS18B20中读取数据。1-Wire总线上每一个读写时段只能传送一个位的数据。

写时段

写时段有两种情况:“写1”时段和“写0”时段。主设备通过写1时段来向DS18B20中写入逻辑1以及通过写0时段来向DS18B20中写入逻辑0。每个写时段最小必须有60us的持续时间且独立的写时段间至少有1us的恢复时间。两个写时段都是由主设备通过将1-Wire总线拉低来进行初始化。

为了形成写1时段,在将1-Wire总线拉低后,主设备必须在15us之内释放总线。当总线释放后,5kΩ的上拉电阻将总线拉至高。为了形成写0时段,在将1-Wire总线拉低后,在整个时段期间主设备必须一直拉低总线(至少60us)。

在主设备初始化写时段后,DS18B20将会在15us至60us的时间窗口内对总线进行采样。如果总线在采样窗口期间是高电平,则逻辑1被写入DS18B20;若总线是低电平,则逻辑0被写入DS18B20。

读时段

仅在读时段期间DS18B20才能向主设备传送数据。因此,主设备在执行完读暂存寄存器[BEh]或读取供电模式[B4h]后,必须及时地生成读时段,这样DS18B20才能提供所需的数据。此外,主设备可以在执行完转换温度[44h]或拷贝EEPROM[B8h]命令后生成读时段,以便获得DS18B20功能命令的操作信息。

每个读时段最小必须有60us的持续时间且独立的写时段间至少有1us的恢复时间。读时段通过主设备将总线拉低超过1us再释放总线来实现初始化。当主设备初始化完读时段后,DS18B20将会向总线发送0或者1。DS18B20通过将总线拉至高来发送逻辑1,将总线拉至低来发送逻辑0。当发送完0后,DS18B20将会释放总线,则通过上拉电阻该总线将会恢复到高电平的闲置状态。从DS18B20中输出的数据在初始化读时序后仅有15us的有效时间。因此,主设备在开始改读时段后的15us之内必须释放总线,并且对总线进行采样。

代码实现

#include "ds18b20.h"
#include "uart.h"
#include <intrins.h>/******* 延时函数 *******************/void delay750us(void)   //误差 -0.217013888889us
{unsigned char a,b;for(b=198;b>0;b--)for(a=2;a>0;a--);
}void delay15us(void)   //误差 -0.894097222222us
{unsigned char a;for(a=4;a>0;a--);
}void delay70us(void)   //误差 -0.555555555556us
{unsigned char a,b;for(b=1;b>0;b--)for(a=28;a>0;a--);
}void delay45us(void)   //误差 -0.512152777778us
{unsigned char a;for(a=18;a>0;a--);
}void delay1ms(void)   //误差 -0.651041666667us
{unsigned char a,b;for(b=4;b>0;b--)for(a=113;a>0;a--);
}void delay750ms(void)   //误差 -0.000000000183us
{unsigned char a,b,c;for(c=147;c>0;c--)for(b=127;b>0;b--)for(a=17;a>0;a--);_nop_();  //if Keil,require use intrins.h
}/****** 低层时序 *********************************************/// 返回0则表示初始化成功,返回1则表示初始化失败
unsigned char Ds18b20Init(void)
{unsigned char i = 0;DATA = 0;            //将总线拉低480us~960usdelay750us();     // 实际延时750us,符合480-960之间的条件DATA = 1;            //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低i = 0;while (DATA)   //等待DS18B20拉低总线{i++;if(i>5)//等待>5MS{return 1;//初始化失败}delay15us();   }return 0;//初始化成功
}void Ds18b20WriteByte(unsigned char dat)
{unsigned int i = 0, j = 0;for (j=0; j<8; j++){DATA = 0;               //每写入一位数据之前先把总线拉低1usi++;DATA = dat & 0x01;   //然后写入一个数据,从最低位开始delay70us();            // 时序要求最少60usDATA = 1;             //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值dat >>= 1;}
}unsigned char Ds18b20ReadByte()
{unsigned char byte = 0, bi = 0;unsigned int i = 0, j = 0;for (j=8; j>0; j--){DATA = 0;        //先将总线拉低1usi++;DATA = 1;     //然后释放总线i++;i++;            //延时6us等待数据稳定bi = DATA;        //读取数据,从最低位开始读取/*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/byte = (byte >> 1) | (bi << 7);    //byte |= (bi << (8-j));delay45us();}                return byte;
}/*************** 高层时序 *************************************/void Ds18b20ChangTemp(void)
{Ds18b20Init();delay1ms();Ds18b20WriteByte(0xcc);       //跳过ROM操作命令      Ds18b20WriteByte(0x44);        //温度转换命令delay750ms();   //等待转换成功,而如果你是一直刷着的话,就不用这个延时了
}void Ds18b20ReadTempCom(void)
{   Ds18b20Init();delay1ms();Ds18b20WriteByte(0xcc);     //跳过ROM操作命令Ds18b20WriteByte(0xbe);  //发送读取温度命令
}void Ds18b20ReadTemp2(void)
{unsigned int temp = 0;unsigned char tmh, tml;double t = 0;Ds18b20ChangTemp();                //先写入转换命令Ds18b20ReadTempCom();          //然后等待转换完后发送读取温度命令tml = Ds18b20ReadByte();     //读取温度值共16位,先读低字节tmh = Ds18b20ReadByte();       //再读高字节
//  temp = tmh;
//  temp <<= 8;
//  temp |= tml;temp = tml | (tmh << 8);t = temp * 0.0625;uart_send_byte(0);uart_send_byte((unsigned char)t);return;
}void Ds18b20ReadTemp(void)
{unsigned int temp = 0;unsigned char tmh, tml;Ds18b20ChangTemp();              //先写入转换命令Ds18b20ReadTempCom();          //然后等待转换完后发送读取温度命令tml = Ds18b20ReadByte();     //读取温度值共16位,先读低字节tmh = Ds18b20ReadByte();       //再读高字节uart_send_byte(0);uart_send_byte(tml);uart_send_byte(tmh);return;
}

51单片机外设篇:DS18B20相关推荐

  1. 51单片机外设篇:点阵式LCD

    什么是LCD LCD(Liquid Crystal Display)俗称液晶. 液晶是一种材料,液晶这种材料具有一种特点:可以在电信号的驱动下液晶分子进行旋转,旋转时会影响透光性,因此我们可以在整个液 ...

  2. 51单片机外设篇:蜂鸣器

    蜂鸣器 蜂鸣器是一种将电信号转换为声音信号的器件,常用来产生设备的按键音.报警音等提示信号. 蜂鸣器按驱动方式可分为有源蜂鸣器和无源蜂鸣器: 有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发 ...

  3. 51单片机外设篇:数码管

    数码管简介 LED数码管:数码管是一种简单.廉价的显示器,是由多个发光二极管封装在一起组成"8"字型的器件.比如红绿灯. 单个数码管: 多个数码管: 这些引脚由对应的寄存器控制着, ...

  4. 学习笔记之51单片机键盘篇(非编码键盘与编码键盘、非编码键盘的扫描方式、独立键盘、矩阵键盘)

    这篇博文主要记录51单片机键盘篇(非编码键盘与编码键盘.非编码键盘的扫描方式.独立键盘.矩阵键盘.键盘消抖等)包含原理图.代码等 (一)基础补充 1.键盘的任务 2.键盘的识别 3.如何消除按键的抖动 ...

  5. 【Proteus仿真】51单片机汇编实现DS18B20+LCD1602显示

    [Proteus仿真]51单片机汇编实现DS18B20+LCD1602显示 Proteus仿真 汇编代码(.asm) ;**************************************** ...

  6. 【51单片机】DS1302+ DS18b20+LCD1602时钟仿真

    [51单片机]DS1302+ DS18b20+LCD1602时钟仿真 ✨演示效果 工程简介 DS1302提供实时时钟/日历和31字节的静态RAM,它经过一个简单的串行接口与微处理器通信,实时时钟/日历 ...

  7. 智慧农场,51单片机上实现DS18B20与YL69土壤湿度传感器,并将两个获取的数据在LCD上显示出来

    上一篇我说了我们做的是两个模块,但是介于DS18B20的资料太多,我就不再阐述,直接给最终的代码. 该代码是将温度传感器与YL69湿度传感器获取的数据在51单片机LCD上显示出来 #include & ...

  8. 51单片机外设系列:LCD1602 的详细编程

    前言,LCD1602是一个比较常用的单片机显示外设,下面我们从它的显示原理,来分析用51单片机编程的思路.另外结尾还提供了完成的程序代码参考. 一.LCD1602的外观.结构和基本参数 引脚功能解析: ...

  9. 51单片机定时器中断怎么用-------51单片机基础篇

    首先,什么时定时器,简单来说可以比喻为一个闹钟,当你把他打开以后,他就会每秒动一下,+1,+1,+1,+1,如果你设置了某一个时间点闹钟会向以后,那么当闹钟的时间点+1,+1,+1,+到了你设置的时间 ...

  10. 51单片机学习篇-- --红外通信(PPM脉时)笔记

    开篇先说一句废话···· 本旺名字叫萨摩耶,,Please 叫我旺财,,,哈哈,招财进宝嘛! 开篇 从学完帮网友写完<倒计时数字钟–矩阵按键可调>然后在CSDN上总结完之后,学习了剩下的模 ...

最新文章

  1. 数据蒋堂 | 怎样生成有关联的测试数据
  2. Java并发包中Lock的实现原理
  3. 世道变了!这个AI竞赛不再要刷榜成绩,直接看商业落地计划书
  4. PHP (20140519)
  5. 大剑无锋之介绍几个常见的网络协议且位于哪一层?【面试推荐】
  6. GraphQL支持层级结构的query
  7. MUI主界面菜单同时移动主体部分不出滚动条解决
  8. python3 最简单的实现 模版设计模式
  9. OS X 平台的 8 个终端实用工具
  10. 《TensorFlow 2.0深度学习算法实战教材》学习笔记(二、回归问题和分类问题)
  11. NodeJs——(14)express框架的send()方法简介
  12. 计算机考研数据结构参考书,2016计算机考研:数据结构参考书及其复习重点
  13. 水晶报表客户机电脑报错“CrystalDecisions.CrystalReports.Engine.ReportDocument”
  14. Pytorch 神经网络模型量化分析基本框架
  15. JavaScript实现网页截屏方法总结
  16. 简单的哈夫曼树程序实现
  17. 【Windows安装WSL】WSL中安装Ubuntu发行版,提示占位程序接收到错误数据
  18. 微信H5移动端真机调试--vConsole
  19. 长在火山熔岩石板地上的大米
  20. OSChina 程序员节乱弹 ——看程序员如何优雅地生活

热门文章

  1. 怎么用html实现QQ代挂功能,QQ等级每天有几种加速方式
  2. 怎样更改计算机ip,怎么快速修改电脑ip地址
  3. 通信电子电路实验(一)—— 高频小信号调谐放大器电路设计
  4. 广州技能入户计算机证书,广州技能入户申请的条件和工种有哪些
  5. 家庭宽带光猫改桥接模式教程-淇云博客
  6. minist数据集图片查看
  7. bi项目中数据仓库的维度表和事实表
  8. 26、python密度聚类方法(DBSCAN密度聚类)
  9. memtest86内存测试工具介绍
  10. ImageJ 插入插件和基本教程