工具
1.Proteus 8 仿真器
2.keil 5 编辑器
原理图
讲解
DS18B20数字温度传感器提供9-Bit到12-Bit的摄氏温度测量精度和一个用户可编程的非易失性且具有过温和低温触发报警的功能。DS18B20采用的1-Wire通信即仅仅采用一个数据线(以及地)与微控制器进行通信。该传感器的温度检测范围为 -55℃至 +125℃(-67°F至+257°F) ,并且在温度范围超过 -10℃至 +70℃之外时还具有+-0.4℃的精度。此外,DS18B20可以直接由数据线供电而不需要外都电源供电。
特性
- 独特的1-Wire总线接口仅需要一个管脚来通信
- 每个设备内部ROM上都烧写了一个独一无二的64位序列号
- 多路采集能力使得分布式温度采集应用更加简单
- 无需外围元件
- 能够采用数据线供电;供电范围为2.5V至5.5V
- 温度可测量范围:-55℃至+125℃ (-67°F至+257°F)
- 温度范围超过-10℃至+70℃之外时具有+-0.4℃的精度
- 内部温度采集精度可以由用户自定义为9-Bit到12-Bit
- 温度转换时间在转换精度为12-Bit时达到最大值750ms
- 用户自定义非易失性的温度报警设置
引脚
引脚 | 说明 |
N.C | 置空 |
VDD | 电源。当由数据线供电时,VDD必须接地“寄生电源” |
DQ | 数据输入/输出。1-Wire 漏极开路接口引脚。 |
GND | 地 |
“寄生电源”:数据线DQ为设备供电。高电平时为内部电容充电,低电平时由电容向设备供电。
数据
温度(℃) | 数字输出(二进制) | 数字输出(十六进制) |
+125 | 0000 0111 1101 0000 | 07D0h |
+85* | 0000 0101 0101 0000 | 0550h |
+25.0625 | 0000 0001 1001 0001 | 0191h |
+10.125 | 0000 0000 1010 0010 | 00A2h |
+0.5 | 0000 0000 0000 1000 | 0008h |
0 | 0000 0000 0000 0000 | 0000h |
-0.5 | 1111 1111 1111 1000 | FFF8h |
-10.125 | 1111 1111 0101 1110 | FF5Eh |
-25.0625 | 1111 1110 0110 1111 | FE6Fh |
-55 | 1111 1100 1001 0000 | FC90h |
*上电复位时温度寄存器默认值为+85℃
DS18B20温度传感器的温度计算方法如下:
- 读取温度数据:通过数据线读取DS18B20存储的温度数据,包括符号位和12位二进制补码。
- 符号位判断:根据符号位判断温度的正负,正温度时符号位为0,负温度时符号位为1。
- 补码计算:如果温度为正,则直接将12位二进制补码转换为十进制数;如果温度为负,则先将12位二进制补码取反,然后加1,再转换为十进制数。
- 温度值计算:将十进制数乘以0.0625(因为DS18B20的分辨率为0.0625度),得到实际的温度值。
通过以上步骤,就可以计算出DS18B20温度传感器所测得的温度值。
例如:
先判断高四位是0还是1, 0正1负。
算法 | 数值 |
二进制 | 0000 0111 1101 0000 |
高五位取正负 | +(正) |
十六进制 | 07D0h |
转十进制 | 2000 |
乘0.0625 | 125 |
结果 | +125℃ |
算法 | 数值 |
二进制 | 1111 1110 0110 1111 |
高五位取正负 | -(负) |
十六进制 | FE6Fh |
取反 | 0000 0001 1001 0000 |
转十进制 | 400 |
加1 | 401 |
乘0.0625 | 25.0625 |
结果 | -25.0625 |
高速暂存寄存器
寄存器内容 | 温度值低位 | 温度值高位 | 高温限值(TH) | 低温限值(TL) | 配置寄存器 | 保留 | 保留 | 保留 | CRC校验 |
字节地址 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1-Wire单总线信号
DS18B20需要严格的单总线协议以确保数据的完整性。协议定义了几种单总线信号的类型:复位脉冲、存在脉冲 、写0、写1、读0和读1.所有这些信号,除存在脉冲外,都是由总线控制器发出的。
时序
初始化时序
所有和DS18B20间的通信都以初始化序列开始,一个复位脉冲跟着一个存在脉冲表明DS18B20已经准备好发送和接收数据
DQ高电平---DQ低电平---(500us)---释放总线DQ高电平---(60us)---读取DQ状态---(500us)
注意:释放总线为高电平是为了让DS18B20能够检测到总线的状态变化并做出响应,从而完成初始化过程。
写时序
主机将总线拉低60-120us,然后释放总线,表示发送0;主机将总线拉低1~15us,然后释放总线,表示发送1。从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us;
DQ高电平---DQ低电平---(10us)---写入DQ高电平/低电平---(50us)---释放总线DQ高电平
读时序
主机将总线拉低1~15us,然后释放总线,并在拉低后15us内读取总线电平(尽量贴近15us末尾) 读取为低电平则为接收0,读取为高电平则为接收1,整个时间片应大于60us
DQ高电平---DQ低电平---(5us)---释放总线DQ高电平---(5us)---读取DQ高电平/低电平---(50us)
使用
温度变换:初始化---跳过ROM---开始温度变换
温度读取:初始化---跳过ROM---读暂存器---连续的读操作
指令
ROM指令 | 功能指令 | ||
指令 | 描述 | 指令 | 描述 |
F0h | 44h | 这条命令用以启动一次温度转换。温度转换指令被执行,产生的温度转换结果数据以 2 个字节的形式被存储在高速暂存器中,而后 DS18B20 保持等待状态。 | |
33h | 4Eh | ||
55h | BEh | 这条命令读取暂存器的内容。读取将从字节 0 开始,一只进行下去,知道第 9 字节(字节 8,CRC)读完,如果不想读完所有字节,控制器可以在任何时间发出复位命令来中止读取。 | |
CCh | 这条指令允许总线控制器不用提供 64 位 ROM 编码。在单点总线情况下使用该命令,器件无需发回 64 位 ROM 编码,从而节省了时间。如果总线上有不止一只从机,若发出忽略 ROM 指令,由于多只从机同时传送信号,总线上就会发生数据冲突。 | 48h | |
ECh | B8h | ||
B4h |
代码
#include <reg52.h>
#include "Delay.h"
#include "intrins.h"
#include "LCD1602.h"
sbit DQ=P3^0; //定义总线
//DS18B20初始化
unsigned char DS18B20_Init()
{
unsigned char token;
//拉低总线 产生低电平脉冲
DQ=1; //DQ高电平
DQ=0; //DQ低电平
delay_10us(50); //500us
DQ=1; //释放总线DQ高电平
delay_10us(6); //60us
token=DQ; //读取DQ状态
delay_10us(50); //500us
return token; //反馈
}
//写入一位
void write_oneBit(unsigned char Bit)
{
DQ=1; //DQ高电平
DQ=0; //DQ低电平
delay_10us(1); //10us
DQ=Bit; //写入DQ高电平/低电平
delay_10us(5); //50us
DQ=1; //释放总线DQ高电平
}
//读取一位
unsigned char read_oneBit()
{
unsigned char Dat;
DQ=1; //DQ高电平
DQ=0; //DQ低电平
delay_10us(1); //10us
DQ=1; //释放总线DQ高电平
delay_10us(1); //10us
Dat=DQ; //读取DQ高电平/低电平
delay_10us(5); //50us
P1=Dat;
return Dat;
}
//写入一字节
void write_oneHex(unsigned char h)
{
unsigned char i;
for(i=0;i<8;i++)
{
write_oneBit(h&(0x01<<i));
}
}
//接收一字节
unsigned char read_oneHex()
{
unsigned char i,Byte=0x00;
for(i=0;i<8;i++)
{
if(read_oneBit()){Byte|=(0x01<<i);}
}
return Byte;
}
//温度变换:初始化-->跳过ROM-->开始温度变换
void DS18B20_ConvertT(void)
{
DS18B20_Init();//初始化
write_oneHex(0xCC);//跳过ROM
write_oneHex(0x44);//温度变换
}
//温度读取:初始化-->跳过ROM-->读暂存器-->连续的读操作
float DS18B20_ReadT(void)//温度读取
{
unsigned char TLSB,TMSB;
int temp_data;//16位数据
float temp=0.0000;
DS18B20_Init();
write_oneHex(0xCC);
write_oneHex(0xBE);//读暂存器
//一旦发送完指令,控制权交给 从机
TLSB = read_oneHex(); //读的Byte0,低8位数据
TMSB = read_oneHex(); //读的Byte1,高8位数据
temp_data = (TMSB << 8) | TLSB; //正好为int类型16位数据
//负数
if(temp_data>>12)
{
temp=(~temp_data+1)*0.0625;
return -temp;
//正数
}else{
temp=temp_data*0.0625;
return temp;
}
}
void LCD1602_temp(float tem)
{
if(tem<0)
{
LCD_ShowChar(2,1,'-');
LCD_ShowNum(2,2,(int)-tem,3);
LCD_ShowString(2,5,".");
LCD_ShowNum(2,6,((-tem-(int)-tem)*10000),4);
LCD_ShowChar(2,10,0xDF);
LCD_ShowChar(2,11,0x43);
}else{
LCD_ShowChar(2,1,'+');
LCD_ShowNum(2,2,(int)tem,3);
LCD_ShowString(2,5,".");
LCD_ShowNum(2,6,((tem-(int)tem)*10000),4);
LCD_ShowChar(2,10,0xDF);
LCD_ShowChar(2,11,0x43);
}
}
void main(void)
{
//初始化液晶
LCD_Init();
LCD_ShowString(1,1,"Old_man:temp");
DS18B20_ConvertT();
delay_ms(1000); //延时一秒 跳过初始化85℃默认值
LCD1602_temp(DS18B20_ReadT());
while(1)
{
delay_ms(100);
DS18B20_ConvertT();
LCD1602_temp(DS18B20_ReadT());
delay_ms(100);
}
}
实现
🚀本欧也处于学习阶段,所学所识将以笔记发布。
笔记会根据相关知识的接触而随时更新!
如果文章对你有帮助,请留下你宝贵的点赞吧👍
V:Werluo 本欧也很喜欢交朋友的哦!