温度范围:-55℃到125℃
默认12位精度,0.0625℃一格

因为网上很多ds18b20的中文资料,我只说一下最不容易理解的几个点。代码再最后

单总线通信。数据什么的都在一根线上传输。
读写时序为什么一样?因为在读写之前要先发命令。比如先发一个0x44,就是启动温度转换,然后发送0xbe,再读数据。温度转换后温度数据被放在ram中的第1.2字节,掉电丢失,芯片复位不丢失。所以执行一次温度转换,可以读好几次。不过记住,每次发送命令之前都要执行复位函数,再发命令。温度的2字节和配置可以放入eeprom中,不过目前没啥用。
出场默认精度12位,11位数据1位符号。剩下4位随着符号位变化。

在执行完ROM操作命令后,我们需要进行的就是RAM操作命令,我们先来认识一下高速暂存RAM。暂存器由9个字节组成。

第1第2两个字节包含测得温度信息,温度传感器(温度灵敏元件)测得的温度值被存储到高速暂存器的这两个字节(温度寄存器)。
以12位精度存储温度,最高位为符号位,负温度S=1,正温度S=0。将存储器中的二进制数求补再转换成十进制数乘以精度(0.5、0.25、0.0625)就得到被测温度值。如0550H为+85℃,0191H为
+25.0625℃,FC90H为-55℃,上电初始为+85℃。第3和第4个字节是 TH 和 TL 的易失性拷贝(从EEPROM拷贝到高速暂存器这两个字节),在每一次上电复位时被刷新;

第5个字节是配置寄存器,如图,用户可按照“温度计精确度配置”表,来修改R1R2的值,来设定DS18B20的精度,上电默认设置R1R0=11(12位精度),配置寄存器的其他为均保留,禁止写入;
第6、7、8字节被保留,禁止写入;
第9个字节是只读的,包含以上八个字节的CRC码;

再看一下RAM操作指令(功能指令)
在发送ROM操作指令后,下一步需要进行RAM操作指令。这些指令允许总线控制器读写DS18B20的暂存器,发起温度转换和识别电源模式。DS18B20的功能指令详见下文。
CONVERTT [44h] (温度转换指令)
这条命令用以启动一次温度转换。温度转换指令被执行,产生的温度转换结果数据以2个字节的形式被存储在高速暂存器中,而后DS18B20保持等待状态。如果寄生电源模式下发出该命令后,在温度转换期间(tconv),必须在10us(最多)内给单总线一个强上拉。如果DS18B20以外部电源供电,总线控制器在发出该命令后跟着发出读时序,DS18B20如处于转换中,将在总线上返回 0,若温度转换完成,则返回 1。寄生电源模式下,总线被强上拉拉高前这样的通讯技术不会被使用。
WRITESCRATCHPAD [4Eh] (写暂存器指令)
这条命令向 DS18B20 的暂存器写入数据,开始位置在 TH 寄存器(暂存器的第 2个字节),接下来写入 TL 寄存器(暂存器的第 3 个字节),最后写入配置寄存器(暂存器的第 4 个字节)。数据以最低有效位开始传送。上述三个字节的写入必须发生在总线控制器发出复位命令前,否则会中止写入。
写是往2.3.4个字节里依次写数据。

这个配置寄存器里只有两个能改动,R1R0;

所以这样写就行,先把前两个给他添上,再接着写命令就可以写到配置寄存器里

         DS18B20Write(0x4e);         //写暂存器指令4EDS18B20Write(0x4b);           //写高速缓存器TH高温限值75度DS18B20Write(0x00);            //写高速缓存器TL低温限值0度DS18B20Write(0x1f); //0x1f : 0.5000°C  转换时间93.75ms//0x3f : 0.2000°C  转换时间187.5ms//0x5f : 0.1250°C  转换时间375ms//0x7f : 0.0625°C  转换时间750ms

接下来是一些命令,有的前面带0是打错了,不用看第一个0

每一次读写之前都要对 DS18B20 进行复位,复位成功后发送一条 ROM 指令,最后发送 RAM 指令,这样才能对 DS18B20 进行预定的操作。

温度报警虽然用不上,但是还是写一下,因为我们一般再外部控制,判断温度是否超标


下面是一些详细的,有了解可以不看

推挽电路和漏极开路的帖子:
https://www.zhihu.com/question/28512432
https://blog.csdn.net/u012604283/article/details/84647237


代码开始

ds18b20.c

#include "ds18b20.h"
#include "public.h"uchar ds18b20Init(void)
{uchar i=0;DATA=0;delay700us();DATA=1;delay100us();while(DATA){if(i>=5){return 0;}i++;}return 1;
}void writeByte(uchar dat)
{uchar i;DATA=0;delay4us();for(i=0;i<8;i++){DATA=0;delay4us();DATA=dat&0x01;delay60us();DATA=1;dat>>=1;}
}uchar readByte()
{uchar i,dat=0;uchar da=0;for(i=0;i<8;i++){DATA=0;_nop_();DATA=1;delay4us();da=DATA;da<<=7;dat=(dat>>1)|da;delay60us();}return dat;
}void changeTemp()
{ds18b20Init();delay700us();writeByte(0xcc);writeByte(0x44);delay1s();
}void readTempCommand()
{ds18b20Init();delay700us();writeByte(0xcc);writeByte(0xbe);
}int readTemp()
{int dat=0;uchar tmh, tml;changeTemp();readTempCommand();tml = readByte();        //读取温度值共16位,先读低字节tmh = readByte();dat=tmh;dat<<=8;dat|=tml;return dat;
}

ds18b20.h

#ifndef __DS18B20_H_
#define __DS18B20_H_#include "public.h"
sbit DATA=P3^7;uchar ds18b20Init(void);
void writeByte(uchar dat);
uchar readByte();
void changeTemp();
void readTempCommand();
int readTemp();#endif

main.c

#include "uart.h"
#include "public.h"
#include "ds18b20.h"void main()
{int dat;int    DAT;uchar ge,shi,bai,qian;uart_init();while(1){dat=readTemp();if(dat>0){DAT=dat*6.25+0.5;qian=(uchar)(DAT/1000);bai=(uchar)(DAT/100%10);shi=(uchar)(DAT/10%10);ge=(uchar)(DAT%10);uart_send_sentence("now, the temperature is :");uart_send_byte('0'+qian);uart_send_byte('0'+bai);uart_send_byte('.');uart_send_byte('0'+shi);uart_send_byte('0'+ge);uart_send_byte('\r');uart_send_byte('\n');}else{dat=dat-1;dat=~dat;DAT=dat*0.0625*100+0.5;  qian=(uchar)(DAT/1000);bai=(uchar)(DAT/100%10);shi=(uchar)(DAT/10%10);ge=(uchar)(DAT%10);uart_send_byte('-');uart_send_byte('0'+qian);uart_send_byte('0'+bai);uart_send_byte('0'+shi);uart_send_byte('0'+ge);}delay1s() ;  //误差 0us}
}/* uchar i;i=ds18b20Init();while(1){if(i==1)uart_send_byte('y');elseuart_send_byte('n');delay();}
*/

uart.c

#include "uart.h"
#include "public.h"// 串口设置为: 波特率9600、数据位8、停止位1、奇偶校验无
// 使用的晶振是11.0592MHz的,注意12MHz和24MHz的不行
void uart_init(void)
{// 波特率9600SCON=0X50;          //设置为工作方式1TMOD=0X20;           //设置计数器工作方式2PCON=0X80;         //波特率加倍TH1=0XF3;               //计数器初始值设置,注意波特率是4800的TL1=0XF3;//ES=1;                     //打开接收中断//EA=1;                        //打开总中断TR1=1;
}// 通过串口发送1个字节出去
void uart_send_byte(unsigned char c)
{// 第1步,发送一个字节SBUF = c;// 第2步,先确认串口发送部分没有在忙while (!TI);// 第3步,软件复位TI标志位TI = 0;
}void uart_send_sentence(unsigned char *sen)
{while(*sen!='\0'){uart_send_byte(*sen);sen++;}
}

uart.h

#ifndef __UART_H__
#define __UART_H__void uart_init(void);
void uart_send_byte(unsigned char c);
void uart_send_sentence(unsigned char *sen);#endif

public.c

#ifndef __PUBLIC_H__
#define __PUBLIC_H__#include <reg51.h>
#include <intrins.h>#ifndef uchar
#define uchar unsigned char
#endif#ifndef uint
#define uint unsigned int
#endifvoid delay700us(void) ;  //误差 0us
void delay100us(void) ;  //误差 0us
void delay4us(void);   //误差 0us
void delay60us(void) ;  //误差 0us
void delay1s(void) ;  //误差 0us#endif

public.h

#include "public.h"void delay700us(void)   //误差 0us
{unsigned char a,b;for(b=41;b>0;b--)for(a=7;a>0;a--);
}void delay100us(void)   //误差 0us
{unsigned char a,b;for(b=1;b>0;b--)for(a=47;a>0;a--);
}void delay4us(void)   //误差 0us
{_nop_();  //if Keil,require use intrins.h_nop_();  //if Keil,require use intrins.h
}
void delay60us(void)   //误差 0us
{unsigned char a,b;for(b=3;b>0;b--)for(a=8;a>0;a--);
}
void delay1s(void)   //误差 0us
{unsigned char a,b,c;for(c=167;c>0;c--)for(b=171;b>0;b--)for(a=16;a>0;a--);_nop_();  //if Keil,require use intrins.h
}

单片机常用芯片系列(二)——DS18B20详解相关推荐

  1. 【arduino】常用芯片ATMEGA328P-AU 32TQFP资料详解

    使用高速的微处理控制器(ATMEGA328),开发操作界面和环境都非常简单.易理解,非常适合初学者学习. 性能描述  I/O 数字输入/输出端共 0~13.  I/O 模拟输入/输出端共 0~5. 支 ...

  2. RxJS 系列之二 - Observable 详解

    查看新版教程,请访问前端修仙之路 RxJS 系列目录 RxJS 系列之一 - Functional Programming 简介 RxJS 系列之二 - Observable 详解 (本文) RxJS ...

  3. DFT - 对芯片测试的理解(二) 详解

    DFT - 对芯片测试的理解(二) 详解 参考: https://www.docin.com/p-2014360649.html The basic view of DFT scan chain 这图 ...

  4. Android自定义控件系列八:详解onMeasure()(二)--利用onMeasure测量来实现图片拉伸永不变形,解决屏幕适配问题

    上一篇文章详细讲解了一下onMeasure/measure方法在Android自定义控件时的原理和作用,参看博文:Android自定义控件系列七:详解onMeasure()方法中如何测量一个控件尺寸( ...

  5. Docker系列07—Dockerfile 详解

    Docker系列07-Dockerfile 详解 1.认识Dockerfile 1.1 镜像的生成途径 基于容器制作  dockerfile,docker build 基于容器制作镜像,已经在上篇Do ...

  6. 单片机控制两个步进电机画圆_基于单片机的步进电机转速控制设计详解(附程序)...

    步进电机是将电脉冲信号转变为角位移或线位移的开环控制元件.在非超载的情况下,电机的转速.停止的位置只取决于脉冲信号的频率和脉冲数,而不受负载变化的影响,即给电机加一个脉冲信号,电机则转过一个步距角.这 ...

  7. 十二、详解计算网络中的流量控制和差错控制、HDLC

    十二.详解计算网络中的流量控制和差错控制 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动 ...

  8. mongo 3.4分片集群系列之六:详解配置数据库

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  9. python中common在哪个模块导入_python的常用模块之collections模块详解

    认识模块 什么是模块? 常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀. 但其实import加载的模块分为四个通用类别: 1 使用python编写的 ...

  10. React Native按钮详解|Touchable系列组件使用详解

    转载自:http://www.devio.org/2017/01/10/React-Native按钮详解-Touchable系列组件使用详解/ 在做App开发过程中离不了的需要用户交互,说到交互,我们 ...

最新文章

  1. zxing 源码笔记
  2. Extjs4 MVC 示例
  3. 开工大吉!送你一份「远程工作约定」
  4. brew更新的时候不更新某个应用_这样用 Git 想不升职加薪都难!
  5. 牛客多校2 - Just Shuffle(置换群的幂)
  6. P1272 重建道路
  7. atitit.软件设计模式大的总结attialx总结
  8. jsp企业员工请假管理系统
  9. 大厂的激励,员工们不买账了
  10. [BZOJ2286] [Sdoi2011]消耗战
  11. 深度学习之车牌识别(中国、越南)
  12. Windows7下新建记事本的四种编码方式
  13. HashMap的实现原理(简要概述)
  14. 王阳明心学层级图——适合内心困惑的人了解
  15. 开个新栏目,起个恬淡的名字
  16. Linux如何解决root用户Operation not permitted
  17. java font 像素_字体的FontSize(pt)和像素(px)的关系
  18. 今有兽,六首四足;禽,四首二足,上有七十六首,下有四十六足。问:禽、兽各几何?...
  19. 阿里云OSS存储服务器
  20. 011、控制文件作用与管理

热门文章

  1. Docker部署ElasticSearch
  2. 使用Java将中文转化为拼音
  3. Compose Modifier
  4. 《30岁前每一天》 读书心得体会
  5. 图像分类经典卷积神经网络—SENet论文翻译(中英文对照版)—Squeeze-and-Excitation Networks(挤压和激励网络)
  6. 开源高手推荐 十大最流行开源软件
  7. 苹果怎么用计算机,苹果笔记本怎么用(苹果电脑Mac 系统基本操作介绍)
  8. 他发现了古老疟疾背后的元凶,也在质疑声中开创了致病生物的新时代
  9. 嵌入式MRZ机读码OCR识别电子护照阅读器模块|模组安装与测试注意事项
  10. 上传文件到服务器太大怎么办,超大文件怎么上传到云服务器