项目概述
基于 Raspberry Pi Pico 2 的 DS18B20 温度传感器读取方案,支持多设备 ROM 搜索与地址缓存,温度数据每 2 秒更新一次,同时以摄氏/华氏双单位显示在 LCD1602 屏幕上并通过 USB 串口输出。
硬件连接
所需硬件

树莓派 Pico

LCD 1602 I2C 屏幕

DS18B20 温度传感器
引脚对应
| Pico引脚 | 连接设备 | 说明 |
| GPIO 7 | DS18B20 DATA (DQ) | - |
| GPIO 12 | LCD1602 SDA | I2C0 数据线 |
| GPIO 13 | LCD1602 SCL | I2C0 时钟线 |
| 3.3V(OUT) | LCD1602 VCC | 屏幕供电 |
| 3.3V(OUT) | DS18B20 VDD | 传感器供电 |
| GND | DS18B20 GND, LCD1602 GND | 共地 |
软件结构
DS18B20/
├── DS18B20.c # 主程序
└── lib/
├── onewire.h / onewire.c # 1-Wire 协议驱动
├── ds18b20.h / ds18b20.c # DS18B20 高层 API
└── lcd1602_i2c.h / lcd1602_i2c.c # LCD1602 I2C 驱动
库文件功能详解
1. onewire 库 — 1-Wire 底层协议实现
这是整个项目的底层基础,实现了 Maxim 1-Wire 协议的所有时序操作。
核心数据结构:
typedef struct {
uint pin; // GPIO 引脚编号
uint8_t bitmask; // 预计算位掩码(快速访问)
uint8_t ROM_NO[8]; // 当前 ROM 地址
uint8_t LastDiscrepancy; // 搜索状态
uint8_t LastFamilyDiscrepancy;
uint8_t LastDeviceFlag;
} OneWire;
对外 API:
| 函数 | 功能 |
| onewire_init(ow, pin) | 初始化指定 GPIO 引脚上的 1-Wire 总线 |
| onewire_reset(ow) | 执行总线复位,返回 1 表示检测到设备 |
| onewire_select(ow, rom) | 通过 8 字节 ROM 地址选中指定设备 |
| onewire_skip(ow) | 跳过 ROM 选择(广播到所有设备) |
| onewire_write(ow, v, power) | 写入一个字节,power=1 时保持总线供电 |
| onewire_write_bytes(ow, buf, count, power) | 写入多个字节 |
| onewire_read(ow) | 读取一个字节 |
| onewire_read_bytes(ow, buf, count) | 读取多个字节 |
| onewire_write_bit(ow, v) | 写入单个位 |
| onewire_read_bit(ow) | 读取单个位 |
| onewire_depower(ow) | 停止强制供电 |
| onewire_reset_search(ow) | 重置搜索状态 |
库中通过 ONEWIRE_SEARCH 和 ONEWIRE_CRC 宏控制是否启用 ROM 搜索和 CRC 校验功能,可按需裁剪。
2. ds18b20 库 — 传感器高层 API
基于 OneWire 库构建,封装了 DS18B20、DS18S20 及 DS1822 型号的操作逻辑。
型号与命令定义:
#define DS18S20_MODEL 0x10
#define DS18B20_MODEL 0x28
#define DS1822_MODEL 0x22
#define DS18B20_CMD_CONVERT_TEMP 0x44
#define DS18B20_CMD_READ_SCRATCHPAD 0xBE
#define DS18B20_CMD_WRITE_SCRATCHPAD 0x4E
#define DS18B20_CMD_COPY_SCRATCHPAD 0x48
#define DS18B20_CMD_RECALL_EEPROM 0xB8
#define DS18B20_CMD_READ_POWER_SUPPLY 0xB4
#define DS18B20_CMD_ALARM_SEARCH 0xEC
Scratchpad 寄存器偏移:
#define DS18B20_SP_TEMP_LSB 0
#define DS18B20_SP_TEMP_MSB 1
#define DS18B20_SP_HIGH_ALARM 2
#define DS18B20_SP_LOW_ALARM 3
#define DS18B20_SP_CONFIG 4
#define DS18B20_SP_RESERVED 5
#define DS18B20_SP_COUNT_REMAIN 6
#define DS18B20_SP_COUNT_PER_C 7
#define DS18B20_SP_CRC 8
分辨率配置:
#define DS18B20_RES_9_BIT 0x1F
#define DS18B20_RES_10_BIT 0x3F
#define DS18B20_RES_11_BIT 0x5F
#define DS18B20_RES_12_BIT 0x7F
内部辅助函数(关键逻辑):
-
ds18b20_millis_to_wait_for_conversion(resolution):根据分辨率返回转换等待时间。9 位约 94ms,10 位 188ms,11 位 375ms,12 位 750ms。
-
ds18b20_raw_temperature(sensor, addr, raw):读取 scratchpad 并校验 CRC,成功返回 1。
-
ds18b20_raw_to_celsius(raw):将原始值转换为摄氏度,公式为 raw × 0.0625
对外 API:
| 函数 | 功能 |
| ds18b20_init(sensor, ow) | 初始化传感器实例 |
| ds18b20_discover(sensor) | 搜索总线上的所有DS18B20 设备 |
| ds18b20_get_address(sensor, index) | 获取第 index 个设备的 ROM 地址 |
| ds18b20_request_temperatures(sensor) | 向所有设备发出温度转换请求 |
| ds18b20_get_temp_c(sensor, index) | 获取指定设备的摄氏温度 |
| ds18b20_get_temp_f(sensor, index) | 获取指定设备的华氏温度 |
| ds18b20_read_scratchpad(sensor, addr, sp) | 读取 scratchpad 数据 |
| ds18b20_write_scratchpad(sensor, addr, th, tl, config) | 写入 scratchpad |
| ds18b20_set_resolution(sensor, index, resolution) | 设置分辨率 |
主程序流程
DS18B20.c 是程序入口,主要流程如下:
1. 引脚重定义
在包含头文件之前,先覆盖 LCD 的默认引脚配置:
#define LCD1602_SDA_PIN 12
#define LCD1602_SCL_PIN 13
#define LCD1602_I2C_ADDR 0x27
#define LCD1602_I2C_BAUD 100000
2. 初始化
-
初始化 stdio(USB 串口)
-
初始化 LCD1602 I2C 屏幕
-
初始化 OneWire 总线(GPIO 7)
-
初始化 DS18B20 传感器实例
-
执行 ds18b20_discover() 搜索总线上的设备
3. 主循环(每 2 秒)
-
调用 ds18b20_request_temperatures() 发起温度转换
-
等待转换完成(根据当前分辨率计算等待时间)
-
调用 ds18b20_get_temp_c() 和 ds18b20_get_temp_f() 读取温度
-
更新 LCD 显示(第一行显示摄氏温度,第二行显示华氏温度)
-
通过 printf() 输出到 USB 串口
构建方式
前提条件:
-
ARM 交叉编译工具链 arm-none-eabi-gcc
-
CMake 3.31+、Ninja 1.12+
构建步骤:
cd DS18B20
mkdir build && cd build
cmake -G Ninja ..
ninja
最好使用VScode + Raspberry Pi Pico Project 创建、编辑、编译工程,这样非常方便
5万+

被折叠的 条评论
为什么被折叠?



