一篇文章教会你DS18B20温度传感器读取温度,附STM32代码示例
目录
一、DS18B20温度传感器:
(1)描述:
(2)特点:
(3)引脚图及其定义:
(4)使用的DS18B20模块:
二、DS18B20功能命令集:
(1)搜索ROM命令(Search ROM [F0h]):
(2)读取ROM命令(Read ROM [33h]):
(3)匹配ROM命令(Match ROM [55H]):
(4)跳过ROM命令(Skip ROM [CCh]):
(5)报警搜索命令(Alarm Search [ECh]):
(6)转换温度命令(Convert T [44h]):
(7)写入暂存器命令(Write Scratchpad [4Eh]):
(8)读取暂存器命令(Read Scratchpad [BEh]):
(9)复制暂存器命令(Copy Scratchpad [48h]):
(10)回召E2命令(Recall E2 [B8h]):
(11)读取电源命令(Read Power Supply [B4h]):
三、 读取步骤:
(1)初始化1-Wire总线:
头文件:
初始化引脚:
(2)初始化DS18B20:
(3)DS18B20写入一位 0/1:
(4)DS18B20读取一位 0/1:
(5)DS18B20写入一个字节:
(6)DS18B20读取一个字节:
(7)DS18B20读取温度:
(8)主函数:
编辑
四、示例:
(1)DS18B20操作示例:
(2)DS18B20操作示例:
编辑五、DS18B20其他说明:
(1)DS18B20方框图:
(2)测温操作:
编辑(3)报警操作信号:
(4)DS18B20供电:
(5)64位的激光光刻只读存储器(ROM):
(6)存储器:
编辑 (7)配置寄存器:
(8)CRC:
(9)单总线系统:
六、示例代码下载:
一、DS18B20温度传感器:
(1)描述:
DS18B20数字温度计提供9位到12位的摄氏度温度测量,并具有带非易失性用户可编程的上限和下限触发点的报警功能。DS18B20通过定义仅需要一条数据线(和地线)与中央微处理器通信的1-Wire总线进行通信。它的工作温度范围是-55°C至+125°C,在-10°C至+85°C的范围内准确度为±0.5°C。此外,DS18B20可以直接从数据线(“寄生电源”)获取电源,从而消除了对外部电源的需求。
每个DS18B20都有一个独特的64位序列号,允许多个DS18B20在同一个1-Wire总线上工作。因此,使用一个微处理器控制分布在较大区域上的许多DS18B20是很简单的。可以从这个特性中受益的应用包括HVAC环境控制、建筑物、设备或机械内部的温度监测系统,以及过程监控和控制系统。
(2)特点:
(3)引脚图及其定义:
(4)使用的DS18B20模块:
二、DS18B20功能命令集:
在DS18B20的1-Wire通信协议中,主机(微控制器)可以通过一系列ROM命令来识别和选择总线上的特定设备。
(1)搜索ROM命令(Search ROM [F0h]):
(2)读取ROM命令(Read ROM [33h]):
(3)匹配ROM命令(Match ROM [55H]):
(4)跳过ROM命令(Skip ROM [CCh]):
(5)报警搜索命令(Alarm Search [ECh]):
在ROM命令之后,主机可以发出DS18B20功能命令来与DS18B20进行通信:
(6)转换温度命令(Convert T [44h]):
启动一次温度测量。转换完成后,结果存储在暂存器的两字节温度寄存器中,然后DS18B20返回低功耗空闲状态。
(7)写入暂存器命令(Write Scratchpad [4Eh]):
允许主机向DS18B20的暂存器写入3个字节的数据,包括报警上下限寄存器(TH和TL)和配置寄存器。
(8)读取暂存器命令(Read Scratchpad [BEh]):
允许主机读取暂存器的内容,包括温度值、报警上下限和配置寄存器。
(9)复制暂存器命令(Copy Scratchpad [48h]):
将暂存器中的报警上下限和配置寄存器的内容复制到EEPROM中。
(10)回召E2命令(Recall E2 [B8h]):
从EEPROM中回召报警上下限和配置数据到暂存器。
(11)读取电源命令(Read Power Supply [B4h]):
主机使用这个命令来确定总线上的任何DS18B20是否使用寄生电源模式。
三、 读取步骤:
(1)初始化1-Wire总线:
头文件:
#ifndef __DS18B20_H
#define __DS18B20_H
#include "stm32f10x.h"
#define DS18B20_PORT GPIOA
#define DS18B20_PIN GPIO_Pin_1
// 初始化GPIO PA1 用于DS18B20
void DS18B20_Init(void);
// DS18B20复位时序(初始化)
u8 DS18B20_Reset(void) ;
// DS18B20写入一位 0/1
void DS18B20_WriteBit(uint8_t bit);
// DS18B20读取一位 0/1
uint8_t DS18B20_ReadBit(void) ;
// DS18B20写入一个字节
void DS18B20_WriteByte(uint8_t byte);
// DS18B20读取一个字节
uint8_t DS18B20_ReadByte(void);
// DS18B20读取温度
float DS18B20_ReadTemperature(void);
#endif
初始化引脚:
// 初始化GPIO PA1 用于DS18B20
void DS18B20_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = DS18B20_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DS18B20_PORT, &GPIO_InitStructure);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN); // 将PA1设置为高电平
}
(2)初始化DS18B20:
// DS18B20复位时序(初始化)
u8 DS18B20_Reset(void) {
GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
Delay_us(750);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
Delay_us(70);
if(GPIO_ReadInputDataBit(DS18B20_PORT, DS18B20_PIN)==1){
Delay_us(200);
return 0;
}else {
Delay_us(200);
return 1;
}
}
(3)DS18B20写入一位 0/1:
// DS18B20写入一位 0/1
void DS18B20_WriteBit(uint8_t bit) {
if (bit) { // 写入1
GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
Delay_us(5);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
Delay_us(60);
} else { // 写入0
GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN);
Delay_us(60);
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN);
Delay_us(5); // 释放总线
}
}

(4)DS18B20读取一位 0/1:
// DS18B20读取一位 0/1
uint8_t DS18B20_ReadBit(void) {
uint8_t bit_value = 0;
GPIO_ResetBits(DS18B20_PORT, DS18B20_PIN); // 拉低总线,准备读取
Delay_us(2); // 给总线一个短暂的低电平
GPIO_SetBits(DS18B20_PORT, DS18B20_PIN); // 释放总线
Delay_us(13); // 等待DS18B20驱动总线
if (GPIO_ReadInputDataBit(DS18B20_PORT, DS18B20_PIN) == 1) {
bit_value = 1;
Delay_us(50); // 补足剩余的延时
return bit_value;
}else{
Delay_us(50); // 补足剩余的延时
return bit_value;// 如果DS18B20将总线拉低,则读取为1
}
}

(5)DS18B20写入一个字节:
// DS18B20写入一个字节
void DS18B20_WriteByte(uint8_t byte) {
for (uint8_t i = 0; i < 8; i++) {
// 提取当前位的值
uint8_t bit = (byte >> i) & 0x01;
// 写入这一位
DS18B20_WriteBit(bit);
}
}
(6)DS18B20读取一个字节:
// DS18B20读取一个字节
uint8_t DS18B20_ReadByte(void) {
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++) {
uint8_t bit = DS18B20_ReadBit();
// 将读取到的位左移至正确的位置
byte |= (bit << i);
}
return byte;
}
(7)DS18B20读取温度:
// DS18B20读取温度
float DS18B20_ReadTemperature(void) {
uint8_t low, high;
int16_t raw_temp;
// 初始化DS18B20
DS18B20_Init();
// 重置DS18B20
if (DS18B20_Reset() == 0) {
// 传感器未连接
return -1; // 返回-1表示传感器未连接
}
// 发送“读取温度”命令
DS18B20_WriteByte(0xcc); // 跳过ROM命令
DS18B20_WriteByte(0x44); // 读取温度命令
// 等待转换完成
Delay_ms(750); // DS18B20转换时间最长为750ms
// 重置DS18B20
if (DS18B20_Reset() == 0) {
// 传感器未连接
return -1; // 返回-1表示传感器未连接
}
// 发送“读取暂存器”命令
DS18B20_WriteByte(0xcc); // 跳过ROM命令
DS18B20_WriteByte(0xbe); // 读取暂存器命令
low = DS18B20_ReadByte(); // 读取低字节
high = DS18B20_ReadByte(); // 读取高字节
// 组合成完整的温度值
raw_temp = ((int16_t)high << 8) | low;
// 检查温度值是否有效
if (raw_temp == -32768) { // 检查是否为-32768,表示传感器故障
return -1; // 返回-1表示读取失败
}
// 处理负温度值
if (raw_temp & 0x8000) { // 如果符号位为1
raw_temp = ~raw_temp; // 取反
raw_temp += 1; // 加1
raw_temp = -raw_temp; // 取负
}
// 转换为摄氏度
float temperature = raw_temp * 0.0625;
return temperature; // 返回浮点数温度值
}
(8)主函数:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "OLED.h"
#include "DS18B20.h"
int main(void)
{
/*OLED初始化*/
OLED_Init();
// 初始化DS18B20
DS18B20_Init();
// 主循环
while (1)
{
OLED_ShowString(0, 0, "temperature:", OLED_8X16);
OLED_ShowFloatNum(0, 16, DS18B20_ReadTemperature(), 5,2, OLED_8X16);
OLED_Update();
}
}
四、示例:
(1)DS18B20操作示例:
(2)DS18B20操作示例:
五、DS18B20其他说明:
(1)DS18B20方框图:
唯一标识:每个DS18B20设备都拥有一个64位的只读存储器(ROM),存储了设备的唯一序列号,这使得每个传感器都可被单独识别。
温度数据存储:传感器的高速暂存器中包含一个两字节的温度寄存器,用于存储温度传感器测量的温度数据。
温度报警设置:高速暂存器还包含两个温度报警值寄存器,即上报警(TH)和下报警(TL),以及一个配置寄存器。这些寄存器允许用户设置温度报警阈值。
可编程精度:配置寄存器允许用户选择温度测量的精度,可选的分辨率有9位、10位、11位或12位。
非易失性存储:报警值和配置数据存储在非易失性的电可擦除可编程只读存储器(EEPROM)中,这意味着即使在断电的情况下,这些数据也不会丢失。
单总线通信:DS18B20通过Dallas Semiconductor的单总线协议进行通信,该协议只需要一个数据线(DQ)和一个地线,通过一个弱上拉电阻来保持总线的高电平状态。
寄生电源供电:DS18B20能够以寄生电源模式工作,这意味着它可以从单总线直接获取能量,不需要外部电源供电。当总线为高电平时,内部电容(Cpp)会充电,当总线为低电平时,电容会放电以供电。
灵活的电源选项:除了寄生电源模式,DS18B20也可以通过VDD引脚连接外部电源供电。
(2)测温操作:
温度传感器精度:
默认精度:
低功耗等待状态:
温度测量和AD转换:
温度数据存储:
温度转换状态:
寄生电源供电要求:
温度寄存器格式:
温度/数据关系:
(3)报警操作信号:
温度报警阈值:
报警阈值格式:
报警条件:
报警标识:
报警搜索命令:
报警确认:
非易失性存储:
报警处理:
(4)DS18B20供电:
外部电源供电:
寄生电源模式:
寄生电源控制回路:
寄生电源模式下的VDD引脚:
寄生电源模式的电流限制:
强上拉要求:
温度和电源模式:
电源模式的指示:
(5)64位的激光光刻只读存储器(ROM):
在DS18B20温度传感器中,每个设备都内建了一个64位的激光光刻只读存储器(ROM),这个ROM存储了设备的唯一标识信息。这个64位编码的构成如下:
系列码(Family Code):最前面的8位是系列码,对于DS18B20来说,这个系列码是28h
。这个代码标识了设备属于Dallas/Maxim Integrated的1-Wire温度传感器家族。
序列号(Serial Number):紧接着系列码之后的是48位序列号,这个序列号是每个设备独有的,确保了每个DS18B20设备在全球范围内都是可以识别的。
CRC(Cyclic Redundancy Check):最后8位是CRC校验码,这个校验码是通过计算前面56位(系列码和序列号)的CRC得到的。CRC用于检测在ROM代码读取过程中可能出现的错误。
(6)存储器:
DS18B20的存储器结构包括了一个暂存器(Scratchpad)和一个非易失性电可擦除可编程只读存储器(EEPROM),用于存储温度数据和配置信息。
暂存器(Scratchpad):
非易失性EEPROM:
CRC校验码:
写入和读取操作:
从暂存器到EEPROM的拷贝:
召回EEPROM命令:
(7)配置寄存器:
配置寄存器是DS18B20存储器中非常重要的一部分,它允许用户设置温度测量的精度。以下是配置寄存器的详细解释:
配置寄存器结构:
配置寄存器的设置:
用户可以通过设置R0和R1位来配置DS18B20的温度测量精度。具体的设置如下表所示:
R1 | R0 | 分辨率 (位) | 最大转换时间 (ms) |
---|---|---|---|
0 | 0 | 9 | 93.75 (tCONV/8) |
0 | 1 | 10 | 187.5 (tCONV/4) |
1 | 0 | 11 | 375 (tCONV/2) |
1 | 1 | 12 | 750 (tCONV) |
默认设置:
精度与转换时间的关系:
(8)CRC:
在DS18B20的64位ROM中,CRC(循环冗余校验)字节用于确保数据的完整性。CRC是一个错误检测码,用于检测数据传输过程中可能出现的错误。
CRC的作用:
CRC的计算:
X^8 + X^5 + X^4 + 1
。CRC的存储:
CRC的比较:
CRC的错误处理:
CRC的生成:
(9)单总线系统:
单总线系统是一种串行通信总线,用于连接一个主设备和多个从设备。DS18B20是这种系统中的常用从设备之一。
硬件结构:
执行序列:
单总线信号(信号类型和时序):
六、示例代码下载:
通过网盘分享的文件:15-DS18B20模块读取
链接: https://pan.baidu.com/s/1TDrklUD8ns_2mFGLgW2WKw?pwd=aq7r 提取码: aq7r
作者:The_xz