51单片机DS18B20的使用

news2024/11/17 6:55:47

文章目录

  • 前言
  • 一、DS18B20介绍
  • 二、单总线协议
  • 三、DS18B20引脚说明
  • 四、DS18B20程序编写
    • 1.DS18B20复位函数
    • 2.DS18B20存在检测
    • 3.DS18B20读取一个bit和一个byte函数
    • 4.DS18B20写一个字节函数
    • 5.开始温度转换函数
    • 6.DS18B20初始化函数
    • 7.DS18B20读取温度函数
  • 五、代码测试
  • 总结


前言

本篇文章将带大家学习DS18B20的使用,并将DS18B20显示到数码管中。

一、DS18B20介绍

DS18B20是一种数字温度传感器,可直接将温度转换为数字信号输出。它是一种高精度、低功耗、单总线温度传感器,具有以下特点:

精度高:DS18B20的温度测量精度为±0.5℃,可满足大多数应用的需求。

低功耗:DS18B20的工作电压范围为3V-5.5V,工作电流仅为1mA,非常适合应用于低功耗设备中。

单总线协议:DS18B20采用单总线协议,只需要一条数据线即可实现数据传输和电源供应,简化了电路设计。

高精度:DS18B20内置16位ADC,可以在-55℃到+125℃的温度范围内进行测量,且具有高抗干扰性能。

体积小:DS18B20的封装形式为TO-92、TO-92S、SOT-223等,体积小巧,方便集成到各种应用中。
DS18B20应用广泛,可用于温度测量、温度控制、温度报警等各种场合。常见的应用包括室内温度控制、电子温度计、冰箱温度监测、工业自动化等。由于其低功耗、高精度、体积小等特点,DS18B20在物联网等领域也得到了广泛应用。

二、单总线协议

单总线协议是一种串行通信协议,它可以通过一根线实现数据传输和电源供应。在单总线协议中,数据和时钟信号共用一根线,因此只需要一条线就可以实现数据传输和设备控制,简化了电路设计,降低了成本。
在单总线协议中,每个设备都有一个唯一的地址,通过地址可以对设备进行选择。当主设备需要与从设备通信时,它会向总线上发送一个请求信号,同时指定通信的从设备地址。从设备接收到请求信号后,会向总线上发送应答信号,并在一段时间内提供数据。主设备在接收到应答信号后,就可以接收从设备提供的数据。
在单总线协议中,数据的传输速率较慢,一般在几千位每秒到几十万位每秒之间。因此,它主要应用于一些对通信速度要求不高的场合,例如温度传感器、湿度传感器等。同时,单总线协议具有低成本、低功耗、可靠性高等优点,在物联网、家庭自动化等领域也得到了广泛的应用。
这里我们使用的DS18B20所使用的就是单总线协议。

三、DS18B20引脚说明

DS18B20只需要三个引脚即可读取温度数据。
接线方式
GND-----51单片机的GND
VDD-----51单片机的电源引脚
DQ-------数据的读取和写入引脚
在这里插入图片描述

四、DS18B20程序编写

1.DS18B20复位函数

![在这里插入图片描述](https://img-blog.csdnimg.cn/1c0f1bc5d3c64d119074f188bd1e3fb7.png
在这里插入图片描述

/*******************************************************************************
* 函 数 名         : ds18b20_reset
* 函数功能		   : 复位DS18B20  
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ds18b20_reset(void)
{
	DS18B20_PORT=0;	//拉低DQ
	delay_10us(75);	//拉低750us
	DS18B20_PORT=1;	//DQ=1
	delay_10us(2);	//20US
}

2.DS18B20存在检测

在这里插入图片描述
首先需要等待一个低电平,当等待到低电平后就等待一个高电平,当同时满足这两个条件时就说明DS18B20是存在的。

/*******************************************************************************
* 函 数 名         : ds18b20_check
* 函数功能		   : 检测DS18B20是否存在
* 输    入         : 无
* 输    出         : 1:未检测到DS18B20的存在,0:存在
*******************************************************************************/
u8 ds18b20_check(void)
{
	u8 time_temp=0;

	while(DS18B20_PORT&&time_temp<20)	//等待DQ为低电平
	{
		time_temp++;
		delay_10us(1);	
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	else time_temp=0;
	while((!DS18B20_PORT)&&time_temp<20)	//等待DQ为高电平
	{
		time_temp++;
		delay_10us(1);
	}
	if(time_temp>=20)return 1;	//如果超时则强制返回1
	return 0;
}

3.DS18B20读取一个bit和一个byte函数

DS18B20通过使用时间片来读出和写入DS18B20数据。详细介绍如下。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
根据上面的讲解我们可以写出读一个bit的函数出来。
读取一个位函数

/*******************************************************************************
* 函 数 名         : ds18b20_read_bit
* 函数功能		   : 从DS18B20读取一个位
* 输    入         : 无
* 输    出         : 1/0
*******************************************************************************/
u8 ds18b20_read_bit(void)
{
	u8 dat=0;
	
	DS18B20_PORT=0;
	_nop_();_nop_();
	DS18B20_PORT=1;	
	_nop_();_nop_(); //该段时间不能过长,必须在15us内读取数据
	if(DS18B20_PORT)dat=1;	//如果总线上为1则数据dat为1,否则为0
	else dat=0;
	delay_10us(5);
	return dat;
} 

读取一个字节函数其实就是循环8次读取bit将8个bit组合成一个byte。
这里特别要注意的就是每次读取一位,且先读低位再读高位。
读取一个字节函数

/*******************************************************************************
* 函 数 名         : ds18b20_read_byte
* 函数功能		   : 从DS18B20读取一个字节
* 输    入         : 无
* 输    出         : 一个字节数据
*******************************************************************************/
u8 ds18b20_read_byte(void)
{
	u8 i=0;
	u8 dat=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次读取一位,且先读低位再读高位
	{
		temp=ds18b20_read_bit();
		dat=(temp<<7)|(dat>>1);
	}
	return dat;	
}

4.DS18B20写一个字节函数

在这里插入图片描述
在这里插入图片描述

/*******************************************************************************
* 函 数 名         : ds18b20_write_byte
* 函数功能		   : 写一个字节到DS18B20
* 输    入         : dat:要写入的字节
* 输    出         : 无
*******************************************************************************/
void ds18b20_write_byte(u8 dat)
{
	u8 i=0;
	u8 temp=0;

	for(i=0;i<8;i++)//循环8次,每次写一位,且先写低位再写高位
	{
		temp=dat&0x01;//选择低位准备写入
		dat>>=1;//将次高位移到低位
		if(temp)
		{
			DS18B20_PORT=0;
			_nop_();_nop_();
			DS18B20_PORT=1;	
			delay_10us(6);
		}
		else
		{
			DS18B20_PORT=0;
			delay_10us(6);
			DS18B20_PORT=1;
			_nop_();_nop_();	
		}	
	}	
}

5.开始温度转换函数

在这里插入图片描述

/*******************************************************************************
* 函 数 名         : ds18b20_start
* 函数功能		   : 开始温度转换
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void ds18b20_start(void)
{
	ds18b20_reset();//复位
	ds18b20_check();//检查DS18B20
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0x44);//转换命令	
}

6.DS18B20初始化函数

初始化是非常简单的我们只需要使用之前编写好的函数,首先将DS18B20复位,然后检查DS18B20是否存在。

/*******************************************************************************
* 函 数 名         : ds18b20_init
* 函数功能		   : 初始化DS18B20的IO口 DQ 同时检测DS的存在
* 输    入         : 无
* 输    出         : 1:不存在,0:存在
*******************************************************************************/ 
u8 ds18b20_init(void)
{
	ds18b20_reset();
	return ds18b20_check();	
}

7.DS18B20读取温度函数

在DS18B20中,温度数据是以16位的方式存储的,分为高8位和低8位。因此,在读取温度数据时,需要先读取低8位数据,再读取高8位数据,然后将它们合并为16位数据。

在这里插入图片描述
通过这里我们可以知道正温度的符号位和负温度的符号位是不相同的。所以下面我们需要判断读取出来的温度是正温度还是负温度。

/*******************************************************************************
* 函 数 名         : ds18b20_read_temperture
* 函数功能		   : 从ds18b20得到温度值
* 输    入         : 无
* 输    出         : 温度数据
*******************************************************************************/
float ds18b20_read_temperture(void)
{
	float temp;
	u8 dath=0;
	u8 datl=0;
	u16 value=0;

	ds18b20_start();//开始转换
	ds18b20_reset();//复位
	ds18b20_check();//检测是否存在DS18B20
	ds18b20_write_byte(0xcc);//SKIP ROM
    ds18b20_write_byte(0xbe);//读存储器

	datl=ds18b20_read_byte();//低字节
	dath=ds18b20_read_byte();//高字节
	value=(dath<<8)+datl;//合并为16位数据

	if((value&0xf800)==0xf800)//判断符号位,负温度
	{
		value=(~value)+1; //数据取反再加1
		temp=value*(-0.0625);//乘以精度	
	}
	else //正温度
	{
		temp=value*0.0625;	
	}
	return temp;
}

五、代码测试

/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	
  u8 i=0;
  int temp_value;
  u8 temp_buf[5];

	ds18b20_init();//初始化DS18B20

	while(1)
	{				
		i++;
		if(i%50==0)//间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间
			temp_value=ds18b20_read_temperture()*10;//保留温度值小数后一位
		if(temp_value<0)//负温度
		{
			temp_value=-temp_value;
			temp_buf[0]=0x40;//显示负号	
		}
		else
		temp_buf[0]=0x00;//不显示
		temp_buf[1]=gsmg_code[temp_value/1000];//百位
		temp_buf[2]=gsmg_code[temp_value%1000/100];//十位
		temp_buf[3]=gsmg_code[temp_value%1000%100/10]|0x80;//个位+小数点
		temp_buf[4]=gsmg_code[temp_value%1000%100%10];//小数点后一位
		smg_display(temp_buf,4);
	}		
}

总结

DS18B20的总结和驱动代码编写就到这里了,希望大家下去自己能够多看数据手册多多总结经验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ERP系统哪家比较好?

ERP系统哪家好&#xff1f;在选择ERP系统时&#xff0c;我们可以按照这三个维度&#xff0c;然后再按照需求去选择ERP系统。 市面上ERP软件大概可以分为三大类&#xff1a; ① 标准ERP应用&#xff1a;功能比较固定&#xff0c;难以满足个性化需求&#xff0c;二次开发难度很高…

MySQL对表操作

结束了上一章内容&#xff0c;我们对数据库的操作有一定的了解&#xff0c;本章内容就是针对表中的数据进行操作的。 针对表中数据的操作绝大部分都是增删改查&#xff08;CRUD&#xff09;&#xff0c;CRUD也就是四个单词的缩写&#xff1a; 增加(Create)、查询(Retrieve)、…

基于微前端qiankun的tab切换

文章目录背景主应用要做的1、新建tab组件2、引入组件3、tabs.js核心4、开始使用子应用要做的1、将父应用传给子应用的props挂载在Vue对象上2、创建核心逻辑3、将核心逻辑混入到App.vue注意事项分析zy/qiankun-tabs源码index.jsactions.jstabs.js最终效果背景 我们的平时做后台…

1.1 误差的来源

不难发现&#xff0c;考察用计算机解决科学计算问题时所经历的几个环节&#xff08;如图1-1所示&#xff09;&#xff0c;其中每一步都可能产生误差&#xff0c;首先,数学模型是通过对实际问题进行抽象与简化得到的&#xff0c;它与实际问题之间有误差&#xff0e;数学模型与实…

Nginx 是如何进化到 kong 的

Nginx 是如何进化到 kong 的 在传统的互联网服务中,对网关的主要诉求就是反向代理、负载均衡、路由等基础功能。 一个经典的业务的架构图一般是采用四层 LVS 做 对外 IP 收敛,在七层采用 Nginx 来负责七层 HTTPS 协议接入,反向代理、负载均衡、路由。 Nginx 的每个 Worker…

DevOps工具集合

简介 DevOps&#xff08;Development和Operations的组合词&#xff09;是一组过程、方法与系统的统称&#xff0c;用于促进开发&#xff08;应用程序/软件工程&#xff09;、技术运营和质量保障&#xff08;QA&#xff09;部门之间的沟通、协作与整合。 它是一种重视“软件开…

近红外染料IR-825,IR-825 Maleimide,IR-825 Mal,IR-825马来酰亚胺

中文名称&#xff1a;荧光染料IR 825马来酰亚胺&#xff0c;近红外染料IR-825马来酰亚胺英文名称&#xff1a;IR825 Maleimide&#xff0c;IR-825 Maleimide&#xff0c;IR 825 Maleimide&#xff0c;IR825 Mal&#xff0c;IR-825 Mal试剂规格&#xff1a;10mg&#xff0c;25mg…

算法小抄5-原地哈希

书接上回,学会了数组中重复数字的解法三,相信接下来的题也难不倒你 找到数组中消失的数字 题目链接 题意 对于一个大小为n的数组,数组中所有的数都在[1,n]内,其中有些数字重复了,由于有些数字重复了,另一些数字就一定会确实,这次需要找到所有缺少的数字并且返回结果 有没有发…

反转链表相关的练习(上)

目录 一、反转链表 二、反转链表 || 三、两两交换链表中的结点 四、K 个一组翻转链表 一、反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,…

ip-guardip-guard如何通过准入网关对指定的服务器进行通讯加密保护?

1、准入网关在高级配置设置受保护服务器; WEB管理界面【系统工具】,点击【配置管理】,点击参数设置,进入高级配置界面,输入配置内容即可。 [ControlServer]

使用阈值图修改角色脸部阴影

大家好&#xff0c;我是阿赵。 之前介绍了通过修改模型顶点法线的方法&#xff0c;来解决角色模型脸部光影问题。这里再顺便介绍一下第二种方法&#xff0c;使用阈值图修改角色脸部阴影 一、角色脸部光影的问题 这个问题之前讨论过&#xff0c;由于角色脸部法线复杂&#xff0…

2023年最新交通航线(飞机、高铁)信息数据合集(含经纬度匹配)

中国高铁航线数据库Chinese High-speed Rail and Airline Database&#xff0c;CRAD&#xff09;是一个专门收集和管理航空公司和高铁公司交通航线信息的数据仓库。它包含了航线的起始点、终止点、中转点、飞行时间、票价、座位数、乘客数量、货物数量等信息。 该数据仓库可以运…

Fortinet 发布《2022下半年度全球威胁态势研究报告》,七大发现值得关注

全球网络与安全融合领域领导者Fortinet&#xff08;NASDAQ&#xff1a;FTNT&#xff09;&#xff0c;近日发布《2022 下半年度全球威胁态势研究报告》。报告指出&#xff0c;相对于组织攻击面的不断扩大以及全球威胁态势的持续演进&#xff0c;网络犯罪分子设计、优化技术与战术…

设计模式---单例模式

目录 1 简介 2 实现 3 单例模式的几种实习方式 1. 饿汉式 2. 懒汉式&#xff0c;线程不安全 3. 懒汉式&#xff0c;线程安全 4. 双检锁/双重校验锁(DCL, double-check locking) 5. 登记式/静态内部类 4 单例模式的优缺点 1 简介 单例模式(Singleton Pattern) 是 Java…

React 中五种常见的样式

React 中五种常见的样式策略 React中的样式策略主要有以下几种&#xff1a; 内联样式&#xff1a; 内联样式就是在JSX元素中&#xff0c;直接定义行内的样式&#xff1b;CSS样式表&#xff1a; 这也是我们最常用的样式策略&#xff0c;使用单独的样式表&#xff0c;使用CSS或…

lvgl 笔记 按钮部件 (lv_btn) 和 开关部件 (lv_switch)

按钮基础使用方法&#xff1a; lv_btn 和 lb_obj 使用方法一样&#xff0c;只是外表并不相同&#xff0c;基础创建方法只需一行代码。 lv_obj_t* btn lv_btn_create(lv_scr_act()); 添加大小和位置&#xff1a; lv_obj_t* btn lv_btn_create(lv_scr_act()); lv_obj_set_s…

一个小故障:vTaskGenericNotifyGiveFromISR卡死的解决

平台&#xff1a;gd32f103 freertos V10.4.3 LTS Patch 2 调试的时候发现一个问题&#xff1a; 在中断中使用 vTaskNotifyGiveFromISR(TaskHandle_ToCpu_IIC,NULL); //唤醒任务 但是程序却出现卡死现象&#xff1a; 在vTaskGenericNotifyGiveFromISR函数中。 用调试器看到…

C++ STL:string类的概述及常用接口说明

目录 一. 什么是STL 二. string类的概述 三. string类的常用接口说明 3.1 字符串对象创建相关接口&#xff08;构造函数&#xff09; 3.2 字符串长度和容量相关接口 3.3 字符访问相关接口函数 3.4 字符串删改相关接口函数 3.5 字符查找和子串相关接口函数 3.6 迭代器相…

c++11右值引发的概念

右值引用右值&&左值c11增加了一个新的类型&#xff0c;右值引用&#xff0c;记作&#xff1a;&&左值是指在内存中有明确的地址&#xff0c;我们可以找到这块地址的数据&#xff08;可取地址&#xff09;右值是只提供数据&#xff0c;无法找到地址&#xff08;不…

跨时钟域CDC

https://www.cnblogs.com/icparadigm/p/12794483.html https://www.cnblogs.com/icparadigm/p/12794422.html 亚稳态 是什么 时序逻辑在跳变时&#xff0c;由于异步信号、跨时钟域等原因&#xff0c;不满足setup或hold条件&#xff0c;输出在0和1之间产生振荡。 原因 D触发…