当前位置: 首页 > news >正文

硬件开发1-51单片机4-DS18B20

DS18B20 温度传感器驱动代码用法总结

一、DS18B20硬件介绍

1、DS18B20:

        在无干扰时,DS18B20 指示值近似室温;有自身发热或外部热源时,指示值偏向器件温度

2、通信方式:半双工

        因此,读、写和完成温度变换所需的电源可以由数据线本身提供,而不需要外部电源

        能够完成:温度转换→数据存储→与主机通信

<主从关系图>

3、优点:

        DS1820 靠 “唯一序列号” 实现了 “一根线连多个传感器且能区分彼此”,让 “多位置同时测温度” 变得更简单,因此能用于各种需要多点温度管理的场景

4、特点:

        独特的单线接口,只需1个接口引脚即可通信

        多点(multidrop)能力使分布式温度检测应用得以简化

        不需要外部元件

        可用数据线供电

        不需备份电源

        以9 位数字值方式读出温度

        在1秒(典型值)内把温度变换为数字

        用户可定义的,非易失性的温度告警设置

        告警搜索命令识别和寻址温度在编定的极限之外的器件 (温度告警情况)

        应用范围包括恒温控制,工业系统,消费类产品,温度计或任何热敏系统

5、测量范围:

          -55℃-125℃

6、测量精度:

        ±0.5℃

7、引脚排列

引 脚(8 脚 SOIC)引脚 PR35符号说明
51GND
42DQ

单线运用的数据输入 / 输出引脚:漏极开路见 “寄生电源” 一节

(51单片机连接P37引脚)

33V₍DD₎可选 V₍DD₎引脚。有关连接的细节见 “寄生电源” 一节

▲ 51单片机的P37引脚:外接上拉电阻->保证空闲状态是高电平

     满足DS18B20单总线 “空闲高电平” 的通信要求

二、代码实现

1、main.c

#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
#include "ds18b20.h"
#include "uart.h"int main(void)
{float ret = 0;xdata char s[20];Uart_Init();while (1){ret = get_tmp();sprintf(s,"%f",ret);Uart_SendStr(s);}return 0;
}

2、ds18b20.c

#include <reg51.h>
#include <stdio.h>
#include <intrins.h>
#include "delay.h"
#include "uart.h"#define DQ_HIGH ((P3 |= (1<<7))) 		//将与DQ相连接的P37号引脚制1
#define DQ_DOWN ((P3 &= ~(1<<7)))		//将与DQ相连接的P37号引脚制0
#define DQ_CHECK ((P3 & (1<<7)) != 0)		//检测DQ引脚电平 p37为1时 为 1// DQ_CHECK为1是高电平//ds18b20 复位函数
//过程满足:主机发送复位脉冲 → 传感器回应存在脉冲(有两个阶段) → 主机确认存在脉冲
int ds18b20_Reset(void)
{int t = 0;//*初始化 —> 复位和存在脉冲//ds18b20 的p3 连接着一个上拉电阻 所以空闲时是高电平DQ_DOWN;	 		//将DQ引脚拉低Delay10us(70);		// 延时700usDQ_HIGH;			//将DQ引脚拉高Delay10us(5);		// 延时50us//*检测传感器是否存在脉冲的 第一阶段 (现高电平)//在300us内检测DQ引脚是否被ds18b20拉低,被拉低代表ds18b20回复了一个存在脉冲信号while (DQ_CHECK && t < 30)	//高电平进入循环等待,低电平跳出循环(说明回复了一个存在脉冲信号){Delay10us(1);t++;		}if (t >= 30) //如果300us内没恢复低电平,返回失败{return 0;}t = 0;// *检测传感器是否存在脉冲的 第二阶段 (现低电平)// 在300us内检测DQ引脚是否被ds18b20拉高while (!DQ_CHECK && t < 30){Delay10us(1);t++;	}if (t > 30)	//如果300us内没恢复高电平,返回失败{return 0;}//两个阶段都检测成功,返回 1 表示传感器存在且正常return 1;}// 向ds18b20发送一个字节数据
void write_ds18b20(unsigned char dat)
{int i = 0;//* 循环判断要发送的数据中的8bit是1还是0// 写 1 时:只需极短拉低(≥1μs)//写 0 时:需要长拉低(≥60μs)for (i = 0; i < 8; i++){if (dat & 1)  //bit -> 1{DQ_DOWN;_nop_();_nop_();DQ_HIGH;Delay10us(5);}else  			//bit -> 0{DQ_DOWN;Delay10us(5);DQ_HIGH;}dat >>= 1;}
}// 从ds18b20读取一个字节数据
unsigned char read_ds18b20(void)
{int i = 0;unsigned char ret = 0;for (i = 0; i < 8 ; i++){DQ_DOWN;_nop_();_nop_();DQ_HIGH;_nop_();_nop_();_nop_();if (DQ_CHECK)   // 如果DQ是高位,ds18b20发送一个bit1{ret |= (1 << i);}Delay10us(5);}return ret;
}// 获取ds18b20采集到的温度
float get_tmp(void)
{short ret = 0;unsigned char tl = 0;unsigned char th = 0;ds18b20_Reset();write_ds18b20(0xCC);write_ds18b20(0x44);Delay1ms(1000);ds18b20_Reset();write_ds18b20(0xCC);write_ds18b20(0xBE);tl = read_ds18b20();th = read_ds18b20();ret = th << 8;ret |= tl;return ret * 0.0625;		
}

3、ds18b20.h

#ifndef DS18B20_H__
#define DS18B20_H__extern int ds18b20_Reset(void);
extern void write_ds18b20(unsigned char dat);
extern unsigned char read_ds18b20(void);
extern float get_tmp(void);#endif

4、uart.c

#include <reg51.h>xdata char recv_buffer[32];
unsigned int pos = 0;// 串口接收服务
void uart_RecvHandler(void) interrupt 4
{if ((SCON & (1 << 0)) == 1){if (pos < 32){recv_buffer[pos++] = SBUF;recv_buffer[pos] = 0;}SCON &= ~(1 << 0);}
}//串口初始化
void Uart_Init(void)
{//将scon寄存器中的bit6和bit7清0SCON &= ~(3 << 6);//串口工作模式选择:SMO:0 SM1:1 代表串口工作在8位UART模式SCON |= (1 << 6);// 允许串口接收数据SCON |= (1 << 4); // 串口波特率加倍PCON &= ~(1 << 6);PCON |= (1 << 7);// TMOD寄存器高四位清0// 定时器1工作在8位自动重装模式TMOD &= ~(0x0F << 4);        TMOD |= (1 << 5);            // 2 ^ 8 - 2 ^ smod * focs/32/bps/12	bps:2400TL1 = 230;			        TH1 = 230;// 允许定时器1开始计数TCON |= (1 << 6);             // 允许CPU响应中断 + 允许串口产生中断IE |= (1 << 7) | (1 << 4);    
}void Uart_SendChar(unsigned char ch)
{SBUF = ch;while ((SCON & (1 << 1)) == 0);SCON &= ~(1 << 1);}void Uart_SendStr(const char *p)
{while (*p){Uart_SendChar(*p++);} 
}void Uart_SendBuffer(const char *p,int len)
{while(len--){Uart_SendChar(*p++);}
}

5、uart.h

#ifndef UART_H__
#define UART_H__extern void Uart_Init(void);
extern void Uart_SendChar(unsigned char ch);
extern void Uart_SendStr(const char *p);
extern void Uart_SendBuffer(const char *p,int len);
extern xdata char recv_buffer[32];
extern unsigned int pos;#endif

6、delay.c

#include <intrins.h>//粗略进行延时
void delay(unsigned int n)
{while(n--);
}//12MHz晶振版本 更加精准控制时间
void Delay10us(unsigned int n)	//@12.000MHz
{unsigned char data i;_nop_();_nop_();_nop_();i = 2 * n;while (--i){			_nop_();		}
}void Delay1ms(unsigned int n)
{while(n--){Delay10us(100);}
}

7、delay.h

#ifndef DELAY_H__
#define DELAY_H__extern void delay(unsigned int n);
extern void Delay10us(unsigned int n);
extern void Delay1ms(unsigned int n);#endif

三、核心函数功能说明

文件功能核心作用
main.c主程序逻辑循环获取温度并通过串口发送
ds18b20.cDS18B20 驱动(复位 / 读写 / 测温)实现单总线通信协议,获取温度值
uart.c串口初始化与数据发送将温度数据转换为字符串输出
delay.c延时函数提供单总线通信所需的精确时序(μs 级)
.h文件函数 / 变量声明实现跨文件调用,模块解耦

四、核心流程详解(main)

1、初始化阶段:

        Uart_Init(); // 初始化串口,设置波特率、工作模式

2、2. 循环测温与发送:

        main()内的while(1)

ret = get_tmp(); // 获取温度值(float类型)

sprintf(s,"%f",ret); // 转换为字符串

Uart_SendStr(s); // 串口发送字符串

        核心是get_tmp()函数,它封装了 DS18B20 的完整测温流程

五、单总线通信协议的软件实现(DS18B20

1、复位函数:ds18b20_Reset(void)

线型图例
复位时序图

        实现的原理:DS18B20 的通信依赖严格的时序,根据时序图电平的起伏以及所需的时间进行的结合精确的延时函数,模拟时序图中 “电平起伏的时间规律”,从而实现让传感器能识别命令、传输数据(复位、写指令、读温度等操作)

        功能:向 DS18B20 发送复位信号,并检测传感器是否响应

        流程:拉低 DQ 引脚 700us(复位信号)→ 释放引脚 50us → 检测 300us 内是否收到传感器的应答信号(低电平)→ 检测 300us 内应答信号是否结束(恢复高电平)

        返回值1表示传感器响应正常;0表示无响应(通信失败)

2、写数据函数:write_ds18b20(unsigned char dat)

写时序图

        功能:向 DS18B20 写入 1 字节数据(8 位)

        原理:按位发送数据,每位时序如下:

        发送1:拉低 DQ 引脚 2 个时钟周期 → 释放引脚 → 延时 50us

        发送0:拉低 DQ 引脚 50us → 释放引脚

3、读数据函数:read_ds18b20(void)

读时序

        功能:从 DS18B20 读取 1 字节数据(8 位)

        原理:按位读取数据,每位时序如下:

        拉低 DQ 引脚 2 个时钟周期 → 释放引脚 → 延迟 3 个时钟周期后检测 DQ 引脚电平 → 高电平表示读入1,低电平表示读入0 → 延时 50us

        返回值:读取到的 1 字节数据

4、温度读取函数:get_temp(void)

        功能:触发温度转换并读取转换后的温度值

        流程

        复位传感器 → 发送跳过 ROM 指令(0xCC)→ 发送温度转换指令(0x44)→ 延时 1000ms 等待转换完成

        再次复位 → 发送跳过 ROM 指令(0xCC)→ 发送读取暂存器指令(0xBE

        读取温度低 8 位(tl)和高 8 位(th)→ 组合为 16 位数据(ret = th << 8 | tl)。

        转换为温度值:ret * 0.0625(DS18B20 的温度分辨率为 0.0625℃)

        返回值:float 类型的温度值(单位:℃)

六、使用方法

  1. 确保硬件连接正确(DQ 引脚接 P3.7,电源和地正常连接)
  2. 初始化延时函数(Delay10us()Delay1ms()
  3. 直接调用get_temp()函数即可获取当前温度,例如:
    float temp;
    temp = get_temp(); // 读取温度值
    

七、注意事项

  1. 通信时序严格依赖延时函数,若延时不准确会导致通信失败
  2. get_temp()函数中包含 1000ms 的转换等待时间,若需优化响应速度,可根据 DS18B20 的转换速率调整延时(最高精度下转换时间约 750ms)
  3. 若总线上有多个 DS18B20,需修改代码(替换0xCC指令)以支持 ROM 匹配,当前代码默认单传感器场景(跳过 ROM)

文章转载自:

http://A0ircOes.mwLxk.cn
http://2RTdnXo3.mwLxk.cn
http://UmAyZ1DK.mwLxk.cn
http://Trghvyqn.mwLxk.cn
http://eNa2EX1B.mwLxk.cn
http://GDN7g0of.mwLxk.cn
http://LVnMHRD5.mwLxk.cn
http://L0F9uFWn.mwLxk.cn
http://BSMw3RBy.mwLxk.cn
http://27iAvIWG.mwLxk.cn
http://V7kGGsv4.mwLxk.cn
http://yUzxjJk2.mwLxk.cn
http://GYpka9gJ.mwLxk.cn
http://2GXAhWJM.mwLxk.cn
http://wUWjpgGy.mwLxk.cn
http://8IAhbeGt.mwLxk.cn
http://XLsygi9V.mwLxk.cn
http://8HCx1siS.mwLxk.cn
http://bSiwY4gZ.mwLxk.cn
http://P8urdbco.mwLxk.cn
http://j3acpb1E.mwLxk.cn
http://oR6UnSz9.mwLxk.cn
http://m6TYyfWy.mwLxk.cn
http://ZlP70s8Q.mwLxk.cn
http://cRkNWmJI.mwLxk.cn
http://ZMjrXMf3.mwLxk.cn
http://5HXfpQkx.mwLxk.cn
http://OCWEUCkP.mwLxk.cn
http://lBBElq4I.mwLxk.cn
http://8PK0Oc23.mwLxk.cn
http://www.dtcms.com/a/372210.html

相关文章:

  • 【LLIE专题】LYT-Net:一种轻量级 YUV Transformer 低光图像增强网络
  • 数据库造神计划第二天---数据库基础操作
  • TypeORM 入门教程之 `@OneToOne` 关系详解
  • 嵌入式解谜日志之数据结构—基本概念
  • make_shared的使用
  • 《九江棒球》未来十年棒垒球发展规划·棒球1号位
  • agentscope1.0安装与测试
  • Shell 脚本自动安装 Nginx
  • 《探索C++11:现代语法的内存管理优化“性能指针”(下篇)》
  • Basic Pentesting: 1靶场渗透
  • NAS自建笔记服务leanote2
  • 对比Java学习Go——程序结构与变量
  • 【JavaWeb】一个简单的Web浏览服务程序
  • [C/C++学习] 7.“旋转蛇“视觉图形生成
  • webhook(Web 钩子)是什么?
  • 《2025年AI产业发展十大趋势报告》四十三
  • java面试小册(1)
  • NW506NW507美光固态闪存NW525NW539
  • [Maven 基础课程]再看下第一个 Maven 项目
  • Keil快捷键代码补全
  • 2024理想算法岗笔试笔记
  • Java面试-线程安全篇
  • 线程池深度解析:ThreadPoolExecutor底层实现与CompletableFuture异步编程实战
  • 计算机网络学习(七、网络安全)
  • 蓝奏云官方版不好用?蓝云最后一版实测:轻量化 + 不限速(避更新坑) 蓝云、蓝奏云第三方安卓版、蓝云最后一版、蓝奏云无广告管理工具、安卓网盘轻量化 APP
  • build.gradle里面dependencies compile和api的区别
  • C++20格式化字符串:std::format的使用与实践
  • UART 使用教程
  • cuda中线程id的计算方式(简单)
  • Archon02-代码解析