使用OneWire协议从DS18B20温度传感器获取温度值——跨多种单片机类型ESP,AVR,STM32等的实践指南

OneWire协议最重要的三个函数:

retset(), writeBit(), readBit()

有的真接省掉了writeBit,readBit,直接writeByte,readByte也是可以的。

下面直接上代码:

class OneWireV1{
private:
    #define TEMP_LSB    0
    #define TEMP_MSB    1

    enum IO{
        IO_INPUT=0,
        IO_OUTPUT
    };

    int pin;

public:
    OneWireV1(int pin){
        begin(pin);
    }

    ~OneWireV1(){
    }

    void begin(int pin) {
        this->pin = pin;
        ::pinMode(pin, INPUT);
    }

    uint8_t DQ(){
        return digitalRead(pin);
    }

    void DQ(int val){
        digitalWrite(pin, val);
    }

    void pinMode(IO io) {
        if (io == IO::IO_INPUT) {
            ::pinMode(pin, INPUT);
        } else {
            ::pinMode(pin, OUTPUT);
        }
    }

    void delay_us(int us){
        delayMicroseconds(us);
    }

    uint8_t reset() {
        uint8_t retries = 125;
        pinMode(IO_INPUT);
        // wait until the wire is high... just in case
        do {
            if (--retries == 0) return 0;
            delayMicroseconds(2);
        } while ( !DQ());

        uint8_t tdq;
        DQ(0);         // put low bus
        pinMode(IO_OUTPUT);
        delay_us(480);  //将总线拉低480us~960us
        DQ(1);         // release bus
        pinMode(IO_INPUT);
        delay_us(70);    // wait 60us
        tdq = DQ();
        delay_us(410);
        return tdq;
    }

    void writeBit(unsigned char wbit) {
        delay_us(3);
        DQ(0);
        pinMode(IO_OUTPUT); //设置输出模式,关键
        if (wbit) {
            // write 1
            DQ(1);
            delay_us(60);
        } else {
            // write 0
            delay_us(60);
            DQ(1);
        }
    }

    unsigned char readBit() {
        uint8_t tdq;
        pinMode(IO_OUTPUT);
        DQ(0);
        delay_us(2);
        pinMode(IO_INPUT);
        delay_us(10);
        tdq = DQ();
        delay_us(60);
        return tdq;
    }

    void writeByte(uint8_t v, uint8_t power = 0 /* = 0 */) {
        uint8_t bitMask;
        for (bitMask = 0x01; bitMask; bitMask <<= 1) {
            writeBit((bitMask & v) ? 1 : 0);
        }
        if (!power) {
            //noInterrupts();
            pinMode(IO_INPUT);
            DQ(0);
            //interrupts();
        }
    }

    uint8_t readByte() {
        uint8_t bitMask;
        uint8_t r = 0;
        for (bitMask = 0x01; bitMask; bitMask <<= 1) {
            if (readBit())
                r |= bitMask;
        }
        return r;
    }
};

DS18B20类

class DS18B20Lib{
private:
    OneWireV1 oneWire;
    uint8_t rawData[2];

public:
    DS18B20Lib(int pin):
    oneWire(pin)
    {
    }
    ~DS18B20Lib(){

    }

    void readRawData(uint8_t *data, uint8_t fields)
    {
        oneWire.reset();

        oneWire.writeByte(0xCC); //跳过rom的操作
        oneWire.writeByte(0xBE); //读取温度命令

        for (uint8_t i = 0; i < fields; i++)
        {
            data[i] = oneWire.readByte();
        }
        oneWire.reset();
    }

    void requestTemperatures(void)
    {
        oneWire.reset();
        oneWire.writeByte(0xCC, 0); //跳过rom的操作
        oneWire.writeByte(0x44, 0); //转换温度
    }

    bool isConversionComplete(void)
    {
        return (oneWire.readBit() == 1);
    }

    float getTempC(bool checkConnect = true)
    {
        readRawData(rawData, 2);
        int16_t rawTemperature = (((int16_t)rawData[1]) << 8) | rawData[0];
        float temp = 0.0625 * rawTemperature;
        if (temp < -55)
        {
            return -127;
        }
        int _offset = 0; // 温度偏差
        if (_offset != 0)
        {
            temp += _offset;
        }
        return temp;
    }

    void update() {
        // 18b20显示温度,湿度等其它的传感器数据
        requestTemperatures(); // 启动温度转换

        while (!isConversionComplete());  // wait until sensor is ready
        float tempc = getTempC(); // 获取第一个DS18B20的温度

        Serial.println(String(tempc));
    }

};

此代码在Arduino开发环境下调试通过,用的Arduino UNO R3开发板,原理是一样的,也可移植到其它开发板上。

这是用自己开发的串口调试软件接收到的数据。串口调试工具也发布了。

仓库地址:AI串口调试工具: 这是一款在DeepSeek的帮助下开发的串口调试工具,虽然功能不多,在实际的单片机开发中使用还算可以。

有问题就联系我修改吧~

作者:小玩子2016

物联沃分享整理
物联沃-IOTWORD物联网 » 使用OneWire协议从DS18B20温度传感器获取温度值——跨多种单片机类型ESP,AVR,STM32等的实践指南

发表回复