1.DS18B20介绍
DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出。
测温范围:-55°C 到 +125°C
通信接口:1-Wire(单总线)
其它特征:可形成总线结构、内置温度报警功能、可寄生供电
2.DS18B20引脚及电路介绍
3.DS18B20内部结构
内部结构首先包含一个power-supply-sense内部寄生供电,当VDD不接电源时,DS18B20内部采取寄生供电,本此实验不采用寄生供电,VDD接电源正极,当DQ把数据传送进DS18B20内部后,首先回进到ROM里面,而这里的ROM作用通过DQ线进行写数据和读数据,经过逻辑控制,将要写的数据传入到SCRATCHPAD中相当于一个RAM存数据的盒子,通过写进去的数据向DS18B20发号指令,最右边包含温度传感器,温度报警设置温度的阈值,配置寄存器设置温度精度,以及CRC校验。
3.1DS18B20存储器结构
4.1-Wire单总线介绍
单总线(1-Wire BUS)是由Dallas公司开发的一种通用数据总线
单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
一根通信线:DQ
通信特点:异步、半双工
4.1单总线通信规范
设备的DQ均要配置成开漏输出模式
注意:什么是开漏输出模式?
推挽输出:不需要上拉电阻,不可“线与”,不可电平转换
开漏输出:需要上拉电阻,可以进行“线与”,可以电平转换
DQ添加一个上拉电阻,阻值一般为4.7KΩ左右
若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
注意:什么是强上拉输出电路?
上拉电阻是把一个信号通过一个电阻接到电源(Vcc),下拉电阻是一个信号通过一个电阻接到地(GND)。 强上拉、弱上拉的强弱只是上拉电阻的阻值不同,没有什么严格区分。
4.2单总线时序结构
4.2.1单总线初始化
初始化:主机将总线拉低至少480us,然后释放总线,等待15~60us后,存在的从机会拉低总线60~240us以响应主机,之后从机将释放总线
unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;//应答位
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i);//500us Delay500 us
OneWire_DQ=1;
i = 32;while (--i);//Delay 70us
AckBit=OneWire_DQ;//从机响应
i = 247;while (--i); //500us
return AckBit;
}
4.2.2单总线发送1bit数据(接受1bit)
发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=0;
i = 4;while (--i);//Delay10us
OneWire_DQ=Bit;
i = 24;while (--i);//Delay50us
OneWire_DQ=1;
}
接收一位:主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us的末尾),读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
OneWire_DQ=0;
i = 2;while (--i);//Delay5us
OneWire_DQ=1;
i = 2;while (--i);//Delay5us
Bit=OneWire_DQ;//接受数据
i = 24;while (--i);//Delay50us
return Bit;
}
4.2.3单总线发送1字节(接受一字节)
注意:I2C发送字节:先发送高位再发送低位,1-Wire先发送低位,再发送高位
发送一个字节:连续调用8次发送一位的时序,依次发送一个字节的8位(低位在前)
接收一个字节:连续调用8次接收一位的时序,依次接收一个字节的8位(低位在前)
void OneWire_SendByte(unsigned char Byte)//发送一个字节
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<<i));
}
}unsigned char OneWire_ReceiveByte(void)
{
unsigned char i;
unsigned char Byte=0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
}
return Byte;
}
5.DS18B20实现温度读取
5.1操作流程
为了实现DS18B20温度读取,我们要使用到DS18B20内部的寄存器,这里我们只需要用到ROM指令中的SKIP ROM[CCh],功能指令中的CONVERT温度变化[44h],READ SCRATCHPAD [BEh]功能读取命令
初始化:从机复位
主机判断从机是否响应 ROM操作:ROM指令+本指令需要的读写操作
功能操作:功能指令+本指令需要的读写操作
5.2温度变换和温度读取
温度变换:初始化→跳过ROM →开始温度变换
温度读取:初始化→跳过ROM →读暂存器→连续的读操作
这里对温度进行读取,要先读取温度的LSB低8位,再读取温度的高八位MSB
6.DS18B20温度读取程序
6.1子程序包含
这里只展示main.c主函数,onewire.c和onewire.h,DS18B20.c和DS18B20.h
6.2onewire.c子函数
#include <REGX52.H>
sbit OneWire_DQ=P3^7;
unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;//应答位
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i);//500us Delay500 us
OneWire_DQ=1;
i = 32;while (--i);//Delay 70us
AckBit=OneWire_DQ;//从机响应
i = 247;while (--i); //500us
return AckBit;
}
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=0;
i = 4;while (--i);//Delay10us
OneWire_DQ=Bit;
i = 24;while (--i);//Delay50us
OneWire_DQ=1;
}
unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
OneWire_DQ=0;
i = 2;while (--i);//Delay5us
OneWire_DQ=1;
i = 2;while (--i);//Delay5us
Bit=OneWire_DQ;//接受数据
i = 24;while (--i);//Delay50us
return 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(void)
{
unsigned char i;
unsigned char Byte=0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit()){Byte|=(0x01<<i);}
}
return Byte;
}
6.3onewire.h子函数
#ifndef __ONEWIRE_H__
#define __ONEWIRE_H__
unsigned char OneWire_Init(void);
void OneWire_SendBit(unsigned char Bit);
unsigned char OneWire_ReceiveBit(void);
void OneWire_SendByte(unsigned char Byte);
unsigned char OneWire_ReceiveByte(void);
#endif
6.4DS18B20.c子函数
#include <REGX52.H>
#include "onewire.h"
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_CONVERT_T 0xBE
void DS18B20_ConvertT()
{
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM );//发送skip RoM地址
OneWire_SendByte(DS18B20_CONVERT_T);//发送温度转化地址
}
float DS18B20_ReadT(void)
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);//发送skip RoM地址
OneWire_SendByte(DS18B20_READ_CONVERT_T);//发送读温度暂存器的地址
TLSB=OneWire_ReceiveByte();
TMSB=OneWire_ReceiveByte();
Temp=(TMSB<<8)|TLSB;//拼接为16位
T=Temp/16.0;//得到准确的温度
return T;
}
6.5DS18B20.h子函数
#ifndef __DS18B20_H__
#define __DS18B20_H__
void DS18B20_ConvertT(void);
float DS18B20_ReadT(void);
#endif
6.6main主函数
#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"
#include "DS18B20.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);//显示温度小水但后面4位小数
}
}
.