一、介绍
DS18B20是一种常见的数字型温度传感器,具备独特的单总线接口方式。其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点。
传感器参数
测温范围为-55℃到+125℃,在-10℃到+85℃范围内误差为±0.4°。
返回16位二进制温度数值
主机和从机通信使用单总线,即使用单线进行数据的发送和接收
在使用中不需要任何外围元件,独立芯片即可完成工作。
掉电保护功能 DS18B20 内部含有 EEPROM ,通过配置寄存器可以设定数字转换精度和报警温度,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。
每个DS18B20都有独立唯一的64位-ID,此特性决定了它可以将任意多的DS18b20挂载到一根总线上,通过ROM搜索读取相应DS18B20的温度值
宽电压供电,电压2.5V~5.5V
DS18B20返回的16位二进制数代表此刻探测的温度值,其高五位代表正负。如果高五位全部为1,则代表返回的温度值为负值。如果高五位全部为0,则代表返回的温度值为正值。后面的11位数据代表温度的绝对值,将其转换为十进制数值之后,再乘以0.0625即可获得此时的温度值。
传感器引脚及原理图
DS18B20传感器的引脚及封装图如下:
DS18B20一共有三个引脚,分别是:
GND:电源地线
DQ:数字信号输入/输出端。
VDD:外接供电电源输入端。
程序设计
将读取得到的温湿度数据同时在OLED上显示
DS18B20.C
#include "ds18b20.h"
/****************************************************************************
函数名:delay_us
功能:微秒级延时
输入:延时数据
输出:无
返回值:无
备注:
****************************************************************************/
void delay_us(uint32_t time)
{
time *= 10;
while(time)
time--;
}
/****************************************************************************
函数名:DS18B20_IO_IN
功能:使DS18B20_DQ引脚变为输入模式
输入:无
输出:无
返回值:无
备注:DQ引脚为PA5
****************************************************************************/
void DS18B20_IO_IN(void){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/****************************************************************************
函数名:DS18B20_IO_OUT
功能:使DS18B20_DQ引脚变为推挽输出模式
输入:无
输出:无
返回值:无
备注:DQ引脚为PA5
****************************************************************************/
void DS18B20_IO_OUT(void){
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB,&GPIO_InitStructure);
}
/***************************************************************************
函数名:DS18B20_Rst
功 能:发送复位信号
输 入: 无
输 出:无
返回值:无
备 注:
***************************************************************************/
void DS18B20_Rst(void){
DS18B20_IO_OUT();//引脚输出模式
//拉低总线并延时750us
DS18B20_DQ_OUT_LOW;
delay_us(750);
//释放总线为高电平并延时等待15~60us
DS18B20_DQ_OUT_HIGH;
delay_us(15);
}
/***************************************************************************
函数名:DS18B20_Check
功 能:检测DS18B20返回的存在脉冲
输 入: 无
输 出:无
返回值:0:成功 1:失败 2:释放总线失败
备 注:
***************************************************************************/
uint8_t DS18B20_Check(void){
//定义一个脉冲持续时间
uint8_t retry = 0;
//引脚设为输入模式
DS18B20_IO_IN();
while(DS18B20_DQ_IN && retry < 200){
retry++;
delay_us(1);
}
if(retry >= 200)
return 1;
else
retry = 0;
//判断DS18B20是否释放总线
while(!DS18B20_DQ_IN && retry < 240){
retry++;
delay_us(1);
}
if(retry >= 240)
return 2;
return 0;
}
/***************************************************************************
函数名:DS18B20_Write_Byte
功 能:向DS18B20写一个字节
输 入: 要写入的字节
输 出:无
返回值:无
备 注:
***************************************************************************/
void DS18B20_Write_Byte(uint8_t data){
uint8_t j;
uint8_t databit;
DS18B20_IO_OUT();
for(j=1;j<=8;j++){
databit=data&0x01;//取数据最低位
data=data>>1; //右移一位
if(databit){ //当前位写1
DS18B20_DQ_OUT_LOW;
delay_us(2);
DS18B20_DQ_OUT_HIGH;
delay_us(60);
}else{ //当前位写0
DS18B20_DQ_OUT_LOW;
delay_us(60);
DS18B20_DQ_OUT_HIGH;
delay_us(2);
}
}
}
/***************************************************************************
函数名:DS18B20_Read_Bit
功 能:向DS18B20读一个位
输 入: 无
输 出:无
返回值:读入数据
备 注:
***************************************************************************/
uint8_t DS18B20_Read_Bit(void){
uint8_t data;
DS18B20_IO_OUT();
DS18B20_DQ_OUT_LOW;
delay_us(2);
DS18B20_DQ_OUT_HIGH;
DS18B20_IO_IN();
delay_us(12);
if(DS18B20_DQ_IN)
data = 1;
else
data = 0;
delay_us(50);
return data;
}
/***************************************************************************
函数名:DS18B20_Read_Byte
功 能:向DS18B20读一个字节
输 入: 无
输 出:无
返回值:读入数据
备 注:
***************************************************************************/
uint8_t DS18B20_Read_Byte(void){
uint8_t i,j,data;
data = 0;
for(i=1;i<=8;i++){
j = DS18B20_Read_Bit();
data = (j<<7)|(data>>1);
/*j=0或1,j<<7=0x00或0x80,和data右移一位相或,即把1/0写入最高位,下次再往右移位*/
}
return data;
}
/***************************************************************************
函数名:DS18B20_Start
功 能:DS18B20开启
输 入: 无
输 出:无
返回值:无
备 注:
***************************************************************************/
void DS18B20_Start(void){
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);//跳过ROM
DS18B20_Write_Byte(0x44);//温度变换命令
}
/***************************************************************************
函数名:DS18B20_Init
功 能:DS18B20初始化
输 入: 无
输 出:无
返回值:无
备 注:
***************************************************************************/
uint8_t DS18B20_Init(void){
//引脚初始化
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.Pull = GPIO_PULLUP;
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA,&GPIO_InitStructure);
DS18B20_Rst();
return DS18B20_Check();
}
/***************************************************************************
函数名:DS18B20_Read_Temperature
功 能:读取一次温度
输 入: 无
输 出:无
返回值:读取到的温度数据
备 注:适用于总线上只有一个DS18B20的情况
***************************************************************************/
short DS18B20_Get_Temperature(void){
uint8_t temp;
uint8_t TL,TH;
short temperature;
DS18B20_Start();
DS18B20_Rst();
DS18B20_Check();
DS18B20_Write_Byte(0xcc);//跳过ROM
DS18B20_Write_Byte(0xbe);//读暂存器
TL = DS18B20_Read_Byte();//低八位
TH = DS18B20_Read_Byte();//高八位
//判断温度值是否为负数
if(TH>0x70){
TH = ~TH;
TL = ~TL;
temp = 0;
}else
temp = 1;
temperature = TH;
temperature <<= 8;
temperature += TL;
temperature = (float)temperature*0.625;
if(temperature)
return temperature;
else
return -temperature;
}
DS18B20.H
#ifndef __DS18B20_H__
#define __DS18B20_H__
#include "main.h"
#define DQ_GPIO_Port GPIOB
#define DQ_Pin GPIO_PIN_9
#define DS18B20_DQ_OUT_HIGH HAL_GPIO_WritePin(DQ_GPIO_Port, DQ_Pin, GPIO_PIN_SET)
#define DS18B20_DQ_OUT_LOW HAL_GPIO_WritePin(DQ_GPIO_Port, DQ_Pin, GPIO_PIN_RESET)
#define DS18B20_DQ_IN HAL_GPIO_ReadPin(DQ_GPIO_Port, DQ_Pin)
uint8_t DS18B20_Init(void);
short DS18B20_Get_Temperature(void);
#endif
main.c
tem = DS18B20_Get_Temperature();
sprintf(text,"temp=:%f ",(tem/10));
OLED_ShowString(3,1,text);