一、DS18B20介绍
DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
测温范围: -55°C 到+125°C .
通信接口: 1-Wire (单 总线)
其它特征:可形成总线结构、内置温度报警功能、可寄生供电
二、引脚及应用电路
VCC表示电路的意思,指的是接入电路的电压;VDD表示器件的意思,指的是器件内部的工作电压;VSS表示公共连接端的意思,指的是公共接地端电压的意思。
三、DS18B20内部结构框图
64-BT ROM:作为器件地址。用于总线通信的寻址
SCRATHPAD (暂存器)公用于总线的数据交互
EEPROM用于保存温度触发阚值和配置参数
64-BIT ROM 每个DS18B02都有一个ID号,用来寻址,相当于一个大门,当只有一个单总线设备时,可以选择跳过这个大门;
MEMORY CONTROL LOGIC 内存控制逻辑,相当于管家,操作底下的暂存器;
SCRATCHPAD 暂存器,属于RAM,用于总线上数据交互;
TEMPERATURE SENSOR 是温度传感器,直接将数据处理好放在暂存器中;
底下两个都是设置阈值的,用于报警;
第四个是配置寄存器,设置分辨率,默认最高分辨率0.0625,可以设置为0.5的分辨率,使得运算的更快一些;
第五个是校验寄存器;
四、存储器结构
我们无法通过写数据直接给EEPROM写数据,只能写入到暂存器中,通过发送指令,再让暂存器中的数据复制到EEPROM。
五、单总线介绍
●单总线(1-Wire BUS) 是由Dallas公司开发的-种通用数据总线一根通信线: DQ
●异步、半双工
●单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
单总线应用其实并不是很广泛,可以说DS18B20撑起了单总线的天下;右边这个是温湿度传感器DHT11,虽然说他也是一根数据线进行传输的,但它的通信协议和单总线通信协议有很大的区别,他不能在总线上边挂在很多设备,但它说它是单总线设备。
(一)单总线电路规范
设备的DQ均要配置成开漏输出模式
DQ添加一个上拉电阻,阻值一般为4.7KQ左右
若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
(二)单总线时序结构
①初始化
初始化: 主机将总线拉低至少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);//将总线拉低至少480us,这里我们拉低延时500us
OneWire_DQ=1;
i = 32;while (--i);//延时70us,函数调用花费4us忽略掉
AckBit=OneWire_DQ;//主机读取从机是否响应
i = 247;while (--i);//延时500us
return AckBit;
}
② 发送一位
发送一位:主机将总线拉低60~120us,然后释放总线,表示发送0;主机将总线拉低1~ 15us, 然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us 。
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=0;
i = 4;while (--i);//延时14us,考虑到函数跳转需要4us,因此我们用isp时要多延时4us
OneWire_DQ=Bit;//省去一个if判断,在14us后直接将需要发送的位放在单总线上,30us //从机自行读取
i = 24;while (--i);//延时50us,考虑函数跳转需要4us,另外加4us
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);//Delay 5us
OneWire_DQ=1;
i = 2;while (--i);//Delay 5us
Bit=OneWire_DQ;//此时读取从机所发送的位
i = 24;while (--i);//延时50us,考虑函数跳转需要4us,另外加4us
return Bit;
}
④发送和接收一个字节
发送一个字节
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01< }
}
接收一个字节
unsigned char OneWire_ReceiveByte(void)
{
unsigned char i;
unsigned char Byte=0x00;
for(i=0;i<8;i++)
{
if(OneWire_ReceiveBit()){Byte|=(0x01< }
return Byte;
}
六、DS18B20操作流程
(1)
初始化:从机复位,主机判断从机是否响应
ROM操作:ROM指令+本指令需要的读写操作
功能操作:功能指令+本指令需要的读写操作,相当于RAM操作对暂存器的操作
MATCH ROM[55h] 匹配ROM,相当于设备的地址
SKIP ROM[CCh] 跳过ROM,只有一个设备在总线上,因此可以直接跳过ROM(大门),进行通信
CONVERT T[44h] 温度传递指令,发送该指令,DS18B20中的温度传感器就将数据传送到暂存器当中
WRITE SCRATCHPAD[4Eh] 写暂存器指令,该指令是将EEPROM中的数据写到暂存器当中
READ SCRATCHPAD[BEh] 读暂存器指令,该指令是将暂存器当中的数据都读出来,但实际操作时我们只需要前两个温度的字节
COPY SCRATCHPAD[48h] 复制暂存器,将ROM中的数据写入到EEPROM中,如果想要实现掉电不丢失,就先把数据写入到ROM中,再通过调用该指令,写入到EEPROM中
RECALL E2[B8h] 覆盖暂存器指令,该指令是将EEPROM中的数据覆盖掉暂存器中的数据
(2)DS18B20数据帧
(3)温度存储格式
低四位表示小数,高五位表示符号,中间的才是整数部分
(4)代码
onewire.c
#include
//引脚定义
sbit OneWire_DQ=P3^7;
/**
* @brief 单总线初始化
* @param 无
* @retval 从机响应位,0为响应,1为未响应
*/
unsigned char OneWire_Init(void)
{
unsigned char i;
unsigned char AckBit;
OneWire_DQ=1;
OneWire_DQ=0;
i = 247;while (--i);//将总线拉低至少480us,这里我们拉低延时500us
OneWire_DQ=1;
i = 32;while (--i);//延时70us,函数调用花费4us忽略掉
AckBit=OneWire_DQ;//主机读取从机是否响应
i = 247;while (--i);//延时500us
return AckBit;
}
/**
* @brief 单总线发送一位
* @param Bit 要发送的位
* @retval 无
*/
void OneWire_SendBit(unsigned char Bit)
{
unsigned char i;
OneWire_DQ=0;
i = 4;while (--i);//Delay 10us,考虑到函数跳转需要4us,因此我们用isp时要多延时4us
OneWire_DQ=Bit;
i = 24;while (--i);//延时50us,考虑函数跳转需要4us,另外加4us
OneWire_DQ=1;
}
/**
* @brief 单总线接收一位
* @param 无
* @retval 读取的位
*/
unsigned char OneWire_ReceiveBit(void)
{
unsigned char i;
unsigned char Bit;
OneWire_DQ=0;
i = 2;while (--i);//Delay 5us
OneWire_DQ=1;
i = 2;while (--i);//Delay 5us
Bit=OneWire_DQ;//此时读取从机所发送的位
i = 24;while (--i);//延时50us,考虑函数跳转需要4us,另外加4us
return Bit;
}
/**
* @brief 单总线发送一个字节
* @param Byte 要发送的字节
* @retval 无
*/
void OneWire_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
OneWire_SendBit(Byte&(0x01<
DS18B20.c
#include
#include "OneWire.h"
//DS18B20指令
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
/**
* @brief DS18B20开始温度变换
* @param 无
* @retval 无
*/
void DS18B20_ConvertT(void)
{
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_CONVERT_T);
}
/**
* @brief DS18B20读取温度
* @param 无
* @retval 温度数值
*/
float DS18B20_ReadT(void)
{
unsigned char TLSB,TMSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
TLSB=OneWire_ReceiveByte();
TMSB=OneWire_ReceiveByte();
Temp=(TMSB<<8)|TLSB;
T=Temp/16.0;//因为低四位表示的是小数部分,因此Temp直接读出来并不是实际的值,
//要把小数部分摘出来,除以16相当于把低四位给滤出来
return T;
}
main.c
#include
#include "LCD1602.h"
#include "OneWire.h"
#include "DS18B20.h"
#include "Delay.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);
}
}