DS18B20温度传感器
特点:
- 通信采用1-onewire接口
- 每个DS18b20都有唯一的64位序列码储存在ROM中
- 无需外部原件
- 可从数据线供电,电源范围3.0v~5.5v
- 可测量温度范围在-55℃~+125℃
- 在-10℃~+85℃范围内精度为±0.5℃
- 温度计分辨率可设置为9~12位,12位时分辨率对应为0.0625℃
DS18B20在实际应用中的典型接法
工作在寄生电源下
外部供电下
单总线时序
DS18B20采用1-wire BUS所有数据都在一条线上传输,因此单总线协议对时序要求非常严格以确保数据的完整性。
单总线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1.所有这些信号除存在脉冲由DS18B20发出的以外其它信号都由总线控制器发出。
数据传输总是从最低有效位开始。(IIC总线从最高有效位开始)
初始化程序
主机和DS18B20做任何通讯前都要对其初始化。初始化期间,总线控制器拉低总线并保持480us以上挂在总线上的器件将被复位,然后释放总线,等待15-60us,此时DS18B20将返回一个60-240us之间的低电平存在信号。
写时序分为写0时序和写1时序
总线控制器通过控制单总线高低电平持续时间从而把逻辑1或0写入DS18B20中。
总线控制器要产生一个写时序,必须将总线拉低最少1us,产生写0时序时总线必须保持低电平60~120us之间,然后释放总线,产生写1时序时在总线产生写时序后的15us内允许把总线拉高。注意:2次写周期之间至少间隔1us。
读时序分为读0时序和读1时序
总线控制器通过读取DS18B20控制的总线高低电平接收DS18B20数据。
总线控制器要产生一个读时序,必须将总线拉低至少1us,然后释放总线,在读信号开始后15us内总线控制器采样总线数据,读一位数据至少保持在60us以上。注意:2次读周期之间至少间隔1us。
DS18B20暂存器
温度寄存器图表
S为1:负温度 S为0:正温度
温度/数据关系
配置寄存器图表
温度计精确度配置
部分ROM指令及功能指令
忽略ROM指令(CCH)
这条指令允许总线控制器不用提供64位ROM编码就使用功能指令。例如,总线控制器可以先发出一条忽略ROM指令,然后发出温度转换指令[44H],从而完成温度转换操作。在单点总线情况下使用该命令,器件无需发回64位ROM编码,从而节省了时间。如果总线上有不止一只从机,若发出忽略ROM指令,由于多只从机同时传送信号,总线上就会发生数据冲突。
温度转换指令(44H)
这条命令用于启动一次温度转换。温度转换指令被执行,产生的温度转换结果数据以2个字节的形式被存储在高速暂存器中,而后DS18B20保持等待状态。
读暂存器指令(BEH)
这条命令读取暂存器的内容。读取将从字节0开始,一直进行下去,直到读完暂存器所有字节,如果不想读完所有字节,控制器可以在任何时间发出复位命令来终止读取。
写暂存器指令(4EH)
这条命令向DS18B20的暂存器写入数据,开始位置在TH寄存器(暂存器的第2个字节),接下来写入TL寄存器(暂存器的第3个字节),最后写入配置寄存器(暂存器的第4个字节)
拷贝暂存器指令(48H)
这条命令把TH,TL和配置寄存器的内容拷贝到EEPROM中。
DS18B20温度转换与读取流程
- DS18B20复位
- 写入字节0XCC,跳过ROM指令
- 写入字节0X44,开始温度转换
- DS18B20复位
- 写入字节0XCC,跳过ROM指令
- 写入字节0XBE,读取高速暂存器
- 读取暂存器的第0字节,即温度数据的LSB
- 读取暂存器的第1字节,即温度数据的MSB
- DS18B20复位,表示读取数据结束
- 将LSB和MSB整合成为1个16位数据
- 判断读取结果的符号,进行正负温度的数据处理
ds18b20.c
#include <onewire.h>
void Delay_us(uint us)//延时1us
{
do{
_nop_();
_nop_();
_nop_();
}while(us--);
}
bit DS18B20_Init()
{
bit i;
DQ = 0;//读写之前都要将该引脚拉低
Delay_us(500);
DQ = 1;//释放总线
Delay_us(50);
i = DQ;//读取DQ的值
Delay_us(100);
DQ = 1;
return i;
}
void Write_DS18B20(uchar dat)
{
uchar i;
for(i = 0; i < 8; i++)
{
DQ = 0;
Delay_us(2);
DQ = dat & 0x01;//从最低位开始传送
Delay_us(100);
DQ = 1;//释放总线,准备下一次数据的写入
dat >>= 1;
}
}
uchar Read_DS18B20()
{
uchar i,j,dat;
for(i = 0; i < 8; i++)
{
DQ = 0;
Delay_us(1);
DQ =1;
j = DQ;
Delay_us(100);
DQ = 1;//释放总线,准备下一次数据的写入
dat = (j <<7) | (dat >> 1);
}
return dat;
}
ulong Temper_Get()
{
uchar MSB,LSB;
ulong temp;
DS18B20_Init();
Write_DS18B20(0XCC);
Write_DS18B20(0X44);
Delay_us(500);
DS18B20_Init();
Write_DS18B20(0XCC);
Write_DS18B20(0XBE);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
DS18B20_Init();
temp = msb;
temp <<= 8;
temp |= lsb;
temp >>= 4;
temp = temp*100;
temp = temp + (lsb&0x0f)*6.25;
if((msb >> 4) == 0x0f)
temp |= 0x8000;
}
nixie.c
#include <sys.h>
uchar code Nixie[] = {0XC0, 0XF9, 0XA4, 0XB0, 0X99, 0X92, 0X82, 0XF8, 0X80, 0X90,
0X40, 0X79, 0X24, 0X30, 0X19, 0X12, 0X02, 0X78, 0X00, 0X10, 0XBF, 0XFF};
//0-9 0.-9. - 熄灭
void DisplayAlone(uchar pos,value)
{
Select_74H138(7);
P0 = 0XFF;
Select_74H138(6);
P0 = _crol_(0X01,pos);
Select_74H138(7);
P0 = Nixie[value];
Delay(1);
Select_74H138(0);
}
onewire.h
#ifndef _ONEWIRE_H_
#define _ONEWIRE_H_
#include <STC15F2K60S2.H>
#include <intrins.h>
sbit DQ = P1^4;
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
//ds18b20.c
void Delay_us(unsigned int us);
bit DS18B20_Init();
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20();
unsigned long Temper_Get();
#endif
main.c
#include <sys.h>
#include <onewire.h>
ulong temp;
void main()
{
Init_System();
while(1)
{
temp = Temper_Get();
DisplayAlone(4,temp / 100000);
DisplayAlone(5,temp % 100000 / 10000 + 10);
DisplayAlone(6,temp % 10000 / 1000);
DisplayAlone(7,temp % 1000 / 100);
Select_74H138(7);
P0 = 0XFF;
}
}
运行结果