0%

51单片机——DS18B20简要记录

对DS18B20的使用作一个简单记录。

DS18B20内部组成

64位ROM

  • 8位FAMILY CODE:DS18B20的64位ROM中的前8位统一为28H

  • 48位SERIAL NUMBER:唯一序列号;

  • 8位CRC:对ROM中前56位编码的校验码。

高速暂存存储器

  • 字节0:存储温度值的低8位;

  • 字节1:存储温度值的高8位;

  • 字节2:存储报警触发的温度上限值,也可作为一般用途的存储器(EEPROM)使用;

  • 字节3:存储报警触发的温度下限值,也可作为一般用途的存储器(EEPROM)使用;

  • 字节4:配置寄存器;通过R0位和R1位可以设置转换分辨率,默认分辨率为12位;

  • 字节5~7:保留字段;

  • 字节8:CRC。

DS18B20温度数据

获取温度

DS18B20以16位补码的形式将温度数据存储于温度寄存器,单位为摄氏度。

11位15位为符号位,温度值为正数时,符号位均为0;温度值为负数时,符号位均为1

剩下的11位当中,对于12位分辨率,所有位全部有效;对于11位分辨率,0位无意义;对于10位分辨率,0位1位无意义;对于9位分辨率,0位1位2位无意义。

12位分辨率的精度为0.0625摄氏度;11位分辨率的精度为0.125摄氏度;10位分辨率的精度为0.25摄氏度;9位分辨率的精度为0.5摄氏度。

温度计算

当温度值为正数时,将温度寄存器从0位10位的11位二进制数转换为十进制数,再与分辨率的精度相乘,即可得到实际温度值;当温度值为负数时,先将温度寄存器的11位二进制补码转换为原码,再将原码转换为十进制数,最后再与分辨率的精度相乘,即可得到实际温度值。

温度阈值

对于两个温度阈值触发寄存器(THTL),由于均为8位寄存器,因此仅能将温度寄存器4位11位所表示的温度值与设定的阈值进行比较。

对于正数,7位0;对于负数,7位1

DS18B20操作指令

ROM指令

当同一总线上挂载多个DS18B20时,需要通过ROM指令来控制某个DS18B20;当总线上只挂载单个DS18B20时,使用跳过ROM指令(0xCC)即可。

  • 读ROM0x33):读取DS18B20的64位ROM中的编码;
  • ROM匹配0x55):发出此指令后,接着发出64位ROM中的编码,选中总线上与编码对应的DS18B20,为下一步对该DS18B20的读写作准备;
  • 搜索ROM0xF0):用于确定挂载在同一总线上DS18B20的个数和识别64位ROM地址,为操作各器件作准备;
  • 跳过ROM0xCC):忽略64位ROM地址,直接向DS18B20发送温度转换指令;
  • 警报搜索0xEC):查找总线上温度超过阈值的DS18B20。

RAM指令

  • 温度转换0x44):启动DS18B20进行温度转换,转换结果存储于内部的9字节RAM中;
  • 读暂存器0xBE):读取内部RAM中9字节的内容;
  • 写暂存器0x4E):发出此指令向内部RAM的第3、4字节写温度上、下限的阈值,紧跟该命令之后,发送两字节的数据;
  • 复制暂存器0x48):将内部RAM中第3、4字节的内容复制到EEPROM中;
  • 重调EEPROM0xB8):将EEPROM中相应的内容恢复到RAM中的第3、4字节;
  • 读供电方式0xB4):读DS18B20的供电模式;若为寄生供电,则DS18B20发送0;若为外接电源供电,则DS18B20发送1

DS18B20时序

初始化DS18B20

  • MCU拉低电平最少480us,产生复位脉冲,然后释放总线;
  • DS18B20检测到请求后,拉低电平60~240us表示应答;
  • 在DS18B20拉低电平的60~240us期间,MCU读取总线的电平,若为低电平,则表示DS18B20初始化成功;
  • 在DS18B20拉低电平60~240us之后,释放总线。

写时序

  • 0:MCU拉低电平60~120us,然后释放总线;
  • 1:MCU拉低电平大于1us,然后在15us内释放总线。

在写时序起始后15~60us内,DS18B20处于电平采样状态;若此时总线为高电平,则向DS18B20写1;若此时总线为低电平,则向DS18B20写0

两次写周期之间最少间隔1us。

读时序

MCU拉低电平最少1us,然后释放总线;DS18B20检测到电平被拉低1us后,若发送0,则将电平拉低直到读周期结束,若发送1,则释放总线。读时序必须最少需要60us,且两次读时序之间最少需要间隔1us。

举个栗子

通过DS18B20采集环境温度,并在开发板的数码管模块上的左三位显示(带1位小数)。

MCU:AT89S52

#include <reg52.h>

sbit DS=P2^2;
sbit DU=P2^6;
sbit WE=P2^7;

unsigned char table0[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //无小数点
unsigned char table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //有小数点
unsigned int temp;

void Delay(unsigned int x) //延时一定时间
{
unsigned int i;
while(x)
{
i=200;
while(i>0)
{
i--;
}
x--;
}
}

void DS18B20_init() //DS18B20初始化
{
unsigned int i;
DS=0; //MCU拉低电平最少480us,产生复位脉冲,然后释放总线
i=103; //延时480us~960us
while(i>0)
{
i--;
}
DS=1; //释放总线
i=4; //等待15~60us,然后DS18B20拉低电平60~240us表示应答
while(i>0)
{
i--;
}
while(DS);
}

bit Read_bit() //读取1比特的数据;“读”时序最少需要60us
{
unsigned int i;
bit dat;
DS=0;
i++; //拉低电平最少1us,然后再释放总线
DS=1;
i++; //等待一定时间后,再读取电平状态
i++;
dat=DS;
i=8;
while(i>0)
{
i--; //等待最少60us
}
return dat;
}

unsigned char Read_byte() //读取1字节的数据
{
unsigned char i,j;
unsigned char dat=0;
for(i=1;i<=8;i++)
{
j=Read_bit();
dat=(j<<7)|(dat>>1);
}
return dat;
}

void Write_byte(unsigned char dat) //往DS18B20中写入1字节的数据
{
unsigned int i;
unsigned char j;
bit x;
for(j=1;j<=8;j++)
{
x=dat&0x01; //依次将dat的每一位赋值给x
dat=dat>>1;
if(x) //写入“1”
{
DS=0; //拉低电平大于1us,在15us内拉高电平
i++;
i++;
DS=1; //“写”时序起始后的15~60us内,DS18B20处于采样状态,在此期间,若总线为高电平,则表示“1”
i=8;
while(i>0)
{
i--; //等待最少60us
}
}
else //写入“0”;拉低电平60~120us,然后释放总线
{
DS=0;
i=8;
while(i>0) //最少60us
{
i--;
}
DS=1;
}
}
}

void Change(void) //温度转换,即测量温度
{
DS18B20_init();
Delay(1);
Write_byte(0xcc); //“跳过ROM”操作
Write_byte(0x44); //“温度转换”操作
}

unsigned int GET() //获取温度数据
{
float x;
unsigned char a,b;
DS18B20_init();
Delay(1);
Write_byte(0xcc);
Write_byte(0xbe); //读取DS18B20内的RAM的内容
a=Read_byte(); //读取温度值的低8位
b=Read_byte(); //读取温度值的高8位
temp=b;
temp<<=8;
temp=temp|a;
x=temp*0.0625; //DS18B20默认设置为12位分辨率,即表示分辨率为0.0625摄氏度
temp=x*10+0.5;
return temp;
}

void OUTPUT(unsigned int temp) //数码管显示
{
unsigned char x0,x1,y,x2;
x0=temp/100;
y=temp%100;
x1=y/10;
x2=y%10;
DU=0;
P0=table0[x0]; //显示温度值的十位
DU=1;
DU=0;
WE=0;
P0=0xfe;
WE=1;
WE=0;
Delay(1);
DU=0;
P0=table1[x1]; //显示温度值的个位
DU=1;
DU=0;
WE=0;
P0=0xfd;
WE=1;
WE=0;
Delay(1);
P0=table0[x2]; //显示温度值的十分位
DU=1;
DU=0;
P0=0xfb;
WE=1;
WE=0;
Delay(1);
}

void main()
{
while(1)
{
Change();
OUTPUT(GET());
}
}

参考资料

【常用传感器】DS18B20温度传感器原理详解及例程代码

DS18B20温度传感器

Ds18b20的使用

51单片机DS18B20温度传感器详解