一,DS18B20
DS18B20是一种常见的数字温度传感器,相比模拟温度传感器,它能直接输出温度值。测温范围—55°C~125°C,采用单总线通信,支持寄生供电(提供工作电压与传输数据可同用一条线,使用寄生供电时需要采用强上拉输出电流)。
内部主要元件有:ROM:一条总线中可以连接多个DS18B20,这个ROM存储ID号相当与DS18B20的地址,用于通信寻址,在蓝桥杯实训平台只有一个DS18B20,所以可以跳过寻址这一步。
SCRATCHPAD:本质就是一个暂存器,用于与总线进行交互,测量到的温度回存储在里面,作为一个RAM断电时也会复位。
读取的温度回放在该寄存器的第0位也就是LSB(低8位)和第1位也就是MSB(高8位),两者合成一个16位的数据就是测量的温度。在数据处理中这16位的数据以补码的形式读出:高5位为符号位(全为1时为负,全为0是为正),中间7位为整数部分,低4位为小数部分。
读取温度操纵流程:1,温度转化
1)DS18B20复位。
2)写入0xcc,跳过ROM指令。
3)写入0x44,开始温度转化。
4)延时,如果不延时读取温度时会读取到上次的温度。
2,温度读取
1)DS18B20复位。
2)写入0xcc,跳过ROM指令。
3)写入0xbe,读取SCRATCHPAD。
4)读取第0位和第1位,在读取温度时是按位读的。
二,代码部分
1,onewire.c
这一部分代码包含DS18B20初始化函数,写操作函数,读操作函数
#include "reg52.h"
sbit DQ = P1^4;
void Delay_OneWire(unsigned int t) /
{
while(t--);
}
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(50);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(50);
}
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(50);
}
return dat;
}
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(120);
DQ = 0;
Delay_OneWire(800);
DQ = 1;
Delay_OneWire(100);
initflag = DQ;
Delay_OneWire(50);
return initflag;
}
2,onewire,h
#ifndef __ONEWIRE_H
#define __ONEWIRE_H
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
3,DS18B20
#include <reg52.h>
#include <intrins.h>
#include <absacc.h>
#include <onewire.h>
unsigned char SMGnotdotduanma[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char SMGdotduanma[]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e};
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void Delay(unsigned int t)
{
while(t--);
}
void SMGDisplay(unsigned char pos,unsigned char val)
{
XBYTE[0XC000]=0X01 << pos;
XBYTE[0XE000]=val;
}
void SMGWorking(int temp)
{
SMGDisplay(7,SMGnotdotduanma[temp%10]);
Delay1ms();
SMGDisplay(6,SMGdotduanma[temp/10%10]);
Delay1ms();
SMGDisplay(5,SMGnotdotduanma[temp/100]);
Delay1ms();
SMGDisplay(4,0xff);
Delay1ms();
SMGDisplay(3,0xff);
Delay1ms();
SMGDisplay(2,0xff);
Delay1ms();
SMGDisplay(1,0xff);
Delay1ms();
SMGDisplay(0,0xff);
Delay1ms();
}
void Convert_18B20()
{
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay(500);
}
float Read_18B20()
{
int temp;
float T;
unsigned char LSB,MSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB=Read_DS18B20();
MSB=Read_DS18B20();
temp=(MSB << 8) | LSB;
T=temp/16.0;
return T;
}
void main()
{
XBYTE[0x8000]=0xff;
while(1)
{ float T;
Convert_18B20();
T=Read_18B20();
SMGWorking(T*10);
}
}
段码部分:由于DS18B20能读取小数,所以我们这里不仅引用了普通的段码还引用了带小数点的 段码。由没有小数点段码减去0x80得到。
SMGWorking(T*10):把接收到的温度保留一位小数,显示在后3位数码管。把接收的温度乘上10,是因为我们把T为float型,为了能接收温度的小数部分。乘10为了可以取出小数点的后一位。
Convert_18B20():温度转化函数。
Read_18B20():读取温度函数和数据处理,定义为float函数。temp=(MSB << 8) | LSB;用于把低4位和高4位整合以一个16位的补码形式取出,在把2个八位二进制数整合成一个16位二进制数时我们使用了temp=(MSB << 8) | LSB;这里使用的让小数部分于整数部分整合到一起,但是我们这里时把temp定义成int型,int时没有小数部分的,所以int的最后一位权重是2的0次方,但是我们原本LSB最后一位的权重是2的-4次方,说明我们这样操作相当于把LSB与MSB整合的这个16位二进制数左移了4位才得到temp,所以我们要除16。0,相当于把temp的二进制数右移了4,这样才能保留它原有的小数位。
三,小结
若读取的温度一直为85°C或者0°C,也就是默认温度,可以考虑修改初始化函数,写操作函数,读操作函数,把延迟增加10倍或者12倍。若一开始打开的一瞬间是上次测量的结果,可以将温度转换函数里面的延时函数增加。