DS18B20模块应用——蓝桥杯竞赛题目
目录
一、DS18B20基本概念
(一)、DS18B20的基本概念
DS18B20是Dallas公司生产的、具有one-Wire协议的数字式温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
one-Wire(单线制串行总线)是Dallas公司研制开发是一种协议,由一个总线主节点、一个或多个从节点组成系统,通过一根信号线对芯片进行数据读取。
(二)、DS18B20的基本信息
测温范围:-55摄氏度~+125摄氏度
转换精度:9~12位二进制数(含1位符号位)
测温精度:9位精度为0.5摄氏度;12位精度为0.0625摄氏度。
转换时间:9位精度时为93.75ms;10位精度时为187.5ms;12位精度时为750ms。
通信方式:单总线,数据线接上拉电阻,使总线空闲时处于高电平。
二、DS18B20介绍
(一)DS18B20内部存储结构
DS18B20内部有9字节的高速寄存器
对应功能讲解:
对应的字节 |
寄存器编址 |
功能作用 |
第0字节 |
00H |
温度转换值低8位 |
第1字节 |
01H |
温度转换值高8位 |
第2字节 |
02H |
温度上限寄存器TH |
第3字节 |
03H |
温度下限寄存器TL |
第4字节 |
04H |
系统配置寄存器 |
第5字节 |
05H |
保留(FFH) |
第6字节 |
06H |
保留(0CH) |
第7字节 |
07H |
保留(10H) |
第8字节 |
08H |
CRC校验 |
(二)DS18B20系统配置寄存器数据格式
DS18B20系统配置寄存器有8位,低5位值永远为1,最高位为TM,TM是测试模式为,用于设置DS18B20在工作模式还是测试模式。在出厂时被设置为0,需要时可以修改,R1和R0用于设置分辨率(DS18B20在出厂时被设置为12位的分辨率,需要时可以修改)。DS18B20系统配置寄存器数据格式如下:
DS18B20分辨率设置如下:
(三)DS18B20温度数据格式与处理
DS18B20可完成对温度的测量,下面以12位精度为例。以16位带符号位扩展的二进制补码形式读出。低4位为小数部分,中间7位为整数部分,高5位为扩展符号位,
其中,S为符号扩展位,S=1 表示温度为负值,S=0表示温度为正值。
输出数据和实际温度值之间的关系如下:
注:DS18B20的温度数据是以补码形式表示。
计算方法:
DS18B20的12位精度的分辨率为0.0625。当读出数据为正温度时,将LSB和MSB整合成的16位整数,再分辨率(即0.0625)即可;当读出数据为负温度时,将LSB和MSB整合成的16位整数,再取反加1后,最后乘以0.0625即可。
(四)DS18B20时序复位设计
下面为蓝桥杯官方提供的底层驱动代码:
//DS18B20设备初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
(五)DS18B20的读/写时序
下面为蓝桥杯官方提供的底层驱动代码:
//通过单总线向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的几个重要指令
CCH:跳过ROM指令。跳过64位ROM地址,直接向DS18B20发起各种执行指令。
44H:温度转换指令。启动DS18B20进行温度转换。
BEH:读取暂存器指令。
三、DS18B20的底层驱动代码
下面为蓝桥杯官方提供的底层驱动代码:
#include "reg52.h"
sbit DQ = P1^4; //单总线接口
//单总线延时函数
void Delay_OneWire(unsigned int t) //STC89C52RC
{
while(t--);
}
//通过单总线向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);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
四、DS18B10的应用
在CT107D单片机综合训练平台上,实现实时温度测量。
#include "reg52.h"
#include "onewire.h"
unsigned char temp=0;
unsigned char code SMG_NoDot[18] = {0xc0,0xf9,0xa4,
0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,
0xc0,0x86,0x8e,0xbf,0x7f};
unsigned char code SMG_IsDot[10] = {0x40,0x79,0x24,
0x30,0x19,0x12,0x02,0x78,0x00,0x10};
void SelectHC573(unsigned char channel)
{
switch(channel)
{
case 4:
P2=(P2 & 0x1f) | 0x80;
break;
case 5:
P2=(P2 & 0x1f) | 0xa0;
break;
case 6:
P2=(P2 & 0x1f) | 0xc0;
break;
case 7:
P2=(P2 & 0x1f) | 0xe0;
break;
case 0:
P2=(P2 & 0x1f) | 0x00;
break;
}
}
void DelaySMG(unsigned int t)
{
while(t--);
}
void DisplaySMG_Bit(unsigned char pos,unsigned char value)
{
SelectHC573(7);
P0=0xff;
SelectHC573(6);
P0=0x01<<pos;
SelectHC573(7);
P0=value;
}
void DisplaySMG_Temp()
{
DisplaySMG_Bit(7,SMG_NoDot[12]);
DelaySMG(100);
DisplaySMG_Bit(6,SMG_NoDot[temp%10]);
DelaySMG(100);
DisplaySMG_Bit(5,SMG_IsDot[(temp/10)%10]);
DelaySMG(100);
DisplaySMG_Bit(4,SMG_NoDot[(temp/100)%10]);
DelaySMG(100);
DisplaySMG_Bit(3,0xff);
DelaySMG(100);
DisplaySMG_Bit(2,0xff);
DelaySMG(100);
DisplaySMG_Bit(1,0xff);
DelaySMG(100);
DisplaySMG_Bit(0,0xff);
DelaySMG(100);
}
void Delay(unsigned int t)
{
while(t--)
{
DisplaySMG_Temp();
}
}
void DA18B10()
{
unsigned char LSB,MSB;
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Delay(1000);
init_ds18b20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
init_ds18b20();
temp=0x0000;
temp=MSB;
temp<<=8;
temp=temp | LSB; //整合成16位的整数
if((temp & 0xf800)==0x0000)
{
temp>>=4; //移出小数,对整数部分计算
temp=temp*10; //放大10部,然后加上小数部分
temp=temp+(LSB & 0x0f)*0.625;
}
}
void main()
{
while(1)
{
DisplaySMG_Temp();
DA18B10();
}
}