一、介绍
独特的单总线接口方式,DS18B20在与微处理器连接时仅需要一条线即可实现微处理器与DS18B20的双向通讯,大大提高了系统的抗干扰性。
测温范围:-55°C ~ +125°C,精度为+-0.5°C。
支持多点组网功能,多个DS18B20可以并联在唯一的三线上,最多只能并联8个,实现多点测温,如果数量过多,会使供电电源电压过低,从而造成信号传输的不稳定。
工作电源:3.0V ~ 5.5V。
在使用中不需要任何外围元件。
测量结果以9~12位数字量方式串行传送。
单总线是一种半双工通信方式。
DS18B20共有6种信号类型:复位脉冲、应答脉冲、写0、写1、读0和读1。所有这些信号,除了应答脉冲以外,都由主机发出同步信号。并且发送所有的命令和数据都是字节的低位在前。
二、封装
三、连接方式
四、原理图
五、时序
(1)复位脉冲
单总线上的所有通信都是以初始化序列开始。主机输出低电平,保持低电平时间至少480 us,,以产生复位脉冲。接着主机释放总线,4.7K的上拉电阻将单总线拉高,延时15~60 us,并进入接收模式(Rx)。接着DS18B20拉低总线60~240 us,以产生低电平应答脉冲。
(2)写时序
写时序包括写0时序和写1时序。所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线。
写1时序:主机输出低电平,延时2us,然后释放总线,延时60us。
写0时序:主机输出低电平,延时60us,然后释放总线,延时2us。
(3)读时序
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据。
所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间。每个读时序都由主机发起,至少拉低总线1us。主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态。
典型的读时序过程为:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us。
(4)DS18B20的典型温度读取过程
复位--->发SKIP ROM命令(0XCC)--->发开始转换命令(0X44)--->延时--->复位--->发送SKIP ROM命令(0XCC)--->发读存储器命令(0XBE)--->连续读出两个字节数据(即温度)--->结束。
六、程序
#ifndef __DS18B20_H__
#define __DS18B20_H__
#include"stm32f4xx_conf.h"
#define DS18B20_DQ_OUT_LOW() GPIO_ResetBits(GPIOB,GPIO_Pin_15)
#define DS18B20_DQ_OUT_HIGH() GPIO_SetBits(GPIOB,GPIO_Pin_15)
#define DS18B20_DQ_IN() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)
#define DS18B20_DQ_IN() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)
void DS18B20_RST(void);
uint8_t DS18B20_ACK(void);
void DS18B20_Write_Byte(uint8_t data);
uint8_t DS18B20_Read_Byte(void);
short DS18B20_Get_Temp(void);
#endif
#include "./DS18B20/ds18b20.h"
#include "./delay.h"
/****************************
功能:配置GPIO的输入模式
参数:无
返回值:无
*****************************/
void DS18B20_GPIO_IN(void)
{
GPIO_InitTypeDef initValue;
/*1、打开时钟*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
/*2、配置GPIO的输入功能*/
initValue.GPIO_Mode = GPIO_Mode_IN;
initValue.GPIO_Pin = GPIO_Pin_15;
initValue.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB,&initValue);
}
/****************************
功能:配置GPIO的输出模式
参数:无
返回值:无
*****************************/
void DS18B20_GPIO_OUT(void)
{
GPIO_InitTypeDef initValue;
/*1、打开时钟*/
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
/*2、配置GPIO的输出功能*/
initValue.GPIO_Mode = GPIO_Mode_OUT;
initValue.GPIO_Pin = GPIO_Pin_15;
initValue.GPIO_PuPd = GPIO_PuPd_NOPULL;
initValue.GPIO_OType = GPIO_OType_PP;
initValue.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&initValue);
}
/****************************
功能:复位脉冲
参数:无
返回值:无
*****************************/
void DS18B20_RST(void)
{
/*1、配置GPIO的输出模式*/
DS18B20_GPIO_OUT();
/*2、输出低电平*/
DS18B20_DQ_OUT_LOW();
/*3、延时至少480us*/
delay_us(750);
/*4、输出高电平*/
DS18B20_DQ_OUT_HIGH();
/*5、延时15~60us*/
delay_us(15);
}
/*************************************
功能:应答信号
参数:无
返回值:
返回1-->未检测到DS18B20的存在
返回0-->DS18B20存在
**************************************/
uint8_t DS18B20_ACK(void)
{
uint8_t retry = 0;
/*1、配置GPIO的输入功能*/
DS18B20_GPIO_IN();
/*2、等待DQ拉低*/
while(DS18B20_DQ_IN() && retry<200) //高电平
{
retry++;
delay_us(1);
}
if(retry >= 200)
{
return 1;
}
else
{
retry = 0;
}
/*3、*/
while(!DS18B20_DQ_IN() && retry<240)//低电平
{
retry++;
delay_us(1);
}
if(retry>=240)
{
return 1;
}
return 0;
}
/****************************
功能:写一个字节到DS18B20
参数:无
功能:无
*****************************/
void DS18B20_Write_Byte(uint8_t data)
{
uint8_t i;
uint8_t testb;
/*1、配置GPIO的输出模式*/
DS18B20_GPIO_OUT();
/*2、写字节到DS18B20*/
for(i = 0;i<8;i++)
{
testb = data & 0x01; //取出低位数据
data = data >> 1;
if(testb == 1)//写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中读取一个位
参数:无
返回值:读取到的数据
*****************************************/
uint8_t DS18B20_Read_Bit(void)
{
uint8_t data;
/*1、配置GPIO的输出模式*/
DS18B20_GPIO_OUT();
/*2、输出低电平*/
DS18B20_DQ_OUT_LOW();
/*3、延时至少1us*/
delay_us(2);
/*4、输出高电平*/
DS18B20_DQ_OUT_HIGH();
DS18B20_GPIO_IN();//输入模式
/*5、延时0~15us*/
delay_us(12);
/*6、读取一个位的数据*/
if(DS18B20_DQ_IN() == 1)//读取到的数据为1
{
data = 1;
}
else//读取到的数据为0
{
data = 0;
}
/*7、延时50us*/
delay_us(50);
return data;
}
/****************************************
功能:从DS18B20中读取一个字节的数据
参数:无
返回值:读取到的数据
*****************************************/
uint8_t DS18B20_Read_Byte(void)
{
uint8_t i = 0;
uint8_t j;
uint8_t data = 0;
for(i = 0;i<8;i++)
{
j = DS18B20_Read_Bit();
data = ((j<<7) | (data >>1));
}
return data;
}
/**********************************************
功能:读取温度
参数:无
返回值:读取到的温度(-550~1250,扩大了10倍)
***********************************************/
short DS18B20_Get_Temp(void)
{
uint8_t t;
short temp;
uint8_t TL,TH;
/*1、复位*/
DS18B20_RST();
DS18B20_ACK();//应答
/*2、发送SKIP ROM命令(0xCC)*/
DS18B20_Write_Byte(0xCC);
/*3、发送开始转换命令(0x44)*/
DS18B20_Write_Byte(0x44);
/*4、复位*/
DS18B20_RST();
DS18B20_ACK();//应答
/*5、发送SKIP ROM命令(0xCC)*/
DS18B20_Write_Byte(0xCC);
/*6、发送存储器命令(0xBE)*/
DS18B20_Write_Byte(0xBE);
/*7、连续读出两个字节数据(即温度)*/
TL = DS18B20_Read_Byte();
TH = DS18B20_Read_Byte();
/*8、处理读取到的数据*/
if(TH > 7) //温度为负
{
TH = ~TH;
TL = ~TL;
t = 0;
}
else //温度为正
{
t = 1;
}
//获得高8位
temp = TH;
temp <<= 8;
temp += TL;//获得低8位
temp = (double)temp * 0.625;//转换
if(t == 1)
{
return temp;
}
else
{
return ~temp;
}
}
#include "delay.h"
#include "stdio.h"
#include "./USART/usart.h"
#include "./DS18B20/ds18b20.h"
int main(void)
{
short temperature;
//初始化延时函数
delay_init(168);
//初始化串口
USART_Config();
//读取DAC值
temperature = DS18B20_Get_Temp();
printf("value = %d \r\n",temperature);
while(1)
{
}
}