在开头说明一下:本程序只用了温度测量这一个功能,其他功能并未在此涉及。
鄙人不才,如有错误还望各位大佬指点。
趁这段时间充裕把DS18B20温度传感器的一些东西写一写(主要是程序)。
Dallas半导体公司的数字化温度传感器DS18B20是世界上第一片支持“一线总线”接口的温度传感器,即只有一根数据线。它的适用电压为3V-5V,可程序设定9-12位的分辨率,精度为±0.5℃,测温范围-55℃~+125℃。
DS18B20的使用难点主要在延时时间上,只要把延时搞懂了那么除测温以外的功能也就不难了。相信你们手里都有芯片手册,手册上的时序画的明明白白,我也就不多说废话了,直接上程序
/**************************************
平台STC89C52 晶振11.0592MHz
6位共阴数码管 74HC573锁存器
**************************************/
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f, ///不带小数点0~9
0xbf,0x86,0xdb,0xcf,0xe6,
0xed,0xfd,0x87,0xff,0xef, ///带小数点0~9
0x40,0x00};
uchar tem[2]; ///用来存放两字节的温度
uchar wendu[5]; ///用来存放(正负)十进制的温度
uchar fuhao;
bit flag;
sbit DQ=P2^2; ///传感器的信号线
sbit dula=P2^6; ///数码管段选端
sbit wela=P2^7; ///数码管位选端
void delayus(uchar t)
{
while(t--);
}
void delayms(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void delaynop()
{
_nop_();
}
/***************************************
DS18B20复位函数
***************************************/
void res()
{
DQ=1;
_nop_();
_nop_();
_nop_();
DQ=0;
delayus(90); ///约600us
DQ=1;
delayus(9); ///约70us
flag=DQ; ///若flag为0则复位成功,否则失败
delayus(80); ///约530us
DQ=1;
_nop_();
}
/*************************************
写一个字节函数
*************************************/
void ds18b20_write_byte(uchar dat)
{
uchar i;
bit j;
for(i=8;i>0;i--)
{
j=dat&0x01;
dat=dat>>1;
DQ=1;
_nop_();
if(j==0)
{
DQ=0;
delayus(9); ///约70us
DQ=1;
_nop_();
}
else
{
DQ=0;
_nop_();
_nop_();
_nop_();
DQ=1;
delayus(9);
}
}
}
/************************************
读一个字节函数
************************************/
bit ds18b20_read_bit()
{
bit j;
DQ=1;
_nop_();
DQ=0;
delaynop();
DQ=1;
_nop_();
j=DQ;
delayus(8);
DQ=1;
_nop_();
return j;
}
uchar ds18b20_read_byte()
{
uchar i,j,dat;
for(i=8;i>0;i--)
{
j=ds18b20_read_bit();
dat=(dat>>1)|(j<<7);
}
return dat;
}
/*************************************
开始温度转换函数
*************************************/
void ds18b20_starttempreture()
{
res();
ds18b20_write_byte(0xcc); ///写跳过序列号的命令
ds18b20_write_byte(0x44); ///写开始温度转换的命令
}
/************************************
计算读取温度函数
************************************/
void ds18b20_transtemperature()
{
uint temp_i;
uchar temp;
res();
ds18b20_write_byte(0xcc); ///写跳过序列号的命令
ds18b20_write_byte(0xbe); ///写读取温度的命令
tem[0]=ds18b20_read_byte(); ///温度低位
tem[1]=ds18b20_read_byte(); ///温度高位
_nop_();
fuhao=tem[1]&0xf0;
if(fuhao==0xf0) ///表达式为真则为负
{
if(tem[0]==0x00) ///表达式为真则低位有进位
{
tem[0]=~tem[0]+1;
tem[1]=~tem[1]+1;
}
else
{
tem[0]=~tem[0]+1;
tem[1]=~tem[1];
}
}
if(fuhao==0xf0)
{wendu[0]=20;}
else
{wendu[0]=21;} ///符号位
temp=(tem[1]<<4)|(tem[0]>>4);
wendu[1]=temp%100/10; ///十位
wendu[2]=temp%10; ///个位
temp=tem[0]&0x0f;
temp_i=temp*0.0625*10000;
wendu[3]=temp_i/1000; ///十分位
wendu[4]=temp_i%1000/100; ///百分位
}
/**************************************
数码管显示函数
**************************************/
void display(uchar fu,uchar shi,uchar ge,uchar shifen,uchar baifen)
{
wela=0;
P0=table[fu]; ///显示符号位
dula=1;
dula=0;
P0=0x3e;
wela=1;
wela=0;
delayms(1);
P0=table[shi]; ///显示十位
dula=1;
dula=0;
P0=0x3d;
wela=1;
wela=0;
delayms(1);
P0=table[ge+10]; ///显示个位,带小数点
dula=1;
dula=0;
P0=0x3b;
wela=1;
wela=0;
delayms(1);
P0=table[shifen]; ///显示十分位
dula=1;
dula=0;
P0=0x37;
wela=1;
wela=0;
delayms(1);
P0=table[baifen]; ///显示百分位
dula=1;
dula=0;
P0=0x2f;
wela=1;
wela=0;
delayms(1);
}
/***************************************
主函数
***************************************/
void main()
{
while(1)
{
res();
ds18b20_write_byte(0xcc);
ds18b20_write_byte(0x7f);
if(flag==0)
{
ds18b20_starttempreture();
ds18b20_transtemperature();
display(wendu[0],wendu[1],wendu[2],wendu[3],wendu[4]);
}
else
{
display(20,20,20,20,20);
}
}
}