DS18B20温度传感器——测试环境温度及代码

news/2024/11/29 23:42:03/

醒醒!,还在睡呢,开始干代码了!

1.简介:

单片机通过OneWire协议与DS18B20通信,最终测出环境温度

OneWire 总线的硬件接口很简单,只需要把 DS18B20 的数据引脚和单片机的一个 IO 口接上

2.DS18B20引脚及说明

 

 

 说明:GND接地,DQ单引线用于数据的输入,VDD接电源正极(注意正负极不能接反)

3.储存形式

通过编程,将二进制的数字来表示温度

 可以看出最高五位为符号位,若全为0则温度为正值,全为1则为负值

最后四位为小数位,最高可以精确到2的-4次方,可以知道每次变化最小变化值位0.0625

 例如+25.0625°C是

 1*2的-4次方+1*2的0次方+1*2的三次方+1*2的4次方

由于高五位都是0 所以最终结果是+25.0625°C;

二.各个模块的原理

2.1.初始化

在初始化阶段,总线控制器先拉低总线至少480微秒(这里可以拉低500微秒),然后释放总线

进入接收状态,等待 15-60us,然后发出一个由 60-240us低电平信号构成的存在脉冲。

unsigned char OneWire_Init()
{unsigned char i;unsigned char AckBit;OneWire_DQ=1;OneWire_DQ=0;i = 247;while (--i);		//Delay 500usOneWire_DQ=1;i = 32;while (--i);			//Delay 70usAckBit=OneWire_DQ;i = 247;while (--i);		//Delay 500usreturn AckBit;
}

先拉低,延时500微秒等待,再拉高,延时70微秒等待,然后把应答位取出来,再延时500微秒返回应答位,0位应答,1为非应答

这里延时多少可以去用软件来生成代码

2.2.写时序

有两种写时序:写 1 时序和写 0 时序,总线控制器通过写 1 时序写逻辑 1 到DS18B20,写 0 时序写逻辑 0 到 DS18B20,所有写时序必须最少持续 60us

1.发送一位

void OneWire_SendBit(unsigned char Bit)
{unsigned char i;OneWire_DQ=0;i = 4;while (--i);			//Delay 10usOneWire_DQ=Bit;i = 24;while (--i);			//Delay 50usOneWire_DQ=1;
}

 先把总线拉低,延迟10微秒,将bit赋值给DQ(把要发送的数据即bit放在总线上,发0即保持低电平,发1即变成高电平),然后延时50us,最后释放总线;

这里十分巧妙,给的数据是0的话就是0,不拉高总线,是1的话会拉高,延时50us后看变化如果是低电平说明发送的是0,高电平发送1,最后把总线拉高,这里10+50刚好等于60 满足最小的60us

                             2.发送一个字节(一字节也就是八位)

将上述情况重复八次就好

void OneWire_SendByte(unsigned char Byte)
{unsigned char i;for(i=0;i<8;i++){OneWire_SendBit(Byte&(0x01<<i));}
}

从低到高依次将Byte的每一位取出来。(一般取数据用&,将某个数据置1用 | )

2.3.读时序

总线控制器发起读时序时,DS18B20 仅被用来传输数据给控制器。因此,总线控制器在发出读暂存器指令[BEh]或读电源模式指令[B4H]后必须立刻开始读时序。

2.3.1接收(读)一位:

主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us末尾,这样成功的概率高) 读取为低电平则为

接收0,读取为高电平则为接收1,整个时间片应大于60us

 

unsigned char OneWire_ReceiveBit()
{unsigned char i;unsigned char Bit;OneWire_DQ=0;i = 2;while (--i);			//Delay 5usOneWire_DQ=1;i = 2;while (--i);			//Delay 5usBit=OneWire_DQ;i = 24;while (--i);			//Delay 50usreturn Bit;
}

先拉低总线5us,再释放总线5us(此时控制权交给从机),现在时序到了10us,如果读取的数据是0,那么从机就强制拉低总线,如果读取到的数据是1,那就维持高电平,再延时50us满足时序需求.

2.3.2接收(读)一个字节:

和发送一个字节一样

将接收一位重复八次

unsigned char OneWire_ReceiveByte()
{unsigned char i;unsigned char Byte=0x00;for(i=0;i<8;i++){if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}}return Byte;
}

这里定义一个Byte返回值初值为0x00,然后用Byte按位或0x01(从低位到高位)就可以得到Byte了.

上述的发送一位,一个字节;接收一位,一个字节,可以封装到一个文件中,起名为OneWire

下面是OneWire.c

#include <REGX52.H>sbit OneWire_DQ=P3^7;unsigned char OneWire_Init()
{unsigned char i;unsigned char AckBit;OneWire_DQ=1;OneWire_DQ=0;i = 247;while (--i);		//Delay 500usOneWire_DQ=1;i = 32;while (--i);			//Delay 70usAckBit=OneWire_DQ;i = 247;while (--i);		//Delay 500usreturn AckBit;
}void OneWire_SendBit(unsigned char Bit)
{unsigned char i;OneWire_DQ=0;i = 4;while (--i);			//Delay 10usOneWire_DQ=Bit;i = 24;while (--i);			//Delay 50usOneWire_DQ=1;
}unsigned char OneWire_ReceiveBit()
{unsigned char i;unsigned char Bit;OneWire_DQ=0;i = 2;while (--i);			//Delay 5usOneWire_DQ=1;i = 2;while (--i);			//Delay 5usBit=OneWire_DQ;i = 24;while (--i);			//Delay 50usreturn Bit;
}void OneWire_SendByte(unsigned char Byte)
{unsigned char i;for(i=0;i<8;i++){OneWire_SendBit(Byte&(0x01<<i));}
}unsigned char OneWire_ReceiveByte()
{unsigned char i;unsigned char Byte=0x00;for(i=0;i<8;i++){if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}}return Byte;
}

下面是OneWire.h

#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__
unsigned char OneWire_Init();
void OneWire_SendBit(unsigned char Bit);
unsigned char OneWire_ReceiveBit();
void OneWire_SendByte(unsigned char Byte);
unsigned char OneWire_ReceiveByte();#endif

接下来是DS18B20的

ConverT():发送指令,跳过ROM,温度变换

然后是读取温度,在读取函数里面发送完两条指令后,控制权交给从机

这里数据处理比较难理解

剖析:TLSB为第八位,TMSB为高八位

Temp=(TMSB<<8)|TLSB;//将高八位左移八位,把数据整合成16位的;

最后还要把Temp/16

为什么要除以16呢?

这里还是看上面存储形式的那张图片,最低四位为小数位,但是我们整合出来的Temp最低四位是整数位,那么我们只需将Temp右移动4位即可,在二进制里面向右移动一位相当于 /2,那么向右移四位就是 /16了。

#include <REGX52.H>
#include "OneWire.h"#define DS18B20_SKIP_ROM			0xCC
#define DS18B20_CONVERT_T			0x44
#define DS18B20_READ_SCRATCHPAD 	0xBE
void DS18B20_ConvertT()
{OneWire_Init();OneWire_SendByte(DS18B20_SKIP_ROM);OneWire_SendByte(DS18B20_CONVERT_T);
}float DS18B20_ReadT()
{unsigned char TLSB,TMSB;int Temp;float T;OneWire_Init();OneWire_SendByte(DS18B20_SKIP_ROM);OneWire_SendByte(DS18B20_READ_SCRATCHPAD);TLSB=OneWire_ReceiveByte();TMSB=OneWire_ReceiveByte();Temp=(TMSB<<8)|TLSB;T=Temp/16.0;return T;
}
#ifndef __DS18B02_H__
#define __DS18B02_H__void DS18B20_ConvertT();
float DS18B20_ReadT();#endif

最后是主函数测试,这里要用到LCD1602显示屏

#include <REGX52.H>
#include "LCD1602.h"
#include "DS18B02.h"
#include "Delay.h"float T;void main()
{DS18B20_ConvertT();		Delay(1000);			LCD_Init();LCD_ShowString(1,1,"Temperature:");while(1){DS18B20_ConvertT();	T=DS18B20_ReadT();	if(T<0)				{LCD_ShowChar(2,1,'-');	T=-T;			}else				{LCD_ShowChar(2,1,'+');	}LCD_ShowNum(2,2,T,3);		LCD_ShowChar(2,5,'.');		LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);}
}

逻辑全在代码里面了,容易体会,要注意最后

         LCD_ShowNum(2,2,T,3);        
        LCD_ShowChar(2,5,'.');        
        LCD_ShowNum(2,6,(unsigned long)(T*10000)%10000,4);//这里

温度要想显示出四位小数无误,要将float强转为long类型的,但是又不能直接转

所以我们先将整数部分取出显示出来,然后将T*10000%10000就可以取出小数部分了

这里就是DS18B20的基本内容了,还可以实现报警等等功能,在此基础上稍作修改即可,

精心摸鱼(hhh)

 


http://www.ppmy.cn/news/645295.html

相关文章

计算机温度压力测试,整机性能与温度压力测试

整机性能与温度压力测试 神舟战神Z8标配了一块1080P高清屏幕&#xff0c;比较反常的是&#xff0c;这块屏幕采用了蓝天系神舟产品较少采用的镜面面板。 面板信息 Z8屏幕可视角度良好 这款面板来自三星&#xff0c;型号为SDC4952&#xff0c;广大准系统玩家可能对这款面板较为熟…

多点温度测试

DS18B20温度传感器 一、简介&#xff1a; 图示有字的一面&#xff0c;注意GND和VCC不要接反。工作电压3.0v~5.5V&#xff0c;采集温度-55度到正125度&#xff0c;可编程温度9-12位&#xff0c;精度分别是0.5度&#xff0c;0.25度&#xff0c;0.125度0.0625度&#xff0c;默认都…

测一测现在的温度

测一测现在的温度 目录 测一测现在的温度一、Hello World二、使用DHT11测温 我们使用Mongoose OS esp8266 DHT11来做。 Mongoose OS&#xff1a;一个物联网固件开发框架。官方文档 esp8266&#xff1a;ESP8266是一款串口WiFi模块。 DHT11&#xff1a;一个温度传感器。 固件…

【SA8295P 源码分析】33 - Android GVM USB 透传配置

【SA8295P 源码分析】33 - Android GVM USB 透传配置 1. Android 端配置 dts:以配置 USB1 为例2. QNX 端配置 linux-la.config:以配置 USB1 为例3. 在Android shell 中配置USB0 / USB1 的 Host/device 模式切换系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》…

记录一次 vite 配置别名路径 打包时出错的bug

vite多页应用,由于在vite.config.ts中define中配置的常量pages,而路径别名也有pages,所有导致打包时替换路径出错,将pages常量注释掉就好了 export default defineConfig({root: getRoot(), // 项目根路径base: "/", // 公共基础路径envDir: resolve(__dirname), /…

雷神科技c++qt面试

一面 &#xff08;30min&#xff09;&#xff1a; 应该是研发的负责人 腾讯出来的 问了一些项目 然后c的知识 malloc 与 new 区别 指针与引用区别 喜欢用指针还是引用作为参数的出参 哪些场景只能用指针作为参数 udp 与 tcp 区别 如果用udp 怎么实现类似tcp一样的稳定传输 排序…

SpringBoot入门-源码解析(雷神)

一、Spring Boot入门 视频学习资料(雷神)&#xff1a; https://www.bilibili.com/video/BV19K4y1L7MT?p1 github: https://github.com/12722097458/springboot-20220403.git1、Spring Boot简介 简化Spring的一个框架&#xff1b; 是整个Spring技术栈的一个整合&#xff1b; 是…

雷神Springboot2笔记

1. 启动一个springboot项目 创建maven工程 在pom中引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId> </dependency>创建主程序 /*** 主程序类* SpringBootApplicatio…