温度传感器的种类众多,在应用与高精度、高可靠性的场合时DALLAS(达拉斯)公司生产的DS18B20温度传感器当仁不让。超小的体积,超低的硬件开消,抗干扰能力强,精度高,附加功能强,使得DS18B20更受欢迎。对于我们普通的电子爱好者来说,DS18B20的优势更是我们学习单片机技术和开发温度相关的小产品的不二选择。了解其工作原理和应用可以拓宽您对单片机开发的思路。
DS18B20的主要特征:
--全数字温度转换及输出。
-- 先进的单总线数据通信。
--最高12位分辨率,精度可达土0.5摄氏度。
--12位分辨率时的最大工作周期为750毫秒。
--可选择寄生工作方式。
--检测温度范围为–55°C ~+125°C (–67°F ~+257°F)
--内置EEPROM,限温报警功能。
--64位光刻ROM,内置产品序列号,方便多机挂接。
--多样封装形式,适应不同硬件系统。
以下是DS18B20的内部RAM,一共有9位:
其中第四位的Configuration Register(设置寄存器)是用于设置温度控制芯片分辨率的,其内部结构如下:
R1、R2与控制器分辨率关系如下:
控制器对18B20操作流程:
1,复位:首先我们必须对DS18B20芯片进行复位,复位就是由控制器(单片机)给DS18B20单总线至少480uS的低电平信号。当18B20接到此复位信号后则会在15~60uS后回发一个芯片的存在脉冲。
2,存在脉冲:在复位电平结束之后,控制器应该将数据单总线拉高,以便于在15~60uS后接收存在脉冲,存在脉冲为一个60~240uS的低电平信号。至此,通信双方已经达成了基本的协议,接下来将会是控制器与18B20间的数据通信。如果复位低电平的时间不足或是单总线的电路断路都不会接到存在脉冲,在设计时要注意意外情况的处理。
3,控制器发送ROM指令:双方打完了招呼之后最要将进行交流了,ROM指令共有5条,每一个工作周期只能发一条,ROM指令分别是读ROM数据、指定匹配芯片、跳跃ROM、芯片搜索、报警芯片搜索。ROM指令为8位长度,功能是对片内的64位光刻ROM进行操作。其主要目的是为了分辨一条总线上挂接的多个器件并作处理。诚然,单总线上可以同时挂接多个器件,并通过每个器件上所独有的ID号来区别,一般只挂接单个18B20芯片时可以跳过ROM指令(注意:此处指的跳过ROM指令并非不发送ROM指令,而是用特有的一条“跳过指令”)。ROM指令在下文有详细的介绍。
4,控制器发送存储器操作指令:在ROM指令发送给18B20之后,紧接着(不间断)就是发送存储器操作指令了。操作指令同样为8位,共6条,存储器操作指令分别是写RAM数据、读RAM数据、将RAM数据复制到EEPROM、温度转换、将EEPROM中的报警值复制到RAM、工作方式切换。存储器操作指令的功能是命令18B20作什么样的工作,是芯片控制的关键。
5,执行或数据读写:一个存储器操作指令结束后则将进行指令执行或数据的读写,这个操作要视存储器操作指令而定。如执行温度转换指令则控制器(单片机)必须等待18B20执行其指令,一般转换时间为500uS。如执行数据读写指令则需要严格遵循18B20的读写时序来操作。数据的读写方法将有下文有详细介绍。
若要读出当前的温度数据我们需要执行两次工作周期,第一个周期为复位、跳过ROM指令、执行温度转换存储器操作指令、等待500uS温度转换时间。紧接着执行第二个周期为复位、跳过ROM指令、执行读RAM的存储器操作指令、读数据(最多为9个字节,中途可停止,只读简单温度值则读前2个字节即可)。其它的操作流程也大同小异,在此不多介绍。
DS18B20有两种供电方式,一种是VCC供电,另一种被称为寄生电源方式(parasitepower),本文章只讨论VCC供电
DS28B20芯片ROM指令表:
Read ROM(读ROM)[33H](方括号中的为16进制的命令字)
这个命令允许总线控制器读到DS18B20的64位ROM。只有当总线上只存在一个DS18B20的时候才可以使用此指令,如果挂接不只一个,当通信时将会发生数据冲突。
MatchROM(指定匹配芯片)[55H]
这个指令后面紧跟着由控制器发出了64位序列号,当总线上有多只DS18B20时,只有与控制发出的序列号相同的芯片才可以做出反应,其它芯片将等待下一次复位。这条指令适应单芯片和多芯片挂接。
SkipROM(跳跃ROM指令)[CCH]
这条指令使芯片不对ROM编码做出反应,在单总线的情况之下,为了节省时间则可以选用此指令。如果在多芯片挂接时使用此指令将会出现数据冲突,导致错误出现。
SearchROM(搜索芯片)[F0H]
在芯片初始化后,搜索指令允许总线上挂接多芯片时用排除法识别所有器件的64位ROM。
AlarmSearch(报警芯片搜索)[ECH]
在多芯片挂接的情况下,报警芯片搜索指令只对附合温度高于TH或小于TL报警条件的芯片做出反应。只要芯片不掉电,报警状态将被保持,直到再一次测得温度什达不到报警条件为止。
DS28B20芯片存储器操作指令表:
Write Scratchpad(向RAM中写数据)[4EH]
这是向RAM中写入数据的指令,随后写入的两个字节的数据将会被存到地址2(报警RAM之TH)和地址3(报警RAM之TL)。写入过程中可以用复位信号中止写入。
Read Scratchpad(从RAM中读数据)[BEH]
此指令将从RAM中读数据,读地址从地址0开始,一直可以读到地址9,完成整个RAM数据的读出。芯片允许在读过程中用复位信号中止读取,即可以不读后面不需要的字节以减少读取时间。
Copy Scratchpad(将RAM数据复制到EEPROM中)[48H]
此指令将RAM中的数据存入EEPROM中,以使数据掉电不丢失。此后由于芯片忙于EEPROM储存处理,当控制器发一个读时间隙时,总线上输出“0”,当储存工作完成时,总线将输出“1”。在寄生工作方式时必须在发出此指令后立刻超用强上拉并至少保持10MS,来维持芯片工作。
ConvertT(温度转换)[44H]
收到此指令后芯片将进行一次温度转换,将转换的温度值放入RAM的第1、2地址。此后由于芯片忙于温度转换处理,当控制器发一个读时间隙时,总线上输出“0”,当储存工作完成时,总线将输出“1”。在寄生工作方式时必须在发出此指令后立刻超用强上拉并至少保持500MS,来维持芯片工作。
RecallEEPROM(将EEPROM中的报警值复制到RAM)[B8H]
此指令将EEPROM中的报警值复制到RAM中的第3、4个字节里。由于芯片忙于复制处理,当控制器发一个读时间隙时,总线上输出“0”,当储存工作完成时,总线将输出“1”。另外,此指令将在芯片上电复位时将被自动执行。这样RAM中的两个报警字节位将始终为EEPROM中数据的镜像。
Read PowerSupply(工作方式切换)[B4H]
此指令发出后发出读时间隙,芯片会返回它的电源状态字,“0”为寄生电源状态,“1”为外部电源状态。
程序如下:
#include <STC89C51RC.H>
#define uint unsigned int
#define uchar unsigned char
uint temp;
uchar tempH,tempL,aa;
uchar codeDispTab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e};//段码0-9,a-f
bit presence;
sbit DP=P1^6;
sbit LED0=P1^0;
sbit LED1=P1^1;
sbit LED2=P1^2;
sbit LED3=P1^3;
uchar one,two,three,four;
uchar codetable[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0xbf,0xff};//段码0-9,"-",0x00
void mdelay(ucharn)//自减一次约2us
{
while(--n);
}
void display(uchar i)
{
for(;i>0;i--)
{
LED0=0;
if(one==0)//如果百位为0,则不显示
P0=table[11];
else
P0=table[one];
mdelay(10);
LED0=1;
P0=0xff;//每次要注意把P0还原,否则会影响其他灯的亮暗
LED1=0;
if(one==0&&two==0)//如果百位和十位同时为0,则都不显示
P0=table[11];
else
P0=table[two];
mdelay(10);
LED1=1;
P0=0xff;
LED2=0;
P0=table[three]&0x7f;//加小数点
mdelay(10);
LED2=1;
P0=0xff;
LED3=0;
P0=table[four];
mdelay(10);
LED3=1;
P0=0xff;
}
}
void HextoBCD()//18B20的Hex转BCD函数,显示在数码管上
{
if(presence==1)//检测不到18B20数码管就不亮
{
one=11;
two=11;
three=11;
four=11;
}
else
{
temp=tempH*256+tempL;//把tempH和tempL合并成一个数处理
if((temp>>11)&0x01==1)//如果temp是负数
{
one=10;//第一位为负号
temp=0x10000-temp;//负数的值为补码
tempH=temp>>4;
two=tempH/10;//十位
three=tempH%10;//个位
temp=(temp&0x0f)*625;//小数部分先乘以625,再除以1000,等于乘0.625
four=temp/1000;//小数部分再除以1000取最高位,等于乘以0.625
}
else
{
tempH=temp>>4;//如果是正数则右移四位把小数点位移去
one=tempH/100;//百位
two=tempH%100/10;//十位
three=tempH%10;//个位
temp=(temp&0x0f)*625;
four=temp/1000;//小数点位Matrix 25 64-122-164
}
}
}
uchar readbyte()//读是从高位开始读,这个和资料上是反过来的,请注意!
{
uchar i;
uchar rd=0;
for(i=0;i<8;i++)
{
DP=0;//先低电平后高电平,形成一个读信号
DP=1;//高
mdelay(4);//延时约10us
if(DP)rd|=0x01<<i;
mdelay(20);//延时40us
}
return(rd);
}
void writebyte(uchar wb)//写是从低位开始写
{
uchar i;
for(i=8;i>0;i--)
{
DP=1;//先高电平后低电平,形成一个写信号
DP=0;
mdelay(8);//延时15us
DP=wb&0x01;
mdelay(25); // 延时45us
DP=1;
wb=wb>>1;
}
}
voidreset()//复位函数
{
DP=0;//P1^6置低电平
mdelay(240);//低电平维持约480us
DP=1;//P1^6置高电平
mdelay(25);//等待15-60us,等待DS18B20响应
presence=DP;//找到18B20则DP=0;否则DP=1
mdelay(200);
}
void writetoRAM(uchar CR) //CR-Configure register
{
reset();
writebyte(0xcc); //跳过写ROM
writebyte(0x4e);//向RAM中写数据
writebyte(0x41);//set TH = 65
writebyte(0x00);//set TL = 0
writebyte(CR); //set configureregister:0x1f-9bit;0x3f-10bit;
//0x5f-11bit;0x7f-12bit
reset();
}
void gettemp() //温度转换
{
reset();
writebyte(0xcc); //跳过写ROM
writebyte(0x44);//温度转换,大约需要500us
mdelay(250);//等待500us温度转换完成,温度转换完后18B20会向总线会输出1
reset();
writebyte(0xcc); //跳过写ROM
writebyte(0xbe);//读RAM中数据
tempL=readbyte();//第一个RAM中数据读进tempL
tempH=readbyte();//第二个RAM中数据读进tempH
reset(); //复位信号中止读取RAM数据
}
void copyRAMtoEE() //把RAM中的TH,TL,CONFIGUREREGISTER数据复制到EEPROM中
{
reset();
writebyte(0xcc);
writebyte(0x48);//RAM中数据复制到EEPROM
mdelay(100);//当数据完全复制到EEPROM中时总线会输出1
}
void main()
{
if((PCON&0x10)==0)//如果POF位=0
{
PCON=PCON|0x10;//将POF位置1
ISP_CONTR=0x60;//软复位,从ISP监控区启动
}
else
{
PCON=PCON&0xef;//将POF位清零
}
mdelay(100);
presence=1;//presence代表是否DS18B20是否挂在总线上
writetoRAM(0x7f);//分辨率为12位
copyRAMtoEE();//把RAM数据复制到EEPROM
gettemp(); //温度转换和获得温度
display(50);
while(1)
{
gettemp();
HextoBCD();
display(8);
}
}