前言

温度传感器是各种传感器中最常用的一种,在做项目时经常会需要测量当前的温度,而DS18B20采用单总线协议,即与单片机借口仅需占用一个I/O端口,无需任何外部元件,仅需要一个上拉电阻,即可将外部环境温度以数字码的方式串行输出,从而大大简化了传感器与微处理器的接口,且DS18B20提供了9—12位的可编程分辨率为9—12位对应的可分辨温度分别为0.5°C,0.25°C,0.125°C,0.0625°C,其转化速率随着温度分辨率的增加而减少。并且DS18B20的测温范围在-55°C~+125°C满足了大部分基本的项目需求。

一、DS18B20的基本读写初始化时序操作

1 初始化操作

单片机先将DQ引脚拉至低电平480—960us发送一个低电平脉冲(复位)之后释放总线由上拉电阻将引脚上拉至高电平持续等待15—60us之后将单片机引脚转为输入模式检查DS18B20是否做出应答,若DS18B20存在,则会将总线拉低60—240us将DQ引脚拉低做出应答

2 写数据操作

DS18B20的写周期最少为60us最长不能超过120us,DS18B20写0时序与写1时序类似,在写0时序中单片机需要将DQ引脚拉低之后DS18B20会在引脚被拉低的第15—60us内进行采样读取到写0的操作,而对DS18B20进行写1操作需要单片机先将引脚拉低至低电平1us的时间之后将总线释放由上拉电阻将总线拉直高电平,DS18B20则会在第15—60us内读取到写1操作

3 读数据操作

由时序图可知读操作最短时间为60us最长不超过120us,DS18B20读操作开始时单片机需要将DQ引脚拉低至少1us的时间后将总线释放,在总线释放期间,若DS18B20发送0,则把总线拉低至少到15us,之后释放总线,若发送1,则不拉低总线,单片机需要在读周期开始后的15us内读取引脚的电平大小,之后释放总线45us完成时序

二、DS18B20的ROM指令和存储器指令

在完成对DS18B20的初始化后要对DS18B20进行操作,而DS18B20的指令可根据作用对象可分为ROM指令和存储器指令,前者可通过ROM指令选择所需操作的DS18B20,后者是对所选的DS18B20进行温度读取,转换等具体操作。

1,ROM指令

因为DS18B20的光刻ROM(地址)各不相同,如果在项目中如果需要同时操作多个DS18B20,则需要根据ROM指令对DS18B20进行选择

多个DS18B20: 当单片机上挂载了多个DS18B20,需要对某个进行单独操作时需要先将主机逐个与DS18B20连接,独处其序列号,然后再将所有的DS18B20挂载到总线上,之后由单片机发出匹配ROM指命令(55H)。紧接着单片机提供64位序列(包括该DS18B20的48位序列号)之后的操作就是对该DS18B20进行操作

单个DS18B20:如果单片机上仅挂载了一个DS18B20仅需要发送跳过ROM指令(CCH)命令即可,不需要进行读取ROM编码以及匹配ROM编码。

2,存储器指令

高速暂存器RAM

在存储器指令中最常用的是温度转换指令(44H)和读暂存器指令(BEH)。在每次读取温度前都需要对DS18B20发送温度转换指令,它会将获取的温度转换为数字存储在告诉暂存器ROM中的第0和第1的字节中,转换速度由分辨温度的精度限制,最快93.75ms。在温度转换完毕后通过读暂存器(BEH)读取高速存储器RAM中的数据,读取第0和第1字节即可。

温度数据存储格式

DS18B20在刚出厂时默认的配置为12位,即可分辨温度为0.0625.其中第11到第15位为符号位,0为正,1为负。因为在温度数据中第0位到第3位为小数位,所以在进行温度转换时若温度为负数需要先将数据取反在进行加1后再乘以0.0625得到实际温度,若为正数可直接乘以0.0625获得实际温度。

三、DS18B20改变高温报警和低温报警以及温度分辨位数

要改变DS18B20的高温报警,低温报警以及温度分辨位数需要通过写暂存器指令(4EH)来对高速暂存器RAM的第2,3,4位进行编写。

其中TH和TL寄存器的第七位为符号位S=0为正为1为负。

而配置寄存器中可通过改变R1和R0的值来改变DS18B20的测温精度。

R1 R0 分辨率 温度最大转换时间

0 0 9位 93.75ms

0 1 10位 187.5ms

1 0 11位 375ms

1 1 12位 750ms

四、向DS18B20写命令操作的基本步骤

1 写指令顺序

根据上图可知,在对DS18B20进行功能指令时必须先对DSS18B20进行初始化和ROM指令,如果只有一个DS18B20ROM指令可用跳过ROM(CCH),之后在进行存储器操作。

五、DS18B20操作的源代码

#include "obj_ds18b20.h"

int DS18B20_Init(void)

{

int i=0;

RCC->APB2ENR|=(1<<3);//打开GPIOB使能

GPIOB->ODR |= 1<<8; //GPIOB-8输出高电平

DS18B20_Mode_OutPut();//令DQ口为输出模式

PBout(8)=0;

delay_us(720);//延时480-960us

PBout(8)=1;

delay_us(30);//等待15-60us

DS18B20_Mode_InPut();//改为输入模式

while(PBin(8)==1) //若DS18B20存在则会将总线拉低60-240us

{

delay_us(1);

i++;

if(i>240) return 0; //时间大于240us总线仍为高电平则DS18B20不存在

}

return 1;

}

void DS18B20_WriteByte(uint8_t dat)

{

int i;

DS18B20_Mode_OutPut();

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

{

PBout(8)=0; //先拉低引脚

delay_us(15); //等待15us,在第15-60us内DS18B20会获取总线电平

PBout(8)=dat&0x01;

delay_us(60); //延时,使时序图完整

PBout(8)=1;

dat>>=1;

}

}

uint8_t DS18b20_ReadByte(void)

{

int j;

uint8_t dat,byte;

for(j=8;j>0;j--)

{

DS18B20_Mode_OutPut();

PBout(8)=0; //先拉低引脚

delay_us(1); //延时至少大于1us

PBout(8)=1; //释放总线

delay_us(10); //DS18B20会在15us发送数据

DS18B20_Mode_InPut();

dat=PBin(8);

byte=(byte>>1)|(dat<<7);

delay_us(45); //使时序完整

DS18B20_Mode_OutPut();

PBout(8)=1;

}

return byte;

}

/*改变DS18B20的高温报警和低温报警以及分辨率*/

void DS18B20_Resolving_Temp(void)

{

DS18B20_Init();//单片机每次向DS18B20发送功能指令前都需要重新初始化DS18B20和写ROM指令

delay_ms(1);

DS18B20_WriteByte(0xcc);

DS18B20_WriteByte(0xbe);//高温报警的上限

DS18B20_WriteByte(0x00);//低温报警的下限

DS18B20_WriteByte(0x7f);//改变温度分辨率

}

/*进行温度转化*/

void Ds18b20ChangeTemp(void)

{

DS18B20_Init();

delay_ms(1);

DS18B20_WriteByte(0xcc);//跳过ROM

DS18B20_WriteByte(0x44);//发送指令RAM温度变换

}

/*读取温度*/

void Ds18b20ReadTempCom(void)

{

DS18B20_Init();

delay_ms(1);

DS18B20_WriteByte(0xcc);//跳过ROM

DS18B20_WriteByte(0xbe);//发送指令RAM读暂时寄存器

}

int Ds18b20ReadTemp(void)

{

int temp;

float fp;

uint8_t tml,tmh;

DS18B20_Resolving_Temp();//改变高温报警和低温报警以及温度的分辨率

Ds18b20ChangeTemp();//进行温度转换

Ds18b20ReadTempCom();//读取温度

tml=DS18b20_ReadByte();//读低8位数据

tmh=DS18b20_ReadByte();//读高8位数据

temp=tmh;

temp<<=8;

temp|=tml;//拼接为16位数据

fp = temp;

if(temp < 0)//DS18B20存储数据为补码形式,当temp<0时需要转为原码

{

temp = ~temp;

temp += 1;

}

temp = fp*0.0625*10+0.5;//根据获得的温度所需的小数而改变,如果保留2位小数则乘100,+0.5是为了四舍五入

return temp;//返回数据

}

}

//头文件部分

#ifndef _OBJ_DS18B20_H

#define _OBJ_DS18B20_H

#include "stm32f10x.h"

#include "sys.h"

//因为DS18B20是单总线,只靠一根线获取和输出数据,所以要不停的切换模式

#define DS18B20_Mode_OutPut() {GPIOB->CRH &= 0xFFFFFFF0;GPIOB->CRH |= 0x00000003;}//输出模式

#define DS18B20_Mode_InPut() {GPIOB->CRH &= 0xFFFFFFF0;GPIOB->CRH |= 0x00000008;}//输入模式

int DS18B20_Init(void);//DS18B20的初始化

int Ds18b20ReadTemp(void);//DS18B20读取温度

#endif

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐