备战蓝桥杯(四)DS18B20数字温度计

DS18B20是我们比较常用的一种数字温度计,测试温度范围-55℃-125℃,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。单总线,意味着没有时钟线,只有一根通信线。单总线读写数据是靠控制起始时间和采样时间来完成,所以时序要求很严格,这也是DS18B20驱动编程的难点。

DS18B20内部结构图如下图所示

这里写图片描述 
主要由2部分组成:64位ROM和9字节暂存器

(1) 64 位ROM。它的内容是64 位序列号,它可以被看作是该DS18B20 的地址序列码,其作用是使每个DS18B20 都各不相同,这样就可以实现一根总线上挂接多个DS18B20 的目的。

(2) 9字节暂存器包含:温度传感器、上限触发TH高温报警器、下限触发TL低温报警器、高速暂存器、8位CRC产生器。

3.64位ROM结构图

这里写图片描述

8位CRC:是单总线系列器件的编码,DS18B20定义为28H。 
48位序列号:是一个唯一的序列号。 
8位系列码:由CRC产生器生产,作为ROM中的前56位编码的校验码。

9字节暂存器结构图

这里写图片描述

以上是内部9 个字节的暂存单元(包括EEPROM)。 
字节0~1 是温度存储器,用来存储转换好的温度。 
字节2~3 是用户用来设置最高报警和最低报警值。这个可以用软件来实现。 
字节4 是配置寄存器,用来配置转换精度,让它工作在9~12 位。 
字节5~7 保留位。 
字节8 CRC校验位。是64位ROM中的前56位编码的校验码。由CRC发生器产生。

温度寄存器结构图

这里写图片描述

温度寄存器由两个字节组成,分为低8位和高8位。一共16位。 
其中,第0位到第3位,存储的是温度值的小数部分。 
第4位到第10位存储的是温度值的整数部分。 
第11位到第15位为符号位。全0表示是正温度,全1表示是负温度。 
表格中的数值,如果相应的位为1,表示存在。如果相应的位为0,表示不存在。

配置寄存器

这里写图片描述

精度值: 
9-bit 0.5℃  10-bit 0.25℃  11-bit 0.125℃  12-bit 0.0625℃

温度/数据关系

这里写图片描述

注意:如果温度是一个负温度,要将读到的数据减一再取反,不过一般情况下是不会让在比赛的时候去取值温度的负数的,因为负数的环境不好去制造。所以在本文章中我就不做过多的概述。、

DS18B20采用的是单总线寄生供电的方式连接到单片机,如下图所示:

 在比赛的时候在这个压缩包的驱动代码参考文件夹中我们会找到一个名为“onewire.c”的文件,这个就是单总线的驱动文件但是是不完整的我们需要做一些添加和修改。onewire.c”文件的内容如下:

 

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	while(t--);
}

//通过单总线向DS18B20写一个字节
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 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;
}

//DS18B20设备初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

 首先我们都知道STC15F系列的单片机是具有12T和1T两种速度模式的,但是DS18B20默认的接收数据是和AT89C51相同的(也就是12T)。所以我们在使用之前需要将我们的单片机设置为12T,在驱动说明中官方也给了提示说使用12T的模式以避免程序出错。

 修改方法1:

 首先需要在主程序之前声明单片机的辅助功能寄存器AUXR的位置。辅助功能寄存器AUXR的配置方法和功能请参照STC官网给出的《STC15F系列单片机技术手册》P60的MCKO_S1和MCKO_S0的配置。

sfr AUXR = 0x8E; //配置AUXR寄存器的位置
 //配置AUXR寄存器的位置

然后在中断服务函数中添加一句:

AUXR &= 0x7F;  //将定时器的始终设置为12T  //将定时器的始终设置为12T

------------------------------------------------------2019-12-xx---以上错误-----------------------------------------

前段时间无意中看到STC15的数据手册发现自己一直理解错了,如下图所示:

因此MCLK只是在P5.4引脚上输出一个特定频率的CLK信号,并不是我们需要的设置系统运行频率,非常抱歉一直没来得及改正; 真正意义上的对系统频率的修改应该是使用的CLK_DIV(PCON2)这个寄存器,配置方式如下图所示:

从图中我们可以看出并没有办法直接进行12分频,因此我们采用8分频(对于DS18B20来说是可以的),如果想真的让系统速度为12T,就需要在ISP下载软件中将单片机设置为内部R/C震荡作为主时钟 频率8MHz,这样设置CLK_DIV(PCON2)的CLKS2、CLKS1、CLKS0三个位为011,就可以进行8分频。这样系统就运行在12T的模式下了。

 修改方法2:在不修改单片机的处理速度的情况下把"Delay_OneWire"这个延时函数增加到原来的12倍,操作方法是将函数修改为:

void Delay_OneWire(unsigned int t)  //STC89C52RC
{
unsigned char x;
	while(t--)
	{
	for(x=0,x++,x<12);
	}
}

我本身不太推荐使用方法二因为官方也说了让设置为12T的模式,如果坚持使用1T可能会在后续代码增加的时候出现错误(不过至我还没发现错误)。



 

发布了21 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Argon_Ghost/article/details/79171706