【51单片机】程序实验15.DS18B20温度传感器

news2025/3/13 11:37:56

主要参考学习资料:B站【普中官方】51单片机手把手教学视频

开发资料下载链接:http://www.prechin.cn/gongsixinwen/208.html

单片机套装:普中STC51单片机开发板A4标准版套餐7

目录

  • DS18B20介绍
    • 主要特性
    • 内部结构
    • 控制时序
      • 初始化时序
      • 写时序
      • 读时序
  • 硬件设计
  • 实验15 DS18B20温度传感器
    • DS18B20驱动
    • 数码管驱动
    • 主函数

DS18B20介绍

主要特性

DS18B20是达拉斯半导体公司推出的单总线接口的传感器,与传统的热敏电阻测温元件相比,它是一种新型的体积小、工作范围宽、与微处理器接口简单的数字化温度传感器,具体特点如下:

①工作电压范围为3.0V~5.5V,除了依靠电源管脚供电,也可采用寄生电源方式(DQ数据线管脚供电)。

②采用单线接口方式,与微处理器只需要一根线即可实现数据通信。

③支持多点组网功能,多个DS18B20可以同时并联在单总线上。

④不需要外围元器件,所有传感器和转换电路都集成在DS18B20中。

⑤工作温度范围为-55℃~125℃,在-10℃~85℃的精度为±0.5℃。

⑥分辨率(测量数据的细微程度)设置范围为912bit,即0.50.0625,分辨率越高,最大转换时间越慢。DS18B20默认分辨率为12bit,最大转换时间750ms。

⑦测量结果直接以数字通过DQ串行输出给CPU,同时可传输CRC校验码,具有较强的抗干扰能力。

⑧具有负压特性,GND和VDD反接时DS18B20不会因发热而烧毁,但不能正常工作。

内部结构

ROM:刻有64位序列号,可以看作是地址序列号,含有8位产品类型标号(28H)、48位DS18B20自身序列号和8位针对前56位的CRC校验码。每个DS18B20的序列号都不相同,以便实现单总线的多点组网。

高速缓存存储器:包括一个高速暂存器RAM和一个EEPROM,后者存放高/低温触发器TH、TL和结构寄存器。

高速暂存存储器:由9个字节组成:

寄存器内容字节地址
温度值低位LS Byte0
温度值高位MS Byte1
高温限值TH2
低温限值TL3
配置寄存器4
保留5
保留6
保留7
CRC校验值8

当温度转换命令44H发布后,经转换所得温度值以二进制补码形式存放在存储器MS和LS中,MS的高5位为符号位,若温度非负,则符号位均为0,将测得的数值乘以分辨率即为实际温度;温度为负时,符号位均为1,测得的数值需先取反后加一再乘以分辨率。

配置寄存器:高3位依次为TM、R1、R0,低5位均为1。TM为测试模式位,用于设置DS18B20在工作模式还是测试模式,在出厂时已被设置为1(工作模式),不宜改动。R1和R0用于设置分辨率,默认均为1,如下表所示:

R1R0精度最大转换时间
009bit93.75ms
0110bit187.5ms
1011bit375ms
1112bit750ms

控制时序

单总线器件需要严格的信号时序来保证数据的完整性,DS18B20的时序包括初始化时序、写时序、读时序。DS18B20发送命令和数据的字节均是低位在前。

初始化时序

单总线的所有通信均以初始化时序开始。①主机将总线先置高后拉低,保持480960μs。②主机释放总线,电阻上拉,等待DS18B20在1560μs后响应。③DS18B20拉低总线,保持60~240μs。④主机读取到低电平后继续延时,延时时间从释放总线算起至少480μs。

写时序

写时序包括写0和写1,所有写时序的过程至少需要60μs,且两次独立的写时序之间至少需要1μs的恢复时间。写时序均起始于主机拉低总线,若写0则延时60μs后拉高总线并继续延时2μs;若写1则延时大概2μs后拉高总线并继续延时60μs。

读时序

单总线器件仅在主机发出读时序后才向主机发送数据,所以在主机发出读取命令之后必须马上产生读时序。读时序的过程也至少需要60μs,两次独立的读时序之间至少需要1μs的恢复时间。读时序均由主机产生至少1μs的低电平发起,随后释放总线,并在其后的15μs之间采集总线状态,低电平则读0,高电平则读1。

DS18B20典型的温度读取过程:复位(初始化时序)→发动SKIP ROM命令(0XCC)→发送开始转换命令(0X44)→延时→复位→发送SKIP ROM命令(0XCC)→发送读存储器命令(0XBE)→连续读出两个字节的温度数据→结束。

硬件设计

本实验板载DS18B20传感器的数据总线绑定到P3.7IO口管脚。

实验15 DS18B20温度传感器

实现功能:插上DS18B20温度传感器,数码管显示检测的温度值。

DS18B20驱动

按照实验14中的多文件工程框架,在App>ds18b20中创建:

ds18b20.h

#ifndef _DS18B20_H
#define _DS18B20_H

#include "public.h"

//定义IO管脚
sbit DS18B20_PORT = P3^7;

//声明主函数需要的源文件函数
u8 ds18b20_init(void);
float ds18b20_read_temperature(void);

#endif

ds18b20.c

#include "ds18b20.h"
//通过intrins.h调用延时2μs需要用到的nop函数
#include "intrins.h"

//复位函数
void ds18b20_reset(void)
{
	DS18B20_PORT = 0;
	delay_10us(75);
	DS18B20_PORT = 1;
	delay_10us(2);
}

/*
检测DS18B20函数是否存在
若一直为高电平或低电平则不存在,返回1,否则返回0
*/
u8 ds18b20_check(void)
{
	//计时器变量
	u8 time_temp = 0;
	//检测低电平
	while(DS18B20_PORT && time_temp<20)
	{
		time_temp++;
		delay_10us(1);
	}
	//若等待超时则返回1,否则重置计时器
	if(time_temp >= 20)return 1;
	else time_temp = 0;
	//检测高电平
	while((!DS18B20_PORT) && (time_temp<20))
	{
		time_temp++;
		delay_10us(1);
	}
	//若等待超时则返回1,否则返回0
	if(time_temp >= 20)return 1;
	return 0;
}

//初始化同时检测存在
u8 ds18b20_init(void)
{
	ds18b20_reset();
	return ds18b20_check();
}

//写字节函数
void ds18b20_write_byte(u8 dat)
{
	//8位输入循环控制变量
	u8 i = 0;
	//存储准备输入的位的变量
	u8 temp = 0;
	//从低到高按位输入
	for(i=0;i<8;i++)
	{
		//和00000001进行与运算提取最低位
		temp = dat & 0X01;
		//字节右移将次低位移到最低位
		dat >>= 1;
		//根据temp写1或写0
		if(temp)
		{
			//拉低总线
			DS18B20_PORT = 0;
			//延时2μs,nop函数延时1个机器周期,12MHz下即为1μs
			_nop_();_nop_();
			//写入1
			DS18B20_PORT = 1;
			//延时60μs
			delay_10us(6);
		}
		else
		{
			//拉低总线写入0
			DS18B20_PORT = 0;
			//延时60μs
			delay_10us(6);
			//释放总线
			DS18B20_PORT = 1;
			//延时2μs
			_nop_();_nop_();
		}
	}
}

//读取一个位
u8 ds18b20_read_bit(void)
{
	//存储读取数据的变量
	u8 dat = 0;
	//拉低总线
	DS18B20_PORT = 0;
	//延时2μs
	_nop_();_nop_();
	//释放总线后读取
	DS18B20_PORT = 1;
	if(DS18B20_PORT)dat = 1;
	else dat = 0;
	delay_10us(5);
	return dat;
}

//读取一字节
u8 ds18b20_read_byte(void)
{
	//8位读取循环控制变量
	u8 i = 0;
	//存储读取到的每一位的变量
	u8 temp = 0;
	//将每一位存储进字节的变量
	u8 dat = 0;
	//从低到高按位读取
	for(i=0;i<8;i++)
	{
		//读取一位
		temp = ds18b20_read_bit();
		//字节右移一位并将新位存储到最高位
		dat >>= 1;
		//或运算防止其他位被擦除
		dat |= temp << 7;
	}
	return dat;
}

//温度读取函数
float ds18b20_read_temperature(void)
{
	//存储高八位数值
	u8 dath = 0;
	//存储低八位数值
	u8 datl = 0;
	//存储完整十六位数值
	u16 value = 0;
	//存储转换得到的实际温度
	float temp = 0;
	//参照读时序介绍中的温度读取过程
	ds18b20_reset();
	ds18b20_check();
	ds18b20_write_byte(0XCC);
	ds18b20_write_byte(0X44);
	ds18b20_reset();
	ds18b20_check();
	ds18b20_write_byte(0XCC);
	ds18b20_write_byte(0XBE);
	//先读低八位,后读高八位
	datl = ds18b20_read_byte();
	dath = ds18b20_read_byte();
	//高八位移到十六位中的高八位再与低八位结合得到完整的十六位数值
	value = (dath << 8) + datl;
	//和1111100000000000与运算检测符号位
	if((value&&0XF800) == 0XF800)
	{
		//符号位均为1则取反加一得到正值
		value = (~value) + 1;
		//计算实际温度
		temp = value * (-0.0625);
	}
	else temp = value * 0.0625;
	return temp;
}

数码管驱动

数码管驱动延用实验14,但为了数码管显示更加自定义,可以显示负号、小数点等符号,段码值转换功能将移到函数外部来完成,即参数dat直接传入段码值,以下是smg.c修改后的程序:

#include "smg.h"

u8 gseg_code[16] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};

void seg_display(u8 dat[], u8 pos)
{
	u8 i = 0;
	u8 pos_temp = pos - 1;
	for(i = pos_temp;i < 8;i++)
	{
		switch(i)
		{
			case 0: LSC = 1;LSB = 1;LSA = 1;break;
			case 1: LSC = 1;LSB = 1;LSA = 0;break;
			case 2: LSC = 1;LSB = 0;LSA = 1;break;
			case 3: LSC = 1;LSB = 0;LSA = 0;break;
			case 4: LSC = 0;LSB = 1;LSA = 1;break;
			case 5: LSC = 0;LSB = 1;LSA = 0;break;
			case 6: LSC = 0;LSB = 0;LSA = 1;break;
			case 7: LSC = 0;LSB = 0;LSA = 0;break;
		}
		//此处删去gesg_code[]
		SEG_A_DP_PORT = dat[i-pos_temp];
		delay_10us(100);
		SEG_A_DP_PORT = 0x00;
	}
}

主函数

#include "public.h"
#include "smg.h"
#include "ds18b20.h"

void main()
{
	//读取温度间隔的延时控制变量
	u8 i = 0;
	//本实验对温度保留一位小数处理,方法为先乘十后提取整数部分,在数码管上添加小数点显示
	int temp_value = 0;
	//存储每一位供数码管显示的段码值,温度测量结果最高占用5位数码管
	u8 temp_buf[5];
	//初始化
	ds18b20_init();
	while(1)
	{
		//计时器累加
		i++;
		//计时器延时50ms后读取,可自行调整
		if(i%50 == 0)temp_value = ds18b20_read_temperature() * 10;
		//判断温度正负
		if(temp_value < 0)
		{
			//若温度为负,将温度转为正以便拆解数位,并使第一个数码管显示负号
			temp_value = -temp_value;
			temp_buf[0] = 0X40;
		}
		else
			//若温度为正,第一个数码管不显示
			temp_buf[0] = 0X00;
		//将温度拆解数位并转换为段码值依次存储
		temp_buf[1] = gseg_code[temp_value / 1000];
		temp_buf[2] = gseg_code[temp_value % 1000 / 100];
		temp_buf[3] = gseg_code[temp_value % 100 / 10] | 0X80;
		temp_buf[4] = gseg_code[temp_value % 10];
		//将温度显示在数码管后5位上
		seg_display(temp_buf, 4);
	}
}

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

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

相关文章

Vue项目上传到GitHub,vscode拉取vue项目更新后推送到GitHub上

1、新建Vue项目 2、在GitHub新建仓库 3、留意建立好仓库后提示的命令 4、进入vue项目目录&#xff0c;在空白处点击鼠标右键选择git bash here 5、输入命令 git init git add . git commit -m "注释内容" 输入之前创建GitHub仓库后记下的代码的第一句 git remote…

InternVL:论文阅读 -- 多模态大模型(视觉语言模型)

更多内容&#xff1a;XiaoJ的知识星球 文章目录 InternVL: 扩展视觉基础模型与通用视觉语言任务对齐1.概述2.InternVL整体架构1&#xff09;大型视觉编码器&#xff1a;InternViT-6B2&#xff09;语言中间件&#xff1a;QLLaMA。3&#xff09;训练策略&#xff08;1&#xff09…

【BUG】类文件具有错误的版本 61.0, 应为 52.0,请删除该文件或确保该文件位于正确的类路径子目录中。

报错&#xff1a; [ERROR] 类文件具有错误的版本 61.0, 应为 52.0 [ERROR] 请删除该文件或确保该文件位于正确的类路径子目录中。 报错截图&#xff1a; 原因&#xff1a;Java 版本和 Spring 不兼容&#xff0c;显示 Spring 版本过高 解决方法 1. 使用更高版本的 J…

康谋应用 | 基于多传感器融合的海洋数据采集系统

在海洋监测领域&#xff0c;基于无人艇能够实现高效、实时、自动化的海洋数据采集&#xff0c;从而为海洋环境保护、资源开发等提供有力支持。其中&#xff0c;无人艇的控制算法训练往往需要大量高质量的数据支持。然而&#xff0c;海洋数据采集也面临数据噪声和误差、数据融合…

双周报Vol.67: 模式匹配支持守卫、LLVM 后端发布、支持 Attribute 语法...多项核心技术更新!

2025-03-10 语言更新 模式匹配支持守卫&#xff08;Pattern Guard&#xff09; 模式守卫可以通过在模式后追加 if ... 的语法结构来指定。有模式守卫的分支只有在被模式匹配的值满足对应模式&#xff0c;并且模式守卫为真的情况下才会执行。如果模式守卫为假&#xff0c;则会…

MCP-代码解读TypeScript版本

MCP-代码解读TypeScript版本 文章目录 MCP-代码解读TypeScript版本1-参考网址2-TypeScript代码3-代码解读1-[非重点]定义函数2-[非重点]定义工具说明3-[重点]运行MCP服务 1-参考网址 B站视频参考 2-TypeScript代码 import { McpServer } from "modelcontextprotocol/sd…

写了一个二叉树构造函数和画图函数,方便debug

代码 class TreeNode(object):def __init__(self, val, leftNone, rightNone):self.val valself.left leftself.right rightdef construct_tree(nodes):if not nodes:return Noneroot TreeNode(nodes[0])queue [root]index 1while index < len(nodes):node queue.p…

docker 小记

一、卸载 查看当前版本 docker -v2. 如果有&#xff0c;先停止docker systemctl stop docker如果是yum安装&#xff0c;卸载方式为 #已防版本冲突&#xff0c;直接卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-lat…

G-Star 公益行起航,挥动开源技术点亮公益!

公益组织&#xff0c;一直是社会温暖的传递者&#xff0c;但在数字化浪潮中&#xff0c;也面临着诸多比大众想象中复杂的挑战&#xff1a;项目管理如何更高效&#xff1f;志愿者管理又该如何创新&#xff1f;宣传推广怎么才能更有影响力&#xff1f;内部管理和技术支持又该如何…

k9s入门及实战

概述 k9s&#xff0c;GitHub&#xff0c;是用于管理k8s集群的CLI&#xff0c;提供一个终端UI来与k8s集群进行交互。通过封装kubectl功能&#xff0c;k9s会以特定时间间隔监控k8s的变化&#xff0c;默认为2秒&#xff0c;并提供后续命令来与k8s资源进行交互&#xff0c;k9s可让…

redis增加ip白名单

Redis增加IP白名单 随着互联网的快速发展&#xff0c;网络安全问题也日益凸显。为了保护服务器安全&#xff0c;我们常常需要对访问服务器的IP地址进行限制。而Redis作为一种高性能的缓存数据库&#xff0c;可以用来实现IP白名单功能。本文将介绍如何使用Redis来增加IP白名单&…

git commit messege 模板设置 (规范化管理git)

配置方法 git config --global core.editor vim &#xff08;设置 Git 的默认编辑器为 Vim&#xff09;在用户根目录下&#xff08;~&#xff09;&#xff0c;创建一个.git_commit_msg文件&#xff0c;然后把下面的内容拷贝到文件中并保存。 [version][模块][类型]{解决xxx问题…

Franka机器人ROS 2 发布:赋能机器人研究和行业应用

Franka机器人 ROS 2 发布&#xff1a;赋能机器人研究和行业应用 Franka ROS 2 发布&#xff1a;赋能机器人研究和行业应用 由zlem Odeh 于Franka Robotics 发布 在机器人操作系统 (ROS) 等技术和生态系统的推动下&#xff0c;机器人世界正以前所未有的速度发展。ROS 2 是广受…

docker部署jenkins,安装使用一条龙教程

Jenkins k8s 实现CI/CD 一、简介 1. JenKins是什么? Jenkins是一个开源软件项目&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控持续重复的工作&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使软件项目可以进行持续集成。 2. 什么是CI / CD…

短视频下载去水印,用什么工具好?

去除视频和图片水印是许多用户的需求&#xff0c;尤其是在分享或保存内容时。以下是6款超好用的工具&#xff0c;帮助你轻松去除水印&#xff0c;享受纯净的视觉体验&#xff1a; 1. 易下载去水印小程序 特点&#xff1a; 操作简单&#xff0c;支持抖音、快手、小红书、哔哩哔哩…

推理大模型时代,TextIn ParseX助力出版业知识资产重构

在大语言模型&#xff08;LLM&#xff09;与推理能力快速进化的技术浪潮下&#xff0c;出版机构沉淀数十年的非结构化数据资产&#xff0c;包括书籍、期刊、手稿及历史档案&#xff0c;正在焕发新的机遇。基于文档解析、NLP与大模型的推理生成能力&#xff0c;我们在图书馆层层…

Redis 2025/3/9

Redis主从集群 搭建主从集群 Redis并发能力非常强&#xff0c;单节点能够达到数万的并发。 不过对一些用户规模大&#xff0c;并发量比较高的应用来讲&#xff0c;数万并发不太够。这时候就用到redis的集群了。因为Redis中的数据通常读多写少&#xff0c;所以最常用的集群方…

2min搞定~Mac Pro 编译安装 Nginx 1.8.1

2min搞定&#xff5e;Mac Pro 编译安装 Nginx 1.8.1 一安装流程简述1、编译源码前&#xff0c;获取要依赖的源码包2、进行编译、安装nginx3、启动 二、实战部分&#xff1a;测试demo1、nginx.conf改动2、代码改动3、访问 一安装流程简述 阿哟啊哟老铁&#xff0c;别嫌我啰嗦奥…

要在Unreal Engine 5(UE5)中实现角色打击怪物并让怪物做出受击反应,

UE5系列文章目录 文章目录 UE5系列文章目录前言一、实现思路二、最终效果 前言 ue5角色受击没有播放受击动画&#xff0c;主角达到怪物身上没有反应 一、实现思路 要在Unreal Engine 5&#xff08;UE5&#xff09;中实现角色打击怪物并让怪物做出受击反应&#xff0c;你需要…

C++蓝桥杯基础篇(十一)

片头 嗨~小伙伴们&#xff0c;大家好&#xff01;今天我们来学习C蓝桥杯基础篇&#xff08;十一&#xff09;&#xff0c;学习类&#xff0c;结构体&#xff0c;指针相关知识&#xff0c;准备好了吗&#xff1f;咱们开始咯~ 一、类与结构体 类的定义&#xff1a;在C中&#x…