DS18B20是一款由Maxim Integrated(原Dallas Semiconductor)生产的数字温度传感器,以其高精度、低功耗、灵活的接口方式和易于使用的特性,在各种温度监测应用中被广泛采用。
以下是DS18B20的详细介绍:
DS18B20因其灵活性和可靠性,被广泛应用于多种领域,包括但不限于:
使用DS18B20通常需要遵循一定的通信协议,包括初始化、搜索传感器、读取或设置寄存器等步骤。在编程时,开发者需编写相应的代码来控制单总线的时序,或者利用已有的库函数(如Arduino、Raspberry Pi等平台上的库)来简化操作。通过简单的函数调用,即可读取到当前的温度值。
实验板上的DS18B20模块接在单片机的P3.7 IO口上,在插入DS18B20芯片时,圆弧朝上插入,具体效果可以看上面图片。
DS18B20的温度检测与数字数据输出全集成于一个芯片之上,从而抗干扰力更强。
它的一个工作周期可分为两个部分,温度检测和数据处理。
DS18B20内部有三种形态的存储器:
(1) ROM只读存储器:用于存放 DS18B20ID 编码,其前 8 位是单线系列编码(DS18B20 的编码是19H),后面 48 位是芯片唯一的序列号,最后8位是以上56的位的 CRC 码(冗余校验),数据在芯片出厂时设置不可由用户更改。DS18B20 共 64 位 ROM(8+48+8)。
(2) RAM数据暂存器:用于内部计算和数据存取,数据在掉电后丢失,DS18B20 共 9 个字节 RAM,每个字节为 8 位。第 1、 2 个字节是温度转换后的数据值信息,第 3、 4 个字节是用户 EEPROM(常用于温度报警值储存)的镜像。在上电复位时其值将被刷新。第 5 个字节则是用户第 3 个 EEPROM的镜像。第 6、 7、 8 个字节为计数寄存器,是为了让用户得到更高的温度分辨率而设计的,同样也是内部温度转换、计算的暂存单元。第 9 个字节为前 8 个字节的 CRC 码。
(3) EEPROM非易失性记忆体:用于存放长期需要保存的数据。比如: 上下限温度报警值和校验数据,DS18B20共有3个字节的EEPROM,并在 RAM 都存在镜像,以方便用户操作。
DS18B20默认工作在12位分辨率模式,转换后得到的12位数据,存储在DS18B20的两个8比特的RAM中(最前面的两个字节),二进制中的前面5位是符号位,如果测得的温度大于0,这5位为0,只要将测到的数值乘于0.0625即可得到实际温度;如果温度小于0,这5位为1,测到的数值需要取反加1再乘于0.0625即可得到实际温度。
数据提取也可以使用位运算,读取出来的数据是2个字节一共16位(H和L),最低4位是小数位,剩下的是整数位。如果读取的数据是负数,需要-1再取反即可得到真实数据。
例如:
int temp=0;
temp=DS18B20_ReadTemp(); //读取一次DS18B20采集的温度(返回H+L位)
if(temp<0) //如果温度是负数
{
temp=temp-1;
temp=~temp;
printf("DS18b20=-%d.%d\r\n",temp>>4,temp&0xF);
}
else
{
printf("DS18b20=%d.%d\r\n",temp>>4,temp&0xF);
}
下面代码演示了循环读取DS18B20温度的过程,在主函数里1秒的间隔读取一次温度。
在编写DS18B20时序代码时,要注意时间的把控。
当前实验板的环境:采用STC90C516RD单片机,晶振是12MHZ,工作在12T模式下,代码中执行一条i++语句大概消耗的时间是12us。 程序中的延时时间,都是通过该时间推算的,如果程序要移植到其他单片机上,要注意时间的问题。
(硬件平台说明:CPU是STC90C516RD、晶振频率12MHZ 、工作在12T模式下、一个机器周期为1us时间)
示例代码:
#include <reg51.h>
/*DS18B20硬件接口: P3.7*/
sbit DS18B20_GPIO=P3^7;
int DS18B20_ReadTemp(void);
/*
说明: 在12MHZ晶振下,12T模式下,i++消耗的时间差不多是12us
*/
/*
函数名称:u8 DS18B20_Init(void)
函数功能:向DS18B20发送复位脉冲,并检测应答信号
返 回 值:1表示失败,0表示成功
说明: 51单片机IO口默认输出高电平
*/
u8 DS18B20_ResetSignal(void)
{
u8 i=0;
//1. 发送复位信号
DS18B20_GPIO=0;//将总线拉低480us
i=50;
while(i--){} //延时600us ,最少480us
i=0;
DS18B20_GPIO=1;//然后释放(拉高)总线,如果DS18B20做出反应会将在15us~60us后总线拉低
//2. 等待DS18B20拉低总线
while(DS18B20_GPIO)
{
i++;
if(i>10)return 1;//失败 ,大概120us
}
//3. 等待DS18B20释放总线
i=0;
while(DS18B20_GPIO==0) //60us~240us
{
i++;
if(i>20)return 1;//失败,大概240us
}
return 0;//初始化成功
}
/*
函数名称:u8 DS18B20_WriteByte(void)
函数功能:向DS18B20写入一个字节的数据
函数形参:写入的字节数据
*/
void DS18B20_WriteByte(u8 byte)
{
u16 i=0,j=0;
for(j=0;j<8;j++)
{
DS18B20_GPIO=0;//每写入一位数据之前先把总线拉低1us
i++; //+1消耗的时间是12us
DS18B20_GPIO=byte&0x01;//然后写入一个数据,从最低位开始
i=6;
while(i--){}//持续时间最少60us,这里大概72us
DS18B20_GPIO=1;//然后释放总线
byte>>=1;//继续发送
}
}
/*
函数名称:u8 DS18B20_ReadByte(void)
函数功能:从DS18B20读取一个字节的数据
返 回 值:读到的数据
*/
u8 DS18B20_ReadByte(void)
{
u8 byte=0;
u16 i=0,j=0;
for(j=0;j<8;j++)
{
DS18B20_GPIO=0;//先将总线拉低1us
i++;//+1消耗的时间是12us
DS18B20_GPIO=1;//然后释放总线
i++;
i++;//至少等待15us的时间,在读取数据
byte>>=1; //先从低位开始接收数据
if(DS18B20_GPIO)byte|=0x80;
i=4; //读取完之后等待48us再接着读取下一个数据
while(i--){}
}
return byte;
}
/*
函数名称:u16 DS18B20_ReadTemp(void)
函数功能:读取一次DS18B20的温度数据
返 回 值:读取的温度值
注意: 返回值要使用有符号的数据类型,因为温度可以返回负数。
*/
int DS18B20_ReadTemp(void)
{
int temp=0;//存放温度数据
u8 TH,TL;
//第一步: 启动温度转换
DS18B20_ResetSignal(); //发送复位脉冲并检测应答信号
DS18B20_WriteByte(0xcc);//跳过ROM操作命令
DS18B20_WriteByte(0x44);//温度转换命令
//第二步: 读取温度
DS18B20_ResetSignal();//发送复位脉冲并检测应答信号
DS18B20_WriteByte(0xcc);//跳过ROM操作命令
DS18B20_WriteByte(0xbe);//发送读取温度命令
TL=DS18B20_ReadByte();//读取温度值共16位,先读低字节
TH=DS18B20_ReadByte();//再读高字节
temp=TH<<8|TL; //合并成16位
return temp;
}
int main()
{
int temp=0;
UART_Init(); //初始化串口波特率为4800
while(1)
{
temp=DS18B20_ReadTemp();
if(temp<0) //如果温度是负数
{
temp=temp-1;
temp=~temp;
printf("DS18b20=-%d.%d\r\n",temp>>4,temp&0xF);
}
else
{
printf("DS18b20=%d.%d\r\n",temp>>4,temp&0xF);
}
DelayMs(1000);
}
}