DS18B20温度传感器
简介
SHT30是一款高精度、数字输出、电容式温湿度传感器,具有 excellent 的长期稳定性和可靠性。它采用创新的电容式技术,能够提供高精度的温度和湿度测量结果。SHT30传感器具有以下特点:
- 高精度:温度和湿度测量精度可达±0.3℃和±2%RH。
引脚定义
引脚名称 | 描述 |
---|---|
VDD | 电源引脚,连接到3.3V或5V电源 |
GND | 地线引脚,连接到电路板的地线 |
DQ | 数据引脚,用于与微控制器通信 |
数据手册
代码示例
1.ESP-IDF 示例(简单使用)
#include <stdio.h>
#include <string.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#define DS18B20_PIN GPIO_NUM_1 // 定义DS18B20的GPIO引脚
static const char *TAG = "DS18B20";
// 自定义OneWire协议实现
void ds18b20_delay_us(uint32_t us) {
esp_rom_delay_us(us); // 使用 ESP-IDF 提供的精确微秒延迟函数
}
bool ds18b20_reset() {
gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DS18B20_PIN, 0); // 拉低总线
ds18b20_delay_us(480); // 持续480us
gpio_set_direction(DS18B20_PIN, GPIO_MODE_INPUT); // 切换为输入模式
ds18b20_delay_us(60); // 等待60us
bool presence = gpio_get_level(DS18B20_PIN); // 检测是否存在设备
ds18b20_delay_us(420); // 等待420us
return !presence; // 返回是否存在设备
}
void ds18b20_write_bit(bool bit) {
gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DS18B20_PIN, 0); // 拉低总线
ds18b20_delay_us(1); // 持续1us
gpio_set_level(DS18B20_PIN, bit); // 写入数据位
ds18b20_delay_us(60); // 持续60us
gpio_set_level(DS18B20_PIN, 1); // 释放总线
ds18b20_delay_us(1); // 持续1us
}
bool ds18b20_read_bit() {
gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(DS18B20_PIN, 0); // 拉低总线
ds18b20_delay_us(1); // 持续1us
gpio_set_direction(DS18B20_PIN, GPIO_MODE_INPUT); // 切换为输入模式
ds18b20_delay_us(14); // 等待14us
bool bit = gpio_get_level(DS18B20_PIN); // 读取数据位
ds18b20_delay_us(45); // 等待45us
return bit;
}
void ds18b20_write_byte(uint8_t byte) {
for (int i = 0; i < 8; i++) {
ds18b20_write_bit((byte >> i) & 0x01); // 从最低位开始写入
}
}
uint8_t ds18b20_read_byte() {
uint8_t byte = 0;
for (int i = 0; i < 8; i++) {
if (ds18b20_read_bit()) {
byte |= (1 << i); // 从最低位开始设置
}
}
return byte;
}
// 初始化DS18B20
void ds18b20_init() {
// 不需要额外初始化
}
// 添加 CRC8 计算函数
uint8_t onewire_crc8(const uint8_t *data, uint8_t len) {
uint8_t crc = 0;
while (len--) {
uint8_t inbyte = *data++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
// 读取DS18B20温度值
float ds18b20_read_temp() {
uint8_t data[9];
uint8_t crc;
// 发送复位信号
if (!ds18b20_reset()) {
ESP_LOGE(TAG, "DS18B20 not found!");
return -127.0;
}
// 发送跳过ROM命令
ds18b20_write_byte(0xCC);
// 发送转换温度命令
ds18b20_write_byte(0x44);
// 等待转换完成
vTaskDelay(pdMS_TO_TICKS(750));
// 再次发送复位信号
if (!ds18b20_reset()) {
ESP_LOGE(TAG, "DS18B20 not found!");
return -127.0;
}
// 发送跳过ROM命令
ds18b20_write_byte(0xCC);
// 发送读取数据命令
ds18b20_write_byte(0xBE);
// 读取温度数据
for (int i = 0; i < 9; i++) {
data[i] = ds18b20_read_byte();
}
// 验证CRC
crc = onewire_crc8(data, 8);
if (crc != data[8]) {
ESP_LOGE(TAG, "CRC error!");
return -127.0;
}
// 计算温度值
int16_t raw_temp = (data[1] << 8) | data[0];
float temp = (float)raw_temp / 16.0;
// 检查符号位
if (raw_temp & 0x8000) { // 如果最高位为1,表示负数
temp = -((~raw_temp + 1) / 16.0);
}
return temp;
}
void app_main(void) {
ds18b20_init(); // 初始化DS18B20
// gpio_set_direction(DS18B20_PIN, GPIO_MODE_OUTPUT);
while (1) {
float temp = ds18b20_read_temp(); // 读取温度值
if (temp != -127.0) {
ESP_LOGI(TAG, "Temperature: %.2f C", temp); // 打印温度值
} else {
ESP_LOGE(TAG, "Failed to read temperature.");
}
// gpio_set_level(DS18B20_PIN, 0); // 拉低总线
// ds18b20_delay_us(480);
// gpio_set_level(DS18B20_PIN, 1); // 释放总线
// ds18b20_delay_us(60);
vTaskDelay(pdMS_TO_TICKS(1000)); // 等待1秒
}
}
2.ESP-IDF 示例(使用esp-idf
的onewire
组件)
本示例使用 esp-idf
的 ds18b20
组件, 当然这个组件也是基于 onewire
组件的。ds18b20
组件提供了更高级的 API,可以更方便地与 DS18B20 温度传感器进行通信。
使用方法:
添加
ds18b20
组件到idf.py
文件中。 访问: ds18b20组件 在 终端执行:idf.py add-dependency "espressif/ds18b20^0.1.2"
然后编写下面的代码:
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ds18b20.h"
#include "onewire_bus.h"
#define EXAMPLE_ONEWIRE_BUS_GPIO 1
#define EXAMPLE_ONEWIRE_MAX_DS18B20 2
static const char *TAG = "ds18b20_example";
// Now you have the DS18B20 sensor handle, you can use it to read the temperature
void app_main(void)
{
float temperature = 0.0f;
// install 1-wire bus
onewire_bus_handle_t bus = NULL;
onewire_bus_config_t bus_config = {
.bus_gpio_num = EXAMPLE_ONEWIRE_BUS_GPIO,
};
onewire_bus_rmt_config_t rmt_config = {
.max_rx_bytes = 10, // 1byte ROM command + 8byte ROM number + 1byte device command, 对于 DS18B20, 这里设置为10就可以了.
};
ESP_ERROR_CHECK(onewire_new_bus_rmt(&bus_config, &rmt_config, &bus));
int ds18b20_device_num = 0;
ds18b20_device_handle_t ds18b20s[EXAMPLE_ONEWIRE_MAX_DS18B20];
onewire_device_iter_handle_t iter = NULL;
onewire_device_t next_onewire_device;
esp_err_t search_result = ESP_OK;
// create 1-wire device iterator, which is used for device search
ESP_ERROR_CHECK(onewire_new_device_iter(bus, &iter));
ESP_LOGI(TAG, "Device iterator created, start searching...");
do
{
search_result = onewire_device_iter_get_next(iter, &next_onewire_device);
if (search_result == ESP_OK)
{ // found a new device, let's check if we can upgrade it to a DS18B20
ds18b20_config_t ds_cfg = {};
// check if the device is a DS18B20, if so, return the ds18b20 handle
if (ds18b20_new_device(&next_onewire_device, &ds_cfg, &ds18b20s[ds18b20_device_num]) == ESP_OK)
{
ESP_LOGI(TAG, "Found a DS18B20[%d], address: %016llX", ds18b20_device_num, next_onewire_device.address);
ds18b20_device_num++;
}
else
{
ESP_LOGI(TAG, "Found an unknown device, address: %016llX", next_onewire_device.address);
}
}
} while (search_result != ESP_ERR_NOT_FOUND);
ESP_ERROR_CHECK(onewire_del_device_iter(iter));
ESP_LOGI(TAG, "Searching done, %d DS18B20 device(s) found", ds18b20_device_num);
while (1)
{
for (int i = 0; i < ds18b20_device_num; i++)
{
ESP_ERROR_CHECK(ds18b20_trigger_temperature_conversion(ds18b20s[i]));
ESP_ERROR_CHECK(ds18b20_get_temperature(ds18b20s[i], &temperature));
ESP_LOGI(TAG, "temperature read from DS18B20[%d]: %.2fC", i, temperature);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
3.ESP-IDF 示例2的解析
使用onewire来读取18b20的步骤是什么? 假如只有一个18b20芯片, 那么这个步骤是什么?
使用 OneWire 协议读取 DS18B20 温度传感器(只有一个芯片)的步骤可以分为以下几个阶段:
📌 一、硬件准备
使用一个 DS18B20 温度传感器
连接方式:
VCC 接电源(3.3V 或 5V)
GND 接地
DATA 接 MCU 的 GPIO 引脚,加上一个 4.7kΩ 上拉电阻 到 VCC
可以使用寄生供电模式(即 VCC 接 GND),但推荐正常供电更稳定
📌 二、软件流程概览
1. 初始化 OneWire 总线
2. 搜索设备(如果只有一个设备,可跳过搜索,直接复位后进行操作)
3. 发送 ROM 命令(由于只有一个设备,可以直接跳过 ROM)
4. 启动温度转换
5. 等待转换完成(或轮询是否完成)
6. 再次初始化总线并发送命令读取温度数据
7. 解析数据,得到实际温度值
使用onewire来读取18b20的步骤是什么? 假如有多个18b20芯片都是通过同一个接口连接起来.那么这个步骤是什么?
当你有多个 DS18B20 芯片连接在同一个 OneWire 总线上 时,读取温度的流程与只有一个芯片的情况类似,但需要额外处理设备的地址识别和轮询 。
📌 一、基本原理
多个 DS18B20 是通过 OneWire 总线并联 在一起的
每个 DS18B20 都有一个唯一的 64 位 ROM 地址(出厂烧录)
主机可以通过 MATCH ROM 命令来选择特定的 DS18B20 进行通信
📌 二、整体步骤
✅ 1. 初始化 OneWire 总线
✅ 2. 搜索总线上的所有 DS18B20 设备,保存它们的 ROM 地址
✅ 3. 对每个设备依次:
1. 发送 MATCH ROM 命令 + ROM 地址
2. 启动温度转换
3. 等待转换完成
4. 再次发送 MATCH ROM + ROM 地址
5. 读取温度数据
6. 解析为实际温度值