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