文章目录
1、DS18B20的基本概述
工作电压:3.0V~5.5V。
测量范围:-55摄氏度~+125摄氏度。
通信方式:单总线,数据线接上拉电阻,使总线空闲时处于高电平。
转换精度:9~12位分辨率可调,默认为12位,即分辨率是0.0625。
转换时间:典型值200ms。
2、DS18B20内部结构
主要由4部分组成:64 位ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。ROM中的64位序列号是出厂前被光刻好的,它可以看作是该DS18B20的地址序列码,每个DS18B20的64位序列号均不相同。64位ROM的排的循环冗余校验码(CRC=X8+X5+X^4+1)。 ROM的作用是使每一个DS18B20都各不相同,这样就可以实现一根总线上挂接多个DS18B20的目的。
3、DS18B20的内部存储结构
DS18B20的内部有64位的ROM单元和9字节的高速暂存器。64位ROM单元包含了DS18B20唯一的序列号。
第0字节:温度数据的低8位。
第1字节:温度数据的高8位。
第3字节:TH用户字节,设置报警温度最高值。
第4字节:TL用户字节,设置报警温度最低值。
第5字节:配置寄存器,设置转换精度,默认12位。
第6字节和第7字节:保留,不用管。
第8字节:CRC码。
注:上电后,第2字节、第3字节和第4字节的状态值为EEPROM中的数据。
4、DS18B20的数据处理
DS18B20以16位带符号位扩展的二进制补码形式读出。低4位为小数部分,中间7位为整数部分,高5位为符号位。
DS18B20的分辨率为0.0625。读出数据为正温度时,将LSB和MSB整合成的16位整数,直接乘以0.0625即可。读出数据为负温度时,则需要将LSB和MSB整合成的16位整数,取反加1后,再乘以0.0625。
例如:
读出结果为00A2H,温度值 = 162×0.0625 = 10.125 摄氏度。
读出结果为FF5EH,取反加1就是00A2H,温度值则为 -10.125 摄氏度。
注意:在上电复位的时候,温度寄存器中的值为0x0550,即+85摄氏度。
5、DS18B20的复位时序
【1】微处理器首先将总线拉低480us以上,然后释放总线。
【2】总线释放后,上拉电阻会将其拉至高电平。
【3】DS18B20发现总线有上升沿,等待15~60us后,拉低总线,表示应答。
【4】微处理器在DS18B20应答期间,读取总线上的电平,如果是低电平则表示复位成功。
【5】DS18B20在产生60~240us的应答信号后,会释放总线。
bit Init_DS18B20(void)
{
bit initflag = 0;
DQ = 0;
Delay_OneWire(50); //拉低总线480us以上
DQ = 1; //释放总线
Delay_OneWire(5); //等待15~60us
initflag = DQ; //读取18B20的复位应答信号
Delay_OneWire(10); //等待60~240us
return initflag; //应答信号为低电平,表示复位成功
}
6、DS18B20的写时序(低位先发)
【1】微处理器将总线拉低10~15us。
【2】在接下来的15~45us直接,根据逻辑1或逻辑0,控制总线的高低电平。
【3】释放总线。
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0; //先拉低总线电平10~15us
DQ = dat&0x01; //向总线写入一个位数据
Delay_OneWire(5); //维持状态20~45us
DQ = 1; //释放总线
dat >>= 1; //准备发送下一个数据位
}
}
7、DS18B20的读时序(低位先读)
【1】微处理器先将总线拉低1us,然后释放总线。
【2】微处理器读取总线上的电平。
【3】微处理器读取电平后,延时约45us。
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0; //先将总线电平拉低10~15us
dat >>= 1;
DQ = 1; //然后释放总线
if(DQ) //读取总线上的电平状态
{
dat |= 0x80;
}
Delay_OneWire(5); //延时45us左右,再度下一个数据位
}
return dat;
}
8、DS18B20的温度转换与读取流程
[1] DS18B20复位。
[2]写入字节0xCC,跳过ROM指令。
[3]写入字节0x44,开始温度转换。
[4]延时700~900ms。
[5] DS18B20复位。
[6]写入字节0xCC,跳过ROM指令。
[7]写入字节0xBE,读取高速暂存器。
[8]读取暂存器的第0字节,即温度数据的LSB.
[9]读取暂存器的第1字节,即温度数据的MSB.
[10] DS18B20复位。 表示读取数据结束。
[11]将LSB和MSB整合成为一个16位数据。
[12]判断读取结果的符号,进行正负温度的数据处理。
9、DS18B20温度采集完整代码
硬件说明: IAP15F2K61S2
程序代码:
1、main.c
#include "reg52.h" //定义51单片机特殊功能寄存器
#include "temp.h"
#include "absacc.h"
sfr AUXR = 0x8E;
unsigned char dspbuf[8] = {10,10,10,10,10,10,10,10};//显示缓冲区
unsigned char dspcom = 0;
unsigned char intr;
bit temper_flag = 0;//温度读取标志
code unsigned char tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0xff};
void display(void);
void cls_buzz()
{
P2 = ((P2&0x1f)|0xA0);
P0 = 0x00;
P2 &= 0x1f;
}
void cls_led()
{
P2 = ((P2&0x1f)|0x80);
P0 = 0xFF;
P2 &= 0x1f;
}
//主函数
void main(void)
{
unsigned char temperature;
cls_buzz();cls_led();
AUXR |= 0x80;
TMOD &= 0xF0;
TL0 = 0xCD;
TH0 = 0xD4;
TF0 = 0;
TR0 = 1;
ET0 = 1;
EA = 1;
while(1)
{
if(temper_flag)
{
temper_flag = 0;
temperature = rd_temperature(); //读温度
}
//显示数据更新
(temperature>=10)?(dspbuf[6] = temperature/10):(dspbuf[6]=10);
dspbuf[7] = temperature%10;
}
}
//定时器中断服务函数
void isr_timer_0(void) interrupt 1 //默认中断优先级 1
{
display();
if(++intr == 100) //1ms执行一次
{
intr = 0;
temper_flag = 1; //100ms温度读取标志位置1
}
}
//显示函数
void display(void)
{
P2 = ((P2&0x1f)|0xE0);
P0 = 0xff;
P2 &= 0x1f;
P0 = 1<<dspcom;
P2 = ((P2&0x1f)|0xC0);
P2 &= 0x1f;
P0 = tab[dspbuf[dspcom]];
P2 = ((P2&0x1f)|0xE0);
P2 &= 0x1f;
if(++dspcom == 8){
dspcom = 0;
}
}
2、temp.c
#include "reg52.h"
sbit DQ = P1^4;
//单总线延时函数
#ifndef STC12
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
#else
void Delay_OneWire(unsigned int t) //STC12C5260S2
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
#endif
//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//从DS18B20读取一个字节
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80); // 延时大于480us
DQ = 1;
Delay_OneWire(10); // 14
initflag = DQ; // initflag等于1初始化失败
Delay_OneWire(5);
return initflag;
}
//DS18B20温度采集程序:整数
unsigned char rd_temperature(void)
{
unsigned char low,high;
char temp;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44); //启动温度转换
Delay_OneWire(200);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE); //读取寄存器
low = Read_DS18B20(); //低字节
high = Read_DS18B20(); //高字节
temp = high<<4;
temp |= (low>>4);
return temp;
}
3、temp.h
#ifndef _TEMP_H
#define _TEMP_H
#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe
//函数声明
unsigned char rd_temperature(void);
#endif