ds18b20温度转换指令_使用STM32控制DS18B20温度传感器
前言
温度传感器是各种传感器中最常用的一种,在做项目时经常会需要测量当前的温度,而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
更多推荐
所有评论(0)