嵌入式开发学习(STC51-13-温度传感器)

内容

通过DS18B20温度传感器,在数码管显示检测到的温度值;

DS18B20介绍

简介

DS18B20是由DALLAS半导体公司推出的一种的“一线总线(单总线)”接口的温度传感器;

与传统的热敏电阻等测温元件相比,它是一种新型的体积小、适用电压宽、与微处理器接口简单的数字化温度传感器;

特点

DS18B20温度传感器具有如下特点:

  • 适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电;
  • 温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃;
  • 可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和 0.0625℃,可实现高精度测温;
  • 在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更慢;
  • 测量结果直接输出数字温度信号,以"一根总线"串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力;
  • 负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作;

结构

DS18B20一共有三个管脚,当我们正对传感器切面(传感器型号字符那一面)时,传感器的管脚顺序是从左到右排列;

管脚1为GND,管脚2为数据DQ,管脚3为VDD;

如果把传感器插反,那么电源将短路,传感器就会发烫,很容易损坏,所以一定要注意传感器方向;

通常在开发板上都会标出传感器的凸起出,所以只需要把传感器凸起的方向对着开发板凸起方向插入即可;

DS18B20温度传感器的内部存储器包括一个高速的暂存器RAM和一个非易失性的可电擦除的EEPROM,后者存放高温度和低温度触发器TH、TL和配置寄存器;

配置寄存器是配置不同的位数来确定温度和数字的转化,配置寄存器结构如下:

TMR1R011111

低五位一直都是"1",TM是测试模式位,用于设置DS18B20在工作模式还是在测试模式,在DS18B20出厂时该位被设置为0,用户不需要去改动;

R1和R0用来设置DS18B20的精度(分辨率),可设置为9,10,11或12位,对应的分辨率温度是0.5℃,0.25℃,0.125℃和0.0625℃;

R0和R1配置如下图:
在这里插入图片描述
在初始状态下默认的精度是12位,即R0=1、R1=1;

高速暂存存储器由9个字节组成,其分配如下:
在这里插入图片描述
当温度转换命令(44H)发布后,经转换所得的温度值以二字节补码形式存放在高速暂存存储器的第0和第1个字节;

存储由两个字节组成,高字节的前5位是符号位S,单片机可通过单线接口读到该数据,读取时低位在前,高位在后,数据格式如下:
在这里插入图片描述
如果测得的温度大于0,这5位为‘0’,只要将测到的数值乘以0.0625(默认精度是12位)即可得到实际温度;
如果温度小于0,这5位为‘1’,测到的数值需要取反加1再乘以0.0625即可得到实际温度;

温度计算

温度与数据对应关系如下:
在这里插入图片描述
比如我们要计算+85度,数据输出十六进制是0X0550,因为高字节的高5位为0,表明检测的温度是正温度,0X0550对应的十进制为1360,将这个值乘以12位精度0.0625,所以可以得到+85度;

DS18B20使用

知道了怎么计算温度,接下来我们就来看看如何读取温度数据;

由于DS18B20是单总线器件,所有的单总线器件都要求采用严格的信号时序,以保证数据的完整性;

DS18B20时序包括如下几种:初始化时序、写(0和1)时序、 读(0和1)时序;

DS18B20发送所有的命令和数据都是字节的低位在前;

这里我们简单介绍这几个信号的时序:

初始化时序

初始化时序图如下:
在这里插入图片描述

单总线上的所有通信都是以初始化序列开始;

主机输出低电平,保持低电平时间至少480us(该时间的时间范围可以从480到960us),以产生复位脉冲;

接着主机释放总线,外部的上拉电阻将单总线拉高,延时15~60us,并进入接收模式;

接着DS18B20拉低总线60~240us,以产生低电平应答脉冲,若为低电平,还要做延时,其延时的时间从外部上拉电阻将单总线拉高算起最少要480us;

写时序

写时序图如下:
在这里插入图片描述
写时序包括写0时序和写1时序;

所有写时序至少需要60us,且在2次独立的写时序之间至少需要1us的恢复时间,两种写时序均起始于主机拉低总线;

写1时序:主机输出低电平,延时2us,然后释放总线,延时60us;

写0时序:主机输出低电平,延时60us,然后释放总线,延时2us;

读时序

读时序图如下:
在这里插入图片描述
单总线器件仅在主机发出读时序时,才向主机传输数据,所以,在主机发出读数据命令后,必须马上产生读时序,以便从机能够传输数据;

所有读时序至少需要60us,且在2次独立的读时序之间至少需要1us的恢复时间;

每个读时序都由主机发起,至少拉低总线1us;

主机在读时序期间必须释放总线,并且在时序起始后的15us之内采样总线状态;

一般的读时序过程为:主机输出低电平延时2us,然后主机转入输入模式延时12us,然后读取单总线当前的电平,然后延时50us;

完整过程

了解了单总线时序之后,我们来看看DS18B20的温度读取过程:
DS18B20的温度读取过程为:复位→发SKIP ROM命令(0XCC)→发开始转换命令(0X44)→延时→复位→发送SKIP ROM命令(0XCC)→发读存储器命令(0XBE)→连续读出两个字节数据(即温度)→结束;

原理图

在这里插入图片描述
由图可知,总线连接p37口,所以我们通过控制该io口的电位变化即可实现初始化以及读写时序;

思路

根据时序图编写初始化、读、写程序;(初始化包括复位和检测DS18B20是否存在)

编写检测DS18B20是否存在的程序(如果信号口一直为低电位,即判定为不存在);

按使用步骤,读取温度值,转换为十进制后,使其在数码管上显示;

编码

User

main.c

/** @Description: 通过DS18B20温度传感器,在数码管显示检测到的温度值*/
#include "public.h"
#include "smg.h"
#include "ds18b20.h"void main()
{u8 i = 0;int temp_value;u8 temp_buf[5];ds18b20_init(); // 初始化DS18B20while (1){i++;if (i % 50 == 0)								 // 间隔一段时间读取温度值,间隔时间要大于温度传感器转换温度时间(12位分辨率时转换时间为750ms)temp_value = ds18b20_read_temperture() * 10; // 保留温度值小数后一位if (temp_value < 0)								 // 负温度{temp_value = -temp_value;temp_buf[0] = 0x40; // 显示负号}elsetemp_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);}
}

Public

public.h

#ifndef _public_H
#define _public_H#include "reg52.h"typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;void delay_10us(u16 ten_us);
void delay_ms(u16 ms);#endif

public.c

#include "public.h"/*** @description: 延时函数,ten_us=1时,大约延时10us* @param {u16} ten_us 延时倍数* @return {*}*/
void delay_10us(u16 ten_us)
{while (ten_us--);
}/**ms延时函数,ms=1时,大约延时1ms**** @param {u16} ms 延时倍数* @return {*}*/
void delay_ms(u16 ms)
{u16 i, j;for (i = ms; i > 0; i--)for (j = 110; j > 0; j--);
}

App/ds18b20

ds18b20.h

#ifndef _ds18b20_H
#define _ds18b20_H#include "public.h"// 管脚定义
sbit DS18B20_PORT = P3 ^ 7; // DS18B20数据口定义// 函数声明
u8 ds18b20_init(void);
float ds18b20_read_temperture(void);#endif

ds18b20.c

#include "ds18b20.h"
#include "intrins.h"/*** @description: 复位DS18B20* @return {*}*/
void ds18b20_reset(void)
{DS18B20_PORT = 0; // 拉低DQdelay_10us(75);	  // 拉低750usDS18B20_PORT = 1; // DQ=1delay_10us(2);	  // 20US
}/*** @description: 检测DS18B20是否存在* @return {u8} 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; // 如果超时则强制返回1elsetime_temp = 0;while ((!DS18B20_PORT) && time_temp < 20) // 等待DQ为高电平{time_temp++;delay_10us(1);}if (time_temp >= 20)return 1; // 如果超时则强制返回1return 0;
}/*** @description: 从DS18B20读取一个位* @return {u8} 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,否则为0elsedat = 0;delay_10us(5);return dat;
}/*** @description: 从DS18B20读取一个字节* @return {u8} 一个字节数据*/
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;
}/*** @description: 写一个字节到DS18B20* @param {u8} dat 要写入的字节* @return {*}*/
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_();}}
}/*** @description: 开始温度转换* @return {*}*/
void ds18b20_start(void)
{ds18b20_reset();		  // 复位ds18b20_check();		  // 检查DS18B20ds18b20_write_byte(0xcc); // SKIP ROMds18b20_write_byte(0x44); // 转换命令
}/*** @description: 初始化DS18B20的IO口DQ,同时检测DS的存在* @return {u8} 1:不存在,0:存在*/
u8 ds18b20_init(void)
{ds18b20_reset();return ds18b20_check();
}/*** @description: 从ds18b20得到温度值* @return {float} 温度数据*/
float ds18b20_read_temperture(void)
{float temp;u8 dath = 0;u8 datl = 0;u16 value = 0;ds18b20_start(); // 开始转换ds18b20_reset(); // 复位ds18b20_check();ds18b20_write_byte(0xcc); // SKIP ROMds18b20_write_byte(0xbe); // 读存储器datl = ds18b20_read_byte(); // 低字节dath = ds18b20_read_byte(); // 高字节value = (dath << 8) + datl; // 合并为16位数据if ((value & 0xf800) == 0xf800) // 判断符号位,负温度{value = (~value) + 1;	  // 数据取反再加1temp = value * (-0.0625); // 乘以精度}else // 正温度{temp = value * 0.0625;}return temp;
}

App/smg

smg.h

#ifndef _smg_H
#define _smg_H#include "public.h"#define SMG_A_DP_PORT P0 // 使用宏定义数码管段码口// 定义数码管位选信号控制脚
sbit LSA = P2 ^ 2;
sbit LSB = P2 ^ 3;
sbit LSC = P2 ^ 4;extern u8 gsmg_code[17]; // 使“共阴极数码管显示0~F的段码数据”这个变量定义为外部可用void smg_display(u8 dat[], u8 pos);#endif

smg.c

#include "smg.h"// 共阴极数码管显示0~F的段码数据
u8 gsmg_code[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};/*** @description: 动态数码管显示函数* @param {u8} dat 要显示的数据* @param {u8} pos 从左开始第几个位置开始显示,范围1-8* @return {*}*/
void smg_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;}SMG_A_DP_PORT = dat[i - pos_temp]; // 传送段选数据delay_10us(100);							  // 延时一段时间,等待显示稳定SMG_A_DP_PORT = 0x00;						  // 消影}
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

结果:显示检测到的温度
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神码ai火车头标题伪原创【php源码】

这篇文章主要介绍了如何把python 代码打包成可执行软件&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 火车头采集ai伪原创插件截图&#xff1a; Python 程序封装-打包成exe程…

【Apollo学习笔记】—— 相机仿真

文章目录 前言相关代码整理 测试实践文件目录包管理BUILD文件以及cyberfile.xml文件源程序BUILD运行结果其他参考CameraOutput channels启动camera驱动启动camera video compression驱动 前言 本文是对Cyber RT的学习记录,文章可能存在不严谨、不完善、有缺漏的部分&#xff0…

揭秘程序员最喜欢的5个高薪工作

大家好&#xff0c;这里是程序员晚枫。想了解更多精彩内容&#xff0c;快来关注程序员晚枫 今天给大家推荐5个适合程序员的高薪岗位。 01 推荐岗位 以下是5个工资最高的程序员工作&#xff1a; 数据科学家&#xff1a;数据科学家是负责数据收集、处理、分析和报告的专业人员。…

mssqlmysql数据库忽略大小写

一、mssql -- 创建数据时指定排序集Latin1_General_CI_AS CREATE DATABASE [数据库名] COLLATE Latin1_General_CI_AS 查询效果&#xff1a; 二、mysql

【数学】1、导论、数学归纳法与递归、分治

文章目录 一、数学归纳法与递归1.1 数学归纳法的过程1.2 递归1.2.1 本质就是数学归纳1.2.2 递归的场景1.2.2.1 编程实现数学归纳1.2.2.2 归并排序的分治思想1.2.2.3 分布式系统的分治思想 学习目标&#xff1a; 实用主义&#xff1a;为了解决工作日常的问题&#xff0c;而不是…

S7-200SMART与ET200SP远程IO模块进行PROFINET通信的具体方法

S7-200SMART与ET200SP远程IO模块进行PROFINET通信的具体方法 使用前提: 只有标准型且固件版本为V2.4及以上的S7-200 SMART CPU才支持 PROFINET 控制器功能。 S7-200 SMART 作 PROFINET 控制器最多可带8个 IO 设备(例如:远程 IO、阀岛、变频器、伺服和机器人等)。 本例中以 …

eclipse Java Editor Templates

​ Window - Preferences - Java - Editor - Templates ​ date ${currentDate:date(yyyy.MM.dd)}

九、pig安装

1.上传pig包 2.解压文件 3.改名 4.赋权 5.配置环境变量 export PIG_HOME/usr/local/pig export PATH$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$HIVE_HOME/bin:$HBASE_HOME/bin:$SQOOP_HOME/bin:$PIG_HOME/bin 6.测试

如何在轻量级RTSP服务支持H.264扩展SEI发送接收自定义数据?

为什么开发轻量级RTSP服务&#xff1f; 开发轻量级RTSP服务的目的是为了解决在某些场景下用户或开发者需要单独部署RTSP或RTMP服务的问题。这种服务的优势主要有以下几点&#xff1a; 便利性&#xff1a;通过轻量级RTSP服务&#xff0c;用户无需配置单独的服务器&#xff0c;…

7种有效安全的网页抓取方法,如何避免被禁止?

网页抓取是一种从互联网上抓取网页内容的过程&#xff0c;但在网络抓取种相信您也经常遇到障碍&#xff1f;尤其是做跨境业务的&#xff0c;在抓取国外的网站时更有难度。但我们站在您的立场上&#xff0c;提供七种有效的方法来进行网页抓取而不被阻止&#xff0c;最大限度地降…

C语言每日一题:14《数据结构》复制带随机指针的链表

题目一&#xff1a; 题目链接&#xff1a; 思路一&#xff1a; 找相对位置暴力求解的方法&#xff1a; 1.复制一个新的链表出来遍历老的节点给新的节点赋值&#xff0c;random这个时候不去值。 2.两个链表同时遍历&#xff0c;遍历老链表的时候去寻找相对位置&#xff0c;在遍…

压力测试与测试工具jmeter的介绍

目录 一、性能指标 二、jmeter &#xff08;一&#xff09;JMeter 安装 &#xff08;二&#xff09;JMeter 压测示例 1、添加线程组 2、添加 HTTP 请求 3、添加监听器 4、启动压测&查看分析结果 &#xff08;三&#xff09;JMeter Address Already in use 错误解决 压力测…

c++11 标准模板(STL)(std::basic_ofstream)(四)

定义于头文件 <fstream> template< class CharT, class Traits std::char_traits<CharT> > class basic_ofstream : public std::basic_ostream<CharT, Traits> 类模板 basic_ofstream 实现文件上基于流的高层输出操作。它将 std::basic_ost…

HTML5 Canvas(画布)

<canvas>标签定义图形&#xff0c;比如图表和其他图像&#xff0c;你必须用脚本来绘制图形。 在画布上&#xff08; Canvas &#xff09;画一个共红色矩形&#xff0c;渐变矩形&#xff0c;彩色矩形&#xff0c;和一些彩色文字。 什么是 Canvas&#xff1f; HTML5<c…

亚马逊买家账号ip关联怎么处理

对于亚马逊买家账号&#xff0c;同样需要注意IP关联问题。在亚马逊的眼中&#xff0c;如果多个买家账号共享相同的IP地址&#xff0c;可能会被视为潜在的操纵、违规或滥用行为。这种情况可能导致账号受到限制或处罚。 处理亚马逊买家账号IP关联问题&#xff0c;建议采取以下步骤…

数学知识(三)

一、容斥原理 #include<iostream> #include<algorithm>using namespace std;const int N 20;typedef long long LL; int n,m; int p[N];int main() {cin>>n>>m;for(int i 0;i < m;i ) cin>>p[i];int res 0;//从1枚举到2^m(位运算)for(int …

burp suite 2023版 模块详解《一》

burp suite2023版 模块详解<一> Brup suite 仪表盘、目标、代理模块详解 dashboard&#xff08;仪表盘&#xff09;&#xff1a; Burp Suite的dashboard是一个总览视图&#xff0c;显示有关目标和代理的重要信息。我们可以在仪表板上查看最近操作的概要、目标的状态和代…

centos 7镜像(iso)下载图文教程(超详细)

声明&#xff1a;本教程为本人学习笔记&#xff0c;仅供参考 文章目录 前言一、阿里云镜像站下载centos 7 二、清华源下载centos 7小结 前言 声明&#xff1a;本教程为本人学习笔记&#xff0c;仅供参考 本教程将提供两种方式下载centos 7 系统镜像 1、阿里巴巴开源镜像站 2、…

关于视频汇聚融合EasyCVR平台多视频播放协议的概述

视频监控综合管理平台EasyCVR具备视频融合能力&#xff0c;平台基于云边端一体化架构&#xff0c;具有强大的数据接入、处理及分发能力&#xff0c;平台既具备传统安防视频监控的能力与服务&#xff0c;也支持AI智能检测技术的接入&#xff0c;可应用在多行业领域的智能化监管场…

4.PyCharm汉化

完成上一篇的安装之后&#xff0c;全英文的界面可能对一些英文不太好的小伙伴不太友好&#xff0c;本篇文章介绍Phcharm汉化教程&#xff1a; 点击菜单种的File-Setting 选择Marketplace在搜索框输入Chinese 点击安装 安装成功后会提示重新启动&#xff0c;点击Restart 安…