DS18B20 (by 51单片机)

依旧是接着蓝桥杯的机会来学习一下DS18B20和单总线技术,平台依旧是IAP15F2K61S2单片机

DS18B20单线数字温度计以9位数字量的形式反映器件的温度值,DS18B20通过一个单线接口发送或者接受信息,因此在中央微处理器和DS18B20之间只需要一根连线。下图为其引脚功能说明:


器件框图如下所示:


从图中可以看出,DS18B20主要由三个数字部件构成,分别是64位激光ROM,温度传感器,非易失性温度报警触发器TH和TL。

DS18B20所使用的总线技术为单总线技术,目前单片机与外设之间进行数据传输的串行总线主要由SCI,I2C和SPI总线,其中SCI总线总是以异步方式进行通信(一条数据输入线,一条数据输出线),而I2C总线以同步串行二线方式进行通信(一条时钟线,一条数据线),SPI总线则以同步串行三线方式进行通信(一条数据输入线,一条数据输出线)。这些总线都需要至少两条或两条以上的信号线,而DS18B20使用的单总线技术与上述总线不同,它采用单条信号线,既可传输时钟,有可传输数据,而且数据传输是双向的,因而这种单总线技术具有线路简单,硬件开销少,成本低廉,便于总线扩展和维护等优点。单总线适用于单主机系统,能够控制一个或多个从机设备。

还是老方法,先对DS18B20进行初始化,然后对DS18B20进行读写操作。

首先我们来看看控制DS18B20的指令。

33H-----读ROM:读DS18B20温度传感器ROM中的编码。

55H-----匹配ROM。发出此命令之后,接着发出64位ROM的编码,访问单总线上与该编码相对应的DS18B20并使之做出响应,为下一步对该DS18B20的读/写做准备。

F0H-----搜索ROM。用于确定挂接在同一总线上DS18B20的个数,识别64位ROM地址,为操作各器件做好准备。

CCH-----跳过ROM。忽略64位ROM地址,直接向DS18B20发温度变换命令,适用于一个从机工作。

ECH-----告警搜索命令。执行后只有温度超过设定值上限或下限芯片才会做出反应。

以上指令是针对总线上挂接多个DS18B20的情况,但如果总线上只挂接了一个DS18B20,就不需要以上ROM指令,直接进行如下的温度转换和读取操作。

44H----温度转换。启动DS18B20进行温度转换,12位转换时长最长为750ms,9位为93.75ms,结果存入内部9字节的RAM中。

BEH----读暂存器。读内部ROM中9字节的温度数据。

4EH----写暂存器。发出向内部RAM的第二三字节写上下线温度数据的命令,紧跟该命令之后,是传送两字节的数据。

48H----复制暂存器。将RAM中第2,3字节的内容复制到EEPROM中。

B8H----重调EEPROM。将EEPROM中内容恢复到RAM中的第三四字节。

B4H----读供电方式。读DS18B20的供电模式。寄生供电时,DS18B20发送0;外接电源供电时,DS18B20发送1。

和DS18B20的任何通信都需要以初始化序列开始,初始化序列见下图:


上图含义如下:

1.先将数据线置高电平1

2.延时(时间要求不严格,但尽可能短些)

3.数据线拉到低电平0

4.延时750us(该时间范围可以在480~960us)

5.数据线拉到高电平1

6.延时等待。如果初始化成功,则在15~60us内产生一个由DS18B20返回的低电平0,据该状态可以确定它的存在,但是应注意,不能无限地等待,不然会使程序进入死循环,所以要进行超时判断。

7.若CPU读到数据线上的低电平0后,还有进行延时,其延时的时间从发出高电平算起至少要480us。

8.将数据线再次拉到高电平1后结束。

DS18B20写数据,时序如下图所示:


其含义如下:

1.数据线先置低电平0

2.延时确定的时间为15us

3.按从低位到高位的顺序发送数据(一次只发送一位)

4.延时时间为45us

5.将数据线拉到高电平1

6.重复1~5步骤,直到发送完整个字节

7.最后将数据线拉高到1

DS18B20读数据,时序图如下:


含义如下:

1.将数据线拉高到1

2.延时2us

3.将数据线拉低到0

4.延时6us

5.将数据线拉高到1

6.延时4us

7.读数据线的状态得到一个状态位,并进行数据处理

8.延时30us

9.重复1~7步骤,直到读取完一个字节

下面我们一起分析一下蓝桥杯官方给出的代码,如果鄙生有理解错的地方,还望各位大牛指点。

首先是初始化函数

bit init_ds18b20(void)
{
  bit initflag = 0;
  DQ = 1;      //首先将数据线置高
  Delay_OneWire(12);  //短暂延时
  DQ = 0;      //将数据线拉到低电平
  Delay_OneWire(80);    //延时在480~960US之间
  DQ = 1;                     //数据线拉回高电平
  Delay_OneWire(10);  // 延时等待
  initflag = DQ;     // initflag等于1初始化失败
  Delay_OneWire(5);     //最后一个延时
  return initflag;

}

其中的Delay_OneWire()函数如下所示:注意这是一段延时,但是延时t值需要根据你单片机的一个机器周期时长来确定,否则时序会出错,即无法读出温度值!!!

void Delay_OneWire(unsigned int t)
{
int i;
        while(t--)
{
      for(i=0;i<12;i++);
}
}

//向DS18B20写一个字节

void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)    //重复直到发送完整个字节
{
DQ = 0;  //数据线首先拉低
DQ = dat&0x01;
Delay_OneWire(5);  //延时45us
DQ = 1;    //将数据线拉回高电平1
dat >>= 1;
}
Delay_OneWire(5);

}

//从DS18B20读取一个字节

unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat; 
for(i=0;i<8;i++)    //重复接收直到读完整个字节
{
DQ = 0;   //数据线拉低
dat >>= 1;
DQ = 1;   //数据线拉高
if(DQ)
{
dat |= 0x80;
}    
Delay_OneWire(5);
}
return dat;
}

以上就是蓝桥杯官方给出的代码,下面我给出我根据单总线库写出的温度读取函数:

void Read_tem(void)
{
  unsigned char low,high;
        char temp;
  Init_DS18B20();       
  Write_DS18B20(0xCC);  //忽略64位ROM地址,直接向DS18B20发送温度变换命令,适用于一个从机工作
  Write_DS18B20(0x44);   //温度转换
  Delay_OneWire(200);


  Init_DS18B20();
  Write_DS18B20(0xCC);   
  Write_DS18B20(0xBE);   //读取温度数据


  low = Read_DS18B20();    //低八位
  high = Read_DS18B20();   //高八位
  
  temp = high<<4;           //整合成一个字节
  temp |= (low>>4);
  
  return temp;
}

至此,DS18B20部分就全部介绍完了,如果有错误,希望各位大牛指正。

猜你喜欢

转载自blog.csdn.net/qq_33656619/article/details/79574552