DS18B20是最常见的数字温度传感器,有着诸多优点,比如:体积小;精度高(12位时精度可以达到0.625摄氏度,出厂默认12位);接线简单,无需外围短路;封装形式多样,能满足不同应用需求等等。DS18B20工作时序十分复杂,信号传输只在微妙之间,稍有不慎(例如延时函数的使用不够恰当)就可能导致其整个传感器的工作时序混乱。因此,在写DS18B20的控制程序时一定要弄清工作时序并使用合适的延时函数。
引脚图
void dsinit()//初始化
{
DQ=0;
Delay500us();
DQ=1;
Delay500us();
}
uchar read()
{
uchar dat;
uchar i;
for(i=0;i<8;i++)
{
DQ=0;
_nop_();
dat>>=1;//循环右移补零
//根据芯片选择读取数据低位到高右移 反之左移
DQ=1;
if(DQ==1)
{
dat|=0x80;
}
Delay100us();//读的较慢至少60us 延时设置长
}
return dat;
}
void write(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&0x01;//0100 0100&0000 0001=0000 0000
Delay100us();
DQ=1;
dat>>=1;//循环右移补零
//根据芯片选择读取数据低位到高右移 反之左移
}
}
温度数据存储在高八位的低四位,低八位的前四位,分别读取再合并
uchar temget()//温度获取
{
uchar temp;
uchar low,high;
dsinit();
write(0xcc);//忽略rom指令
write(0x44);//温度转换指令
Delay500us();Delay500us();
dsinit();
write(0xcc);//忽略rom指令
write(0xbe);//读取暂存器的内容
low=read();
high=read();
temp=((high<<4)|(low>>4));
return temp;
}
验证后的完整程序如下在半小时程序基础上修改,本程序不需要按键扫描
#include <STC15F2K60S2.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit s7=P3^0;
sbit s6=P3^1;
sbit DQ=P1^4;
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
//0 1 2 3 4 5 6 7 8 9 - 灭
uchar code dottab[]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};
//带小数点的数字,程序主要用第二位,第六位 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
uchar yi,er,san,si,wu,liu,qi,ba;
void Delay1ms(uchar ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void allinit();
void keyscan();
void dsinit();
void Delay100us();
void Delay500us();
void write(uchar dat);
uchar read();
uchar temget();
void main()
{
uchar tem;//温度
allinit();
yi=11,er=11,san=11,si=11,wu=11,liu=6,qi=7,ba=8;
while(1)
{
tem=temget();
liu=tem/100;
qi=tem%100/10;
ba=tem%10;
display1( yi, er);
display2( san, si);
display3( wu, liu);
display4( qi, ba);
keyscan();
}
}
void Delay100us() //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 39;
do
{
while (--j);
} while (--i);
}
void Delay500us() //@12.000MHz
{
unsigned char i, j;
i = 6;
j = 211;
do
{
while (--j);
} while (--i);
}
uchar temget()//温度获取
{
uchar temp;
uchar low,high;
dsinit();
write(0xcc);//忽略rom指令
write(0x44);//温度转换指令
Delay500us();Delay500us();
dsinit();
write(0xcc);//忽略rom指令
write(0xbe);//读取暂存器的内容
low=read();
high=read();
temp=((high<<4)|(low>>4));
return temp;
}
uchar read()
{
uchar dat;
uchar i;
for(i=0;i<8;i++)
{
DQ=0;
_nop_();
dat>>=1;//循环右移补零
//根据芯片选择读取数据低位到高右移 反之左移
DQ=1;
if(DQ==1)
{
dat|=0x80;
}
Delay100us();//读的较慢至少60us 延时设置长
}
return dat;
}
void write(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DQ=0;
DQ=dat&0x01;//0100 0100&0000 0001=0000 0000
Delay100us();
DQ=1;
dat>>=1;//循环右移补零
//根据芯片选择读取数据低位到高右移 反之左移
}
}
void dsinit()
{
DQ=0;
Delay500us();
DQ=1;
Delay500us();
}
void Delay1ms(uchar ms) //@12.000MHz 最多延时255ms
{
unsigned char i, j;
uchar k;
for(k=ms;k>0;k--)
{
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
}
void display1(uchar yi,uchar er)
{
P2=0XC0;
P0=0X01;
P2=0XE0;
P0=tab[yi];
Delay1ms(2);
P2=0XC0;
P0=0X02;
P2=0XE0;
P0=tab[er];
Delay1ms(2);
}
void display2(uchar san,uchar si)
{
P2=0XC0;
P0=0X04;
P2=0XE0;
P0=tab[san];
Delay1ms(2);;
P2=0XC0;
P0=0X08;
P2=0XE0;
P0=tab[si];
Delay1ms(2);
}
void display3(uchar wu,uchar liu)
{
P2=0XC0;
P0=0X10;
P2=0XE0;
P0=tab[wu];
Delay1ms(2);
P2=0XC0;
P0=0X20;
P2=0XE0;
P0=tab[liu];
Delay1ms(2);
}
void display4(uchar qi,uchar ba)
{
P2=0XC0;
P0=0X40;
P2=0XE0;
P0=tab[qi];
Delay1ms(2);
P2=0XC0;
P0=0X80;
P2=0XE0;
P0=tab[ba];
Delay1ms(2);
}
void allinit()
{
P2=0X80;
P0=0XFF;//关LED
P2=0XC0;
P0=0XFF;
P2=0XE0;
P0=0XFF;//关数码管
P2=0XA0;
P0=0X00;//关蜂鸣器 继电器
}
void keyscan()
{
if(s7==0)
{
Delay1ms(5);//延时消抖
if(s7==0)
{
yi=11,er=11,san=11,si=11,wu=11,liu=11,qi=11,ba=11;//所有数码管灭
}
while(!s7);
}
else if(s6==0)
{
Delay1ms(5);
if(s6==0)
{
yi=0,er=0,san=0,si=0,wu=0,liu=0,qi=0,ba=0;//所有数码管为0
}
while(!s6);
}
}