简述:
蓝桥杯板子上的DS18B20温度传感器,通信方式是单总线通信(1一wire);同时在蓝桥杯比赛的资料包中,提供了一个关于DS18B20的库文件(onewire.h,onewire.c),里面有传感器复位 [bit init_ds18b20(void) ]、写字节 [void Write_DS18B20(unsigned char dat) ] 和读字节 [unsigned char Read_DS18B20(void) ] 三个函数。所以我们不一定需要将I2C的时序搞得很清楚,只需要将DS18B20的基本操作流程弄明白。
根据提供的芯片数据手册可以获取的信息:
-
DS18B20 采用单总线协议与主机进行通信。在单线端口条件下,必须先建立ROM 操作协议,才能进行存储器和控制操作。 -
配置寄存器允许用户将温度数字转换的分辨率设置为9、10、11或12位。DS18B20的核心功能是直接数字温度传感器。温度传感器的分辨率可由用户配置为9、10、11或12 位,分别对应0.5℃、0.25℃、0.125℃和0.0625℃的增量。上电时的默认分辨率为12位(即精度为0.0625℃)。 -
通过单线总线端口访问 DS18B20 的协议如下: ? 初始化 ? ROM 操作命令 ? 存储器操作命令 ? 执行/数据
ROM操作命令:
名称(寄存器地址) | 作用 | 其他 |
---|
Search ROM(F0H) | 主机识别总线上所有从机的ROM代码 | | Read ROM(33H) | 主机读取从机的64位ROM代码 | | Match ROM(55H) | 匹配64位ROM命令 | | Skip ROM(CCH) | 主机使用该命令同时寻址总线上的所有器件,无需发送器件的64位rom代码即可读取从机数据 | 适合像CT107D开发板的设计,总线上只有一个器件的情况 | Alarm Search(ECH) | 主机确定最近一次温度转换期间是否有DS18B20出现报警情况 | 很少用到 |
主机可以使用 Skip ROM命令 同时寻址总线上的所有器件,而无需发送任何ROM代码信息。例如,主机可以通过发出Skip ROM命令,然后发出Convert T [44h]功能命令,使总线上的所有DS18B20同时执行温度转换。 请注意,Skip ROM命令适用于总线上有一个从机时。这种情况下,主机无需发送器件的64位ROM代码即可读取从机数据,从而节省了时间。
存储器操作命令
操作命令名称(寄存器地址) | 描述 |
---|
Convert Temperatures(44H) | 该命令启动一次温度转换。转换后,产生的热数据存储在暂存存储器的2 字节温度寄存器 | Write Scratchpad (4EH) | 该命令允许主机向DS18B20的暂存器写入3个字节的数据。 | Read Scratchpad (BEH) | 该命令允许主机读取寄存器的数据。数据传输从字节0的最低有效位开始(低八位开始),继续通过暂存器,直到读取完高八位字节。 |
温度转换及温度获取
温度寄存器格式:
当需要执行温度测量时,总线控制器必须发出温度转换命令。在那之后,产生的温度数据以两个字节的形式被存储到高速暂存器的温度寄存器中,DS18B20继续保持等待状态。单片机可通过单线接口可以读到该数据,读取时低位在前,高位在后。
下表中高5位S为扩展符号位。当S=0时表示测得的温度值为正值,可以直接将二进制位转换为十进制;当S=1时,表示测得的温度值为负值,要先将补码变成原码,再计算十进制值。
原文:After the DS18B20 performs a temperature conversion, the temperature value is compared to the user-defined two’s complement alarm trigger values stored in the 1-byte TH and TL registers (see Figure 3). The sign bit (S) indicates if the value is positive or negative: for positive numbers S = 0 and for negative numbers S = 1.
获取温度的具体操作
读取一次DS18B20温度的基本操作: <1> 对DS18B20进行复位初始化。 <2> 向DS18B20写0xCC命令,跳过ROM。 <3> 向DS18B20写0x44命令,开始进行温度转换。 <4> 等待温度转换完成。 <5> 对DS18B20进行复位初始化。 <6> 向DS18B20写0xCC命令,跳过ROM。 <7> 向DS18B20写0xBE命令,开始读取寄存器中的温度数据 <8>将读取的高八位和高八位的温度数据存入对应的变量中 <9>将DS18B20复位初始化。
完整读取一次温度数据的代码示例:
Init_DS18B20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Init_DS18B20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
Init_DS18B20();
温度数据处理与数码管显示
根据储存温度数据的变量进行实际温度计算(正温度值):
unsigned int Digital_Output,Decimals,Integer;
Digital_Output = MSB << 8 | LSB
if(Digital_Output & 0xF800 == 0X0000)
{
Integer = (Digital_Output >>4)* 100;
Decimals = (LSB & 0x0f) * 0.0625*100;
Digital_Output =Integer+Decimals;
}
需要保留小数时的数据处理(数码管显示): 例如:我们要显示15.34
步骤:
1>将15.34*100
2>利用1534进行每一位的提取
1534/1000 = 1;
1534/100%10 = 5;
1534/10%10 = 3;
1534%10 = 4;
3>将获取的每一位数显示在数码管上
完整项目代码示例:
#include "reg52.h"
#include "onewire.h"
unsigned int T_dat;
unsigned char SMG_NoDot[19] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x80, 0xc6, 0xc0, 0x86, 0x8e, 0xbf, 0x7f, 0xff};
unsigned char code SMG_IsDot[10] = {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};
void Delay500us();
void Read_Temperature();
void Display_Temperature(unsigned int dat);
void Digital_Tube(unsigned char Position, unsigned char Typeface);
void main()
{
while (1)
{
Read_Temperature();
Display_Temperature(T_dat);
}
}
void Delay500us()
{
unsigned char i, j;
i = 6;
j = 211;
do
{
while (--j);
}
while (--i);
}
void Digital_Tube(unsigned char Position, unsigned char Typeface)
{
unsigned char Bit[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
P2 = P2 & 0x1f | 0xc0;
P0 = Bit[Position];
P2 = P2 & 0x1f | 0xe0;
P0 = Typeface;
Delay500us();
P0 = 0XFF;
P2 = P2 & 0x1f ;
}
void Display_Temperature(unsigned int dat)
{
Digital_Tube(7, SMG_NoDot[dat % 10]);
Digital_Tube(6, SMG_NoDot[dat / 10 % 10]);
Digital_Tube(5, SMG_IsDot[(dat / 100) % 10]);
Digital_Tube(4, SMG_NoDot[(dat / 1000) % 10]);
P2 = P2 & 0x1f | 0xc0;
P0 = 0XFF;
P2 = P2 & 0x1f | 0xe0;
P0 = 0XFF;
}
void Read_Temperature()
{
unsigned char LSB, MSB;
unsigned int Decimals,Integer;
Init_DS18B20();
Write_DS18B20(0xCC);
Write_DS18B20(0x44);
Init_DS18B20();
Write_DS18B20(0xCC);
Write_DS18B20(0xBE);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
Init_DS18B20();
T_dat = 0x0000;
T_dat = MSB << 8 | LSB;
if ((T_dat & 0xf800) == 0x0000)
{
Integer = (T_dat >>4)* 100;
Decimals = (LSB & 0x0f) * 0.0625*100;
T_dat=Integer+Decimals;
}
}
DS18B20的蓝桥杯文档及整个工程文件下载:
|