目录
数字温度传感器你会用了吗?会自己敲代码了吗?
一、基础知识
1、基础介绍:
首先当然要知道它的用处啦!它是我们社会生活中不可缺少的"测温计”,温控大棚,高铁上的温度显示等等都离不开它的身影!
DS18B20数字温度传感器是DALLAS公司生产的单总线器件,用它组成的一个测温系统具有线路简单、体积小的特点,在一根通信线上可以挂多个数字温度传感器,十分方便。超小的体积,超低的硬件开销,抗干扰能力强,精度高,附加能力强,使其更加受欢迎。
2、DS18B20特点:
- 通信采用1-Wire接口(单线传输,只有一根数据线)
- 每个DS18B20都有唯一的64位序列码储存在板载ROM中(防止一条线上多个设备无法知晓是哪个设备)
- 无需外部元件
- 可从数据线供电,电源范围为3.0~5.5V
- 可测量的温度范围为-55~+125
- 在-10~+85范围内精确度为0.5
3、单总线时序
其采用1-Wire Bus所有数据都在一条线上传输,因此单总线协议对时序要求非常严格以确保数据的完整性。
单总线信号类型:复位脉冲、存在脉冲、写0、写1、读0、读1。所有这些信号除存在脉冲DS18B20发出和读数据的以外信号都由总线控制器发出。
数据传输从最低位开始(与IIC通信从最高位传输不同)
4、相关操作时序
初始化时序:包含复位DS18B20和接收DS18B20返回的存在信号。主机与DS18B20做任何通讯前都要对其初始化。
写时序:分为写1与写0,通过控制单总线高低电平持续时间从而把逻辑1或逻辑0写DS18B20中。
读时序:分为读0时序和读1时序。 总线控制器通过读取DS18B20控制的总线高低电平接收DS18B20数据。
5、部分ROM指令
忽略ROM指令(CCh) 该指令允许总线控制器不提供64位ROM编码就使用功能指令。单点总线情况下使用此命令可以使器件无需发回64位ROM编码(即只用发送这一条,其它4条ROM指令不用去发送),从而大大降低时间成本,但是队友多器件忽略ROM指令会使得多机同时发送信号,总线发生数据冲突。
温度转换指令(44h) 这条命令用以启动一次温度转换。温度转换指令被执行,产生的温度转换结果数据以2个字节的形式被存储在高速寄存器中,而后DS18B20保持等待状态。
读寄存器指令(BEh) 该命令读取暂存器的内容,读取从字节0开始,一直进行下去,直到读完寄存器所有字节,如果不想读完所有字节,控制器可以发出复位指令停止读取。
写暂存器指令(4Eh) 该命令向DS18B20暂存器写入数据,开始位置在TH寄存器(暂存器第二个字节),接下来写入TL寄存器(暂存器第3个字节),最后写入配置寄存器(暂存区的第4个字节)
拷贝暂存器指令(48h) 这条命令将TH、TL和配置寄存器(第2、3、4字节)的内容拷贝到EEPROM中(使用户设置的值断电不会丢失)
二、相关代码
1、 使用步骤(单点总线情况)
初始化->ROM操作指令->DS18B20功能指令 温度转换指令 读取暂存器指令
2、 代码展示
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS = P3^7; //DS18B20单总线
sbit LA=P2^2;
sbit LB=P2^3;
sbit LC=P2^4; //数码管段选
void delay2(unsigned int z) //延时函数2,delay(1000)=1s
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=120;y>0;y--);
}
unsigned char smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void timefrist()
{
EA = 1; //打开总开关
ET0 = 1; //中断函数0的开关
TR0 = 1; //打开定时器0开关
TMOD = 0x01; //模式一,定时模式
TH0 = 0xED; //这里改值了,到上限就5ms(改初值)
TL0 = 0xFF;
//开关、模式、赋初值
}
unsigned char miao=0;
void DigDisplay(unsigned char h)
{
unsigned char a=h%10;
unsigned char b=h/10%10;
unsigned char c=h/100;
static unsigned char wei=0;
switch(wei)
{
case 0: LA=1;LB=1;LC=1;P0 = smgduan[c];break;
case 1: LA=0;LB=1;LC=1;P0 = smgduan[b];break;
case 2: LA=1;LB=0;LC=1;P0 = smgduan[a];break;
}
wei++;
if(wei==3)
{
wei = 0;
}
}
void Delay_us(char us) //执行一次us--所需6.5us 进入一次函数11.95us
{
while(us--);
}
bit ds_init()
{
bit i;
DS=1;
_nop_();
DS=0;
Delay_us(75); //拉低总线499.45us 挂在总线上的DS18B20将会全部被复位
DS=1; //释放总线
Delay_us(4); //37.95us 读取18B20存在信号
i = DS; //将返回的值存放在i中
Delay_us(20); //141.95us
DS=1; //释放总线
_nop_(); //小延时使其稳定
return i;
}
//写一个字节
void write_byte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
DS = 0;
_nop_(); //产生写时序
DS = dat & 0x01;
Delay_us(10); //76.95us
DS = 1; //释放总线准备下一次数据写入
_nop_();
dat >>= 1;
}
}
uchar read_byte()
{
uchar i,j,dat;
for(i=0;i<8;i++)
{
DS = 0;
_nop_(); //产生读时序
DS = 1;
_nop_(); //释放总线
j = DS;
Delay_us(10); //76.95us
DS = 1;
_nop_();
dat = (j<<7) | (dat>>1);
}
return dat;
}
void main()
{
uint i; //用于存放两个字节
uchar L,M;//用于存储温度的低字节和高字节
timefrist(); //定时器0初始
while(1)
{
ds_init(); //初始化DS18B20
write_byte(0xcc); //发送跳跃ROM指令(忽略ROM指令)
write_byte(0x44); //发送温度转换指令 (温度将被存在高速寄存器中,再将其读出来)
ds_init(); //初始化DS18B20
write_byte(0xcc); //发送跳跃ROM指令(忽略ROM指令)
write_byte(0xbe); //读取DS18B20暂存器值
L = read_byte(); //读取高速暂存器第一个字节(即温度的低位)
M = read_byte(); //读取高速暂存器第二个字节(即温度的高位)
i = M;
i<<=8;
i |= L; //将L,M都写入一个数i中
i = i * 0.0625 * 10 + 0.5; //将i换算为实际温度(同时将小数点右移一位 实际意义为保留小数点一位且四舍五入)
delay2(2000); //延时一秒,速度太快
miao = i; //将i的数值赋值给miao并将其显示出来
}
}
//定时器中断函数
void timer0() interrupt 1
{
TH0 = 0xED; //重新定义5ms初始值
TL0 = 0xFF;
DigDisplay(miao); //显示,不断5ms显示就是动态显示
}
负数要设置判断语句,且其以补码形式存放,我们需要取反加一