DS18B20与单片机的通信、DS18B20采集温度、MODBUS协议、练习框架

我要成为嵌入式高手之4月9日51单片机第四天!!
————————————————————————————

DS18B20温度传感器

单总线数字温度计

异步的半双工的串行通信

测量范围从-55℃ ~ +125℃,增量值为0.5℃

要用DS18B20采集温度,就要实现与单片机之间的通信,因此有两个问题

Bus master active low:主机执行低电平

DS1820 active low:DS18B20执行低电平

Both bus master and DS1820 active low:全都释放低电平

Resistor pull-up:电阻拉高

1、如何向DS18B20发送数据

sendChar(发送单字节的数据)

主机(单片机)向DS18B20写入(发送)0: 

        空闲时总线上呈现高电平,如果要发送0,就把总线电平拉低:至少(MIN)拉低15微秒,典型(TYP)拉低30微秒,最多(MAX)拉低60微秒。这样一段时间就表示单片机向DS18B20写入一个0;(由于是异步传输,故0 和 1只能靠控制时间长短来表示)

主机(单片机)向DS18B20写入(发送)1:

        空闲时总线上呈现高电平,如果要发送1,就把总线电平拉低,拉低时间大于1微秒后,立刻又将电平拉高,拉高时间为:至少(MIN)拉高15微秒,典型(TYP)拉高30微秒,最多(MAX)拉高60微秒。

2、如何从DS18B20读取数据

readChar()

MASTER SAMPLES:主机采样(读引脚电平)

主机(单片机)从DS18B20读取(接收)0:

        空闲时总线上呈现高电平,DS18B20会将电平拉低,在拉低后的15微秒以内,单片机进行采样,若为低电平,说明收到的是0;

主机(单片机)从DS18B20读取(接收)1:

        空闲时总线上呈现高电平,DS18B20会将电平拉低,在拉低后1微秒之后且15微秒以内,单片机进行采样,若为高电平,说明收到的是1;

以上两图即为DS18B20数据收发原理

———————————————————————————————————————————

DS18B20采集流程

复位

1、单片机向DS18B20发送0xCC

2、单片机向DS18B20发送0x44(启动温度变换)

3、延时(将温度模拟转换为数字需要时间,大约为700ms)

复位

4、单片机向DS18B20发送0xCC

5、单片机向DS18B20发送0xBE(读取温度)

6、单片机连续从DS18B20读取两个字节

如何将读取到的字节转换为浮点型(float)?

读出的两个字节是一个补码,需要 * 0.0625(2 ^ -4)得到温度

涉及到的问题:

        单片机P37和DS18B20总线连接起来,要是P37要拉低电平,总线要拉高电平,那到底是高电平还是低电平?

        答:一定是低电平,因为有任一方拉低,相当于该总线接地,那么就是低电平。

        那么如何保证该总线一定是高电平呢?

        答:在该总线上外接一个上拉电阻(4.7k ~ 10k)(因为51的内部构造,导致51的上拉电平非常弱,因此需要这个电阻来添一把力,保证它是高电平),这样在单片机和DS18B20同时拉高时,该总线一定是高电平。

这俩表现出一种特性:线与特性

拉高总线的操作称为:释放总线

拉低总线的操作称为:占有总线

初始化过程"复位和存在脉冲"

黑色线表示单片机拉低,此时DS18B20释放总线(最少480最多960微秒);然后单片机释放总线在60~240微秒之内DS18B20要拉低总线,这样就能检测到低电平,在240微秒之后,DS18B20再次释放总线,此时总线上必然会检测到高电平,这样就表示该信号存在可以被使用

延时10us函数

//延时10us
void delay10us(unsigned int n)	//@12.000MHz
{unsigned char data i;while (n--){i = 2;while (--i);}
}

初始化

#include "ds18b20.h"#define DS18B20CLR (P3 &= ~(1 << 7))
#define DS18B20SET (P3 |= (1 << 7))
#define DS18B20TST ((P3 & (1 << 7)) != 0)//判断总线是否为高电平,1为高电平,0为低电平void delay10us(unsigned int n)	//@12.000MHz
{unsigned char data i;while (n--){i = 2;while (--i);}
}int rest18b20(void)
{int t = 0;DS18B20CLR;//单片机拉低delay10us(70);//延时DS18B20SET;//释放总线while (t <= 24 && DS18B20TST)//240us之内,DS18B20为高电平{delay10us(1);++t;		}if (t >= 24)//超过240us{return 0;//说明初始化有问题}t = 0;while (t <= 24 && !DS18B20TST)//240us之内,DS18B20为低电平{delay10us(1);}if (t > 24){return 0;//一直为低电平,跳不上高电平,初始化有问题}	return 1;//在240us之内出现低电平,初始化正确,返回1
}

 向18b20发送数据

/********************向18b20发送数据*一次发送一个char*先发低位******************/
void sendChar(unsigned char n)//LSB先行,先发低位
{int i = 0;for (i = 0; i < 8; ++i){if ((n & 0x01) != 0)//判断要发的位不为0,此时应该找1的时序图{DS18B20CLR;_nop_();_nop_();DS18B20SET;delay10us(3);			}else{DS18B20CLR;delay10us(5);DS18B20SET;}n >>= 1;}
}

从18b20接收数据

/*********************从18b20接收数据*一次发送一个char*从低位开始接收*返回接收到的数据********************/
unsigned char readChar(void)//接收18b20的数据,每次接收一个字符
{unsigned char ret = 0;int i = 0;for (i = 0; i < 8; ++i){DS18B20CLR;//拉低总线_nop_();//空指令,但是消耗了一个指令周期,1us_nop_();DS18B20SET;//释放总线_nop_();_nop_();_nop_();//采样:DS18B20TST表示P37是(1)否(0)为高电平,若接收到1,左移或运算可以将指定位置1(第i位为1,其余位为0)ret |= DS18B20TST << i;delay10us(5);}return ret;
}

获取温度(按照流程)

float getTemerature(void)
{unsigned char t1, t2;	int ret = 0;
//接收温度的总流程rest18b20();sendChar(0xCC);sendChar(0x44);delay10us(60000);rest18b20();sendChar(0xCC);sendChar(0xBE);t1 = readChar();//低位t2 = readChar();//高位//将字符型转换为浮点型ret = t2 << 8 | t1;return ret * 0.0625;	
//
}

 main.c

如何查看获取到的温度的数据呢?

这里采用串口调试查看(uart->send_buffer)

#include "ds18b20.h"
#include "uart.h"int main(void)
{float f;char s[16];	uart_init();	while (1){f = getTemerature();sprintf(s, "%f", f);send_buffer(s, strlen(s));}return 0;
}

MODBUS协议框架

帧:

起始字节地址码功能码数据长度数据码数据码校验码 结束码
0xAA0x01
01读温度
02读秒数
03设置秒数

02xxxxxx

0x0D

例如:

读温度:

上位机发出:AA 01 01 00 ** 0D        下位机回复:AA 81 01 04 xx xx xx xx ** 0D

                        0000 0001                                        1000 0001

                        第一位0代表上位机发给下位机,第一位1代表下位机发给上位机

读秒数:

上位机发出:AA 01 02 00 ** 0D        下位机回复:AA 81 02 xx xx ** 0D

                                                                               两个字节的数值,大端发送

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

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

相关文章

Ingress配置优化和追踪

介绍 在传统的业务系统中&#xff0c;应用微服务化后&#xff0c;需要一个统一的入口来将各个服务进行整合&#xff0c;这个入口可以是Nginx、Apache、HAproxy等等。而在K8s中&#xff0c;同样需要一个工具来将应用的各个service整合到统一的入口&#xff0c;这个工具就叫Ingr…

ArcGIS Pro中的3D建模

在本文中,我讲述了我最近一直在探索的在 ArcGIS Pro 中设计 3D 模型的过程。 我的目标是尽可能避免与其他软件交互(即使是专门用于 3D 建模的软件),并利用 Pro 可以提供的可能性。 这个短暂的旅程分为三个不同的阶段:准备、组装和照明。 我们必须使用一些布局可能性以及一…

flask后端+网页前端:基于 socket.io 的双向通信和服务器部署

我想实现的效果是&#xff0c;我的服务器提供两个路由网址&#xff0c;网页A用于拍照、然后录音&#xff0c;把照片和录音传给服务器&#xff0c;服务器发射信号&#xff0c;通知另一个路由的网页B更新&#xff0c;把刚刚传来的照片和录音显示在网页上。 然后网页B用户根据这个…

前端开发中地图定位与距离计算的应用实践

前端开发中地图定位与距离计算的应用实践 在前端开发中&#xff0c;地图功能的应用日益广泛&#xff0c;无论是用户位置的定位、目标距离的计算&#xff0c;还是地址的解析与展示&#xff0c;地图都发挥着不可替代的作用。本文将重点介绍前端开发中实现地图定位、距离计算以及…

MySQL前缀索引(3/16)

前缀索引 前缀索引&#xff1a;MySQL支持前缀索引&#xff0c;允许定义字符串的一部分作为索引。如果不指定前缀长度&#xff0c;索引将包含整个字符串。前缀索引可以节省空间&#xff0c;但可能会增加查询时的记录扫描次数&#xff08;因为会查询到多个前缀相同的数据&#x…

Python(9):一文学懂进程,线程和协程

文章目录 一、进程1.创建多进程2.查看进程id3.进程池4.进程间的互相通信 二、线程1.threading线程模块2.创建多线程3.互斥锁4.死锁5.线程间的互相通信 三、协程1.认识协程2.gevent模块在爬虫中的应用 四、多线程、多进程、协程的区别 分类定义程序一个应用可以当做一个程序&…

局域网共享文件夹怎么加密?局域网共享文件夹加密方法介绍

在企业局域网中&#xff0c;共享文件夹扮演着重要的角色。为了保护数据安全&#xff0c;我们需要加密保护局域网共享文件夹。那么&#xff0c;局域网共享文件夹怎么加密&#xff1f;下面我们来了解一下吧。 局域网共享文件夹加密方法 局域网共享文件夹加密推荐使用共享文件夹加…

【计算机考研】择校!北邮VS北航,哪所毕业以后就业好?

北邮计算机专业的就业优势相较于北航可能源于多方面的因素。 北邮在计算机和通信领域的实力备受肯定&#xff0c;被誉为"信息黄埔"&#xff0c;这一声誉在一定程度上增强了北邮计算机专业毕业生的竞争力。 北邮的整体学校氛围和教育体系更加注重信息技术的发展和应…

vue表格操作列,按钮太多显示... 点击后悬浮显示全部按钮

效果: 分析原理: 一共就三步,仔细看看很简单,位置要加对,代码结构下边有demo 代码结构demo: <el-table-columnlabel"操作"align"center"fixed"right"show-overflow-tooltip><template slot-scope"scope"><el-buttonsi…

STM32电机控制固件架构

目录 一、应用程序剖析 二、面向现场的控制实现体系结构 1、参考计算循环 2、电流调节环路 3、安全回路 一、应用程序剖析 上图显示了由ST MC SDK构建的电机控制应用程序。首先&#xff0c;这样的应用程序是由电机控制工作台生成的软件项目&#xff0c;这要归功于STM32Cube…

01 SQL基础 -- 初识数据库与安装

一、初识数据库 数据库是将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合。该数据集合称为数据库(Database, DB)。用来管理数据库的计算机系统称为数据库管理系统(Database Management System, DBMS) 1.1 DBMS 的种类 DBMS 主要通过数据的保存格式…

【MySQL】数据库开篇

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8;友情提供 目录 本系列传送门 1. 什么是数据库&#xff1f; 2. 为什么使用数据库 3. 数据库的分类 4. NoSQL 与关系…

android android.permission.MANAGE_EXTERNAL_STORAGE使用

android11 及以上版本&#xff0c;如果release版本要读取外部存储公共目录&#xff0c;即sdcard公共目录&#xff0c;需要在androidManifest.xml下申明 <uses-permission android:name"android.permission.MANAGE_EXTERNAL_STORAGE" /> 如果要发版到海外&…

【UE Niagara】光束发射模块学习

效果 步骤 1. 新建一个Niagara发射器&#xff0c;使用Empty模板&#xff0c;这里命名为“NE_Beam” 打开“NE_Beam”&#xff0c;添加条带渲染器 添加“Spawn Burst Instantaneous”模块&#xff0c;设置生成数量为100 添加一个“Beam Emitter Setup”模块 再添加一个“Spawn …

Linux C应用编程:MQTT物联网

1 MQTT通信协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传 输&#xff09;是一种基于客户端-服务端架构的消息传输协议&#xff0c;如今&#xff0c;MQTT 成为了最受欢迎的物联网协议&#xff0c;已广泛应用于车联网、智能家居、即时聊…

sqoop:错误: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster(已解决)

1 报错信息 错误: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster 说明&#xff1a; 操作将数据库中的数据导入到HDFS中 执行sqoop import --connect jdbc:mysql://aaa01:3306/mysql --username root --password root --table test 时报了以下错误 2 报…

遥控小车电子方案

遥控小车的功能开发主要包括以下几个方面&#xff1a; 1.基本功能开发&#xff1a; 前进、后退、左转、右转&#xff1a;通过遥控器上的控制按钮&#xff0c;实现小车的前进、后退、左转和右转。加速、减速&#xff1a;通过遥控器上的油门控制按钮&#xff0c;实现小车的加速…

【深度学习】Fine-Grained Face Swapping via Regional GAN Inversion高保真换脸范式

文章目录 代码介绍实践效果 帮助、问询 代码 https://github.com/e4s2022/e4s 介绍 Fine-Grained Face Swapping via Regional GAN Inversion 提出一种新的高保真换脸范式&#xff0c;能够保留期望的微妙几何和纹理细节。从微观面部编辑的角度重新思考换脸任务&#xff0c;基…

Matlab 实时读取串口并绘图

Matlab 实时读取串口并绘图 Vofa Vofa 是一个很好的跨平台上位机软件&#xff0c;但是它无法保存数据&#xff0c;而且作者也并没有要继续更新的意思&#xff0c;保存数据功能应该是遥遥无期了。因此本文使用 Matlab 实时读取串口数据&#xff0c;并使用 plot 函数绘制。 vo…

洛谷P1305 新二叉树

Java 代码 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();char arr[][] new char[n][3];for (int i 0; i < n; i) {String strsc.next();char arr1[]str.toCharArray()…