在51单片机中,DS18B20是一个十分重要的外设,它是一个温度传感器,可以读取温度并以16位的数据输出。这个数据由四位符号位,7位整数位和4位小数位组成。当符号位都是0的时候,温度是零上温度;当符号位都是1的时候,表示温度是零下温度。
在51单片机中运用DS18b20模块,有一套较为固定的用法,首先,我们先引入DS18B20厂家所提供的底层驱动代码,写好头文件。第二部,我们需要先初始化ds18b20,接着向模块里写入0xcc,跳过ROM指令,接着写入0x44,0x44将收集到的温度数据转换,这需要大概800ms的时间,所以我们后面可以跟上一个Delay函数,这个函数由自己编写或者使用isp软件提供的方法生成。延时结束以后我们在复位一下DS18b20传感器,接着继续写入0xcc,跳过ROM指令,在写入0xbe,读取告诉暂存器。在最开始我们设立了俩个变量,LSB与HSB,LSB是用来暂存数据的第一字节的,HSB是用来暂存数据的第二字节的。我们先将数据同时赋给这俩个变量,然后用一个在外面创建的int 类型全局变量Temp来接受数据HSB,接着将HSB左移8位,那么就会空出8位为0,接着或上LSB的数值,0或上任何数就是任何数,于是现在Temp中的数值就是温度的数值了。
接着,我想要得到一个由两位整数和一位小数组成的数据,要如何实现呢?首先,我们先来判断该数据的正负,我们先将该数据与上0xf800,判断符号位是否为0,若符号位都为0,表示温度为正数,则if通过,进入下面的语句,先将Temp右移4位,舍弃4位小数位,保留整数位,接着将Temp放大十倍,有人会疑惑为什么放大十倍,若我们的数据假设是23.3,这是一个浮点数,不好处理,我们将数据放大10倍以后就是一个整数了,处理起来比较容易。后面再让LSB与上0x0f,取出LSB的低4位,再乘以0.0625(分辨率)再乘以10,最终加上已经是整数的Temp,就得到了一个要求的小数。
void DS18b20()
{
unsigned char LSB,HSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay1(1000);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
HSB = Read_DS18B20();
Temp = HSB;
Temp = (Temp<<8) | LSB;
if((Temp & 0xf800) == 0x0000)
{
Temp >>= 4;
Temp *= 10;
Temp = Temp + (LSB & 0x0f)*0.625;
}
}
整体代码最终实现如图所示
main.c
#include <REG52.H>
#include "onewire.h"
unsigned int Temp;
code unsigned char SMG1[20] = {0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e };
code unsigned char code SMG2[20] = {0xc0, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10, 0x03, 0x46, 0x21, 0x06,0x0e};
void Delay(unsigned int t)
{
while(t--);
}
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 = 0xff;
break;
}
}
void SMG_Bit(unsigned char pos,unsigned char dat)
{
SelectHC573(6);
P0 = 0x01 << pos;
SelectHC573(7);
P0 = dat;
SelectHC573(0);
}
void Init_SMG(unsigned char dat)
{
SelectHC573(6);
P0 = 0xff;
SelectHC573(7);
P0 = dat;
SelectHC573(0);
}
void SHOWSMG()
{
SMG_Bit(7,SMG1[Temp%10]);
Delay(100);
SMG_Bit(6,SMG1[(Temp%100)/10]);
Delay(100);
SMG_Bit(5,SMG1[(Temp/100)%10]);
Delay(100);
Init_SMG(0xff);
Delay(100);
}
void Delay1(unsigned int t)
{
while(t--)
{
SHOWSMG();
}
}
void DS18b20()
{
unsigned char LSB,HSB;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
Delay1(1000);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
HSB = Read_DS18B20();
Temp = HSB;
Temp = (Temp<<8) | LSB;
if((Temp & 0xf800) == 0x0000)
{
Temp >>= 4;
Temp *= 10;
Temp = Temp + (LSB & 0x0f)*0.625;
}
}
void main()
{
while(1)
{
DS18b20();
SHOWSMG();
}
}
onewire.h
#ifndef _ONEWIRE_H
#define _ONEWIRE_H
#include "reg52.h"
sbit DQ = P1^4;
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif
onewire.c
#include "onewire.h"
void Delay_OneWire(unsigned int t)
{
unsigned char i;
while(t--){
for(i=0;i<12;i++);
}
}
//
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);
}
//
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;
}
//
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;
}