You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust调用DS18B20的get_temperature函数参数配置求助

问题描述

我是Rust完全新手,正在树莓派上使用ds18b20库读取传感器温度,希望调用get_temperature函数,但不清楚如何声明参数,尤其是delay和one_wire_bus。我已经解决了命名空间/名称绑定问题(我是C++背景),但卡在参数部分。能否提供一个函数调用的使用示例?

我给出的代码框架如下:

use ds18b20::{Resolution, Ds18b20};
use embedded_hal::blocking::delay::{DelayUs, DelayMs};
use embedded_hal::digital::v2::{OutputPin, InputPin};
use one_wire_bus::{self, OneWire, OneWireResult};
use core::fmt::Debug;
use std::io::Write;

fn main() {
    
    let mut delay = ?????;
    let mut one_wire_bus = ?????;
    let mut tx = ?????;  //&mut Vec::new();
    
    let temp = get_temperature(delay, tx, one_wire_bus);

    ...
    //do something whit the temp
    ...
}

该库提供的get_temperature函数实现如下:

fn get_temperature<P, E>(
    delay: &mut (impl DelayUs<u16> + DelayMs<u16>),
    tx: &mut impl Write,
    one_wire_bus: &mut OneWire<P>,
) -> OneWireResult<(), E>
    where
        P: OutputPin<Error=E> + InputPin<Error=E>,
        E: Debug
{
    // initiate a temperature measurement for all connected devices
    ds18b20::start_simultaneous_temp_measurement(one_wire_bus, delay)?;

    // wait until the measurement is done. This depends on the resolution you specified
    // If you don't know the resolution, you can obtain it from reading the sensor data,
    // or just wait the longest time, which is the 12-bit resolution (750ms)
    Resolution::Bits12.delay_for_measurement_time(delay);

    // iterate over all the devices, and report their temperature
    let mut search_state = None;
    loop {
        if let Some((device_address, state)) = one_wire_bus.device_search(search_state.as_ref(), false, delay)? {
            search_state = Some(state);
            if device_address.family_code() != ds18b20::FAMILY_CODE {
                // skip other devices
                continue;
            }
            // You will generally create the sensor once, and save it for later
            let sensor = Ds18b20::new(device_address)?;

            // contains the read temperature, as well as config info such as the resolution used
            let sensor_data = sensor.read_data(one_wire_bus, delay)?;
            writeln!(tx, "Device at {:?} is {}°C", device_address, sensor_data.temperature);
        } else {
            break;
        }
    }
    Ok(())
}
解决方案

针对树莓派环境,我们可以使用rppal库操作GPIO引脚,结合embedded-hal适配层满足OneWire和Delay的要求。以下是完整可运行示例:

首先在Cargo.toml添加依赖:

[dependencies]
ds18b20 = "0.4"
one-wire-bus = "0.2"
rppal = "0.14"
embedded-hal = "1.0"
linux-embedded-hal = "0.4"

然后是main.rs代码:

use ds18b20::{Resolution, Ds18b20};
use embedded_hal::blocking::delay::{DelayUs, DelayMs};
use embedded_hal::digital::v2::{OutputPin, InputPin};
use one_wire_bus::{OneWire, OneWireResult};
use core::fmt::Debug;
use std::io::{self, Write};
use linux_embedded_hal::Delay;
use rppal::gpio::Gpio;

fn get_temperature<P, E>(
    delay: &mut (impl DelayUs<u16> + DelayMs<u16>),
    tx: &mut impl Write,
    one_wire_bus: &mut OneWire<P>,
) -> OneWireResult<(), E>
where
    P: OutputPin<Error = E> + InputPin<Error = E>,
    E: Debug,
{
    ds18b20::start_simultaneous_temp_measurement(one_wire_bus, delay)?;
    Resolution::Bits12.delay_for_measurement_time(delay);

    let mut search_state = None;
    loop {
        if let Some((device_address, state)) = one_wire_bus.device_search(search_state.as_ref(), false, delay)? {
            search_state = Some(state);
            if device_address.family_code() != ds18b20::FAMILY_CODE {
                continue;
            }
            let sensor = Ds18b20::new(device_address)?;
            let sensor_data = sensor.read_data(one_wire_bus, delay)?;
            writeln!(tx, "Device at {:?} is {}°C", device_address, sensor_data.temperature)?;
        } else {
            break;
        }
    }
    Ok(())
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化延迟对象,用于OneWire协议时序控制
    let mut delay = Delay;

    // 初始化GPIO引脚(假设DS18B20数据脚接树莓派GPIO4,可按需修改)
    let gpio = Gpio::new()?;
    let pin = gpio.get(4)?.into_open_drain_output();
    let mut one_wire_bus = OneWire::new(pin)?;

    // 初始化输出对象,这里用标准输出打印温度,也可用Vec<u8>存储输出
    let mut tx = io::stdout();

    // 注意:函数需要可变引用,因此传递&mut delay、&mut tx、&mut one_wire_bus
    get_temperature(&mut delay, &mut tx, &mut one_wire_bus)?;

    // 若需保存温度数据,可改用Vec<u8>作为tx:
    // let mut tx_buffer = Vec::new();
    // get_temperature(&mut delay, &mut tx_buffer, &mut one_wire_bus)?;
    // let output_str = String::from_utf8(tx_buffer)?;
    // println!("{}", output_str);

    Ok(())
}

参数说明

  • delay:使用linux_embedded_hal::Delay,它实现了DelayUs和DelayMs trait,满足OneWire协议的时序延迟要求。
  • one_wire_bus:通过rppal获取GPIO引脚并转为开漏输出模式,传入OneWire::new()创建总线实例,注意修改引脚编号为实际接线的GPIO脚。
  • tx:可以用std::io::stdout()直接打印到终端,也可用Vec<u8>捕获输出内容,后续可处理这些字符串数据。
  • 函数调用必须传递可变引用(&mut),因为函数内部需要修改对象状态。

内容的提问来源于stack exchange,提问作者frave

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 04:25:21