蓝桥杯单片机之DS18B20温度传感器
时间:2022-11-01 12:30:00
蓝桥杯单片机之一DS18B20温度传感器
-
- 简述:
- 从提供的芯片数据手册中获得的信息:
-
- ROM操作命令:
- 存储操作命令
- 温度转换和温度获取
-
- 温度寄存器格式:
- 具体操作获取温度
- 温度数据处理和数字管显示
- 完整的项目代码示例:
简述:
蓝桥杯板DS18B20温度传感器是单总线通信(1wire);同时,在蓝桥杯比赛的信息包中,提供了一个关于蓝桥杯比赛的信息包DS18B20的库文件(onewire.h,onewire.c),有传感器复位 [bit init_ds18b20(void)
]、写字节 [void Write_DS18B20(unsigned char dat)
] 和读字节 [unsigned char Read_DS18B20(void)
] 三个函数。所以我们不一定需要I2C时序很清楚,只需要DS18B了解20的基本操作流程。
从提供的芯片数据手册中获得的信息:
-
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]功能命令使总线上的一切DS18B同时进行温度转换。
请注意,Skip ROM命令适用于总线上的一个从机器。在这种情况下,主机不需要发送设备的64位ROM代码可以读取从机数据,节省时间。
存储操作命令
操作命令名称(寄存器地址) | 描述 |
---|---|
Convert Temperatures(44H) | 该命令启动温度转换。转换后,存储在临时存储器中的热数据 字节温度寄存器 |
Write Scratchpad (4EH) | 该命令允许主机向DS18B将3个字节的数据写入20个暂存器。 |
Read Scratchpad (BEH) | 该命令允许主机读取寄存器的数据。数据传输始于字节0的最低有效性(低8位),并继续通过临时存储器,直到读取高8位字节。 |
温度转换和温度获取
温度寄存器格式:
当需要进行温度测量时,总线控制器必须发出温度转换命令。之后,产生的温度数据以两个字节的形式存储在高速临时存储器的温度寄存器中,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> 对DS18B二十复位初始化。
<6> 向DS18B20写0xCC命令,跳过ROM。
<7> 向DS18B20写0xBE开始读取寄存器中的温度数据
<8>将读取的高八位和高八位的温度数据存储在相应的变量中
<9>将DS18B20复位初始化。
完全读取温度数据的代码示例:
Init_DS18B20(); //对DS18B二十复位初始化。 Write_DS18B20(0xCC);/span> //跳过ROM,仅总线上只有一个从机时使用 Write_DS18B20(0x44); //进行温度转换 Init_DS18B20(); //对DS18B20进行复位初始化。 Write_DS18B20(0xCC); //跳过ROM,仅总线上只有一个从机时使用 Write_DS18B20(0xBE); //开始读取寄存器中的温度数据,需按照从低八位到高八位的顺序 LSB = Read_DS18B20(); //将低八位存入LSB变量 MSB = Read_DS18B20(); //将高八位存入MSB变量 Init_DS18B20(); //对DS18B20进行复位初始化。
温度数据处理与数码管显示
根据储存温度数据的变量进行实际温度计算(正温度值):
unsigned int Digital_Output,Decimals,Integer;
Digital_Output = MSB << 8 | LSB //将高八位左移8位再加上低八位,形成一个16位的完整温度数据
if(Digital_Output & 0xF800 == 0X0000)
{
Integer = (Digital_Output >>4)* 100; //提取整数部分并乘以100
Decimals = (LSB & 0x0f) * 0.0625*100; //提取分数部分乘以精度再乘以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>将获取的每一位数显示在数码管上//记住数码管显示时,5是一个含有小数点的字形>
完整项目代码示例:
#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}; //0-9、A-F、'-'、'.'
unsigned char code SMG_IsDot[10] = {
0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};
void Delay500us();
void Read_Temperature(); //从DS18B20读取一次温度的操作,并将温度进行处理函数
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() //@12.000MHz
{
unsigned char i, j;
i = 6;
j = 211;
do
{
while (--j);
}
while (--i);
}
void Digital_Tube(unsigned char Position, unsigned char Typeface) //Position是数码管第几位(从左到右,0开始),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() //从DS18B20读取一次温度的操作,并将温度进行处理函数
{
unsigned char LSB, MSB;
unsigned int Decimals,Integer; //定义局部变量,整数、小数
Init_DS18B20(); //对DS18B20进行复位初始化。
Write_DS18B20(0xCC); //跳过ROM,仅总线上只有一个从机时使用
Write_DS18B20(0x44); //进行温度转换
Init_DS18B20(); //对DS18B20进行复位初始化。
Write_DS18B20(0xCC); //跳过ROM,仅总线上只有一个从机时使用
Write_DS18B20(0xBE); //开始读取寄存器中的温度数据,需按照从低八位到高八位的顺序
LSB = Read_DS18B20(); //将低八位存入LSB变量
MSB = Read_DS18B20(); //将高八位存入MSB变量
Init_DS18B20(); //对DS18B20进行复位初始化。
T_dat = 0x0000; //数据初始化
T_dat = MSB << 8 | LSB; //将低八位和高八位进行合并
if ((T_dat & 0xf800) == 0x0000) //判断是不是正值
{
Integer = (T_dat >>4)* 100; //提取整数部分并乘以100
Decimals = (LSB & 0x0f) * 0.0625*100; //提取分数部分乘以精度再乘以100
T_dat=Integer+Decimals; //将100倍的整数部分加上100倍的小数部分
}
/*if ((MSB& 0xf8) == 0x0000) //判断是不是正值 { T_dat=T_dat*0.0625*100; //将100倍的整数部分加上100倍的小数部分 } */
}
DS18B20的蓝桥杯文档及整个工程文件下载: