使用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