DS13B20是单总线外设,所以它对时序的要求较高,对DS13B20的使用关键是温度转换、读取以及对读取到的数值进行处理。
DS18B20的基本概述
工作电压:3.0V~5.5V。
测量范围:-55摄氏度~+125摄氏度。
通信方式:单总线,数据线接上拉电阻,使总线空闲时处于高电平。
转换精度:9~12位分辨率可调,默认为12位,即分辨率是0.0625。
转换时间:典型值200ms。
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中的数据。
基本流程:【1】DS13B20复位:通过提供的驱动程序中的init_ds18b20对DS13B20进行初始化。
【2】写入字节0XCC:这是跳过ROM指令操作,由于蓝桥杯开发板上只有一个DS18B20,无需匹配ID,所以跳过此过程,直接进行温度转换。
【3】写入字节0x44:开始温度转换指令。
【4】延时700-900ms:温度转换需要时间,跳过整个时间,否则读取到的数值会出错。
【5】再次复位D13B20.
【6】跳过ROM指令。
【7】写入0XBE,读取高速暂存器:温度转换完之后,数据存放在高度暂存器的第1和第0字节,存储区一共有九个字节。
【8】读取暂存器中的第0 字节(LSB)和第1字节(MSB):存放在暂存器中的数据有16位,LSB与MSB分别存放高八位以及低八位。
【9】DS13B20复位,告诉DS18B20数据读取结束。
【10】将LSB、MSB整合为一个16位数据。
【11】判断读取结果的符号。(通过高五位进行判断)
数据处理
DS18B20以16位带符号位拓展的二进制补码形式读出,低4位位小数,中间7位整数,高五位为符号位。
分辨率位0.0625,读出数据位正温度是,将LSB、MSB整合城的16位整数,乘以0.0625、为负温度时取反加以后再乘以0.0625。
若不许要小数部分,直接将低4位移走即可,整数部分无需换算。
注意
在使用底层驱动程序时需注意看时钟周期是否符合,蓝桥杯单片机的时钟周期为1T,需按照时钟周期倍数关系,改动驱动中的延时,如给的是10T的,则需要延长10倍。
实验用到了onewire头文件,需要在onewire.h文件中将onewire.c文件中函数变量进行声明(特别是我们有用到的函数)。
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
unsigned char rd_temperature(void); //; ;
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
实验部分
实现功能:关闭蜂鸣器,将DS13B20整数部分和一位小数。
#include "reg52.h"
#include "onewire.h"
sbit HC138_A = P2^5;
sbit HC138_B = P2^6;
sbit HC138_C = P2^7;
sbit buzz = P0^6;
#define uchar unsigned char
#define uint unsigned int
void Delay(unsigned int t);
void Init74HC138(unsigned char n);
void buzzoff();
void Displaybit(unsigned char pos,unsigned char value);
void DisplayShow(unsigned int dat);
void Read_Tem();
uchar code SMGNODOT[18]={0xc0,0xf9,0xa4,
0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,
0xc0,0x86,0x8e,0xbf,0x7f};
uchar code SMGDOT[10] = {0x40,0x79,0x24,
0x30,0x19,0x12,0x02,0x78,0x00,0x10};
uint Tdat;
void main()
{
buzzoff();
while(1)
{
Read_Tem();
DisplayShow(Tdat);
}
}
void DelaySMG(unsigned int t)
{
while(t--);
}
void Delay(unsigned int t)
{
while(t--)
{
DisplayShow(Tdat);
}
}
void Init74HC138(unsigned char n)
{
switch(n)
{
case 4:
HC138_A = 0;
HC138_B = 0;
HC138_C = 1;
break;
case 5:
HC138_A = 1;
HC138_B = 0;
HC138_C = 1;
break;
case 6:
HC138_A = 0;
HC138_B = 1;
HC138_C = 1;
break;
case 7:
HC138_A = 1;
HC138_B = 1;
HC138_C = 1;
break;
case 8:
HC138_A = 0;
HC138_B = 0;
HC138_C = 0;
break;
}
}
void buzzoff()
{
Init74HC138(5);
buzz = 0;
}
void Displaybit(unsigned char pos,unsigned char value)
{
Init74HC138(7);
P0= 0XFF;
Init74HC138(6);
P0=0X01<<pos;
Init74HC138(7);
P0=value;
}
void DisplayShow(unsigned int dat)
{
Displaybit(7,SMGNODOT[dat%10]);
DelaySMG(100);
Displaybit(6,SMGDOT[(dat/10)%10]);
DelaySMG(100);
Displaybit(5,SMGNODOT[(dat/100)%10]);
DelaySMG(100);
Displaybit(4,0xff);
DelaySMG(100);
Displaybit(3,0xff);
DelaySMG(100);
Displaybit(2,0xff);
DelaySMG(100);
Displaybit(1,0xff);
DelaySMG(100);
Displaybit(0,0xff);
DelaySMG(100);
}
void Read_Tem()
{
uchar LSB,MSB;
init_ds18b20(); //初始化DS13B20
Write_DS18B20(0xcc);//跳过ROM指令
Write_DS18B20(0x44);//开始温度转换
DelayDis(900);
init_ds18b20();
Write_DS18B20(0xcc);//跳过ROM指令
Write_DS18B20(0xBE);//读取高速暂存器
LSB = Read_DS18B20();
MSB = Read_DS18B20();
init_ds18b20();
Tdat = 0x0000;
Tdat = MSB;
Tdat <<= 8;
Tdat = Tdat | LSB;
if((Tdat & 0xf800) == 0x0000)判断高五位是否为一
{
Tdat >>= 4;
Tdat = Tdat*10;
Tdat = Tdat + (LSB&0x0f)*0.625;
}
}
如果无需对小数部分进行显示,可以将Read_Tem()修改为
void Read_Tem()
{
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();
Tdat = MSB;
Tdat = (Tdat<< 8) | LSB;
Tdat >>= 4;
显示函数也要进行相应的改动
// An highlighted block
var foo = 'bar';
Displaybit(7,SMGNODOT[dat%10]);
DelaySMG(100);
Displaybit(6,SMGNODOT[dat/10]);
DelaySMG(100);
Displaybit(5,0xff);
DelaySMG(100);
```