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.hqwc.cn/news/610944.html

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

相关文章

基于PyAutoGUI图片定位的自动化截图工具--jmeter部分

1、计划 压测完成后需要编写性能测试报告&#xff0c;报告中所需数据截图较多&#xff0c;使用自动化操作方便快捷&#xff0c;就编写一个界面工具以便后续复用。之前编写过loadrunner报告的自动化截图脚本&#xff0c;现在用jmeter也比较多&#xff0c;就编写jmeter部分&#…

UNet网络学习记录

如下图所示&#xff0c;整个网络结构包括两部分&#xff0c;编码结构和解码结构&#xff0c;编码结构是对特征进行提取&#xff0c;解码结构是对特征进行还原&#xff1b;如下右图所示&#xff0c;这个步骤包括数据集的加载&#xff0c;网络的搭建&#xff0c;训练网络&#xf…

计算机网络常见面试总结

文章目录 1. 计算机网络基础1.1 网络分层模型1. OSI 七层模型是什么&#xff1f;每一层的作用是什么&#xff1f;2.TCP/IP 四层模型是什么&#xff1f;每一层的作用是什么&#xff1f;3. 为什么网络要分层&#xff1f; 1.2 常见网络协议1. 应用层有哪些常见的协议&#xff1f;2…

力扣HOT100 - 160. 相交链表

解题思路&#xff1a; /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) {* val x;* next null;* }* }*/ public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if…

无人新零售引领的创新浪潮

无人新零售引领的创新浪潮 在数字化时代加速演进的背景下&#xff0c;无人新零售作为商业领域的一股新兴力量&#xff0c;正以其独特的高效性和便捷性重塑着传统的购物模式&#xff0c;开辟了一条充满创新潜力的发展道路。 依托人脸识别、物联网等尖端技术&#xff0c;无人新…

题目 2349: 信息学奥赛一本通T1437-扩散【二分答案】

信息学奥赛一本通T1437-扩散 - C语言网 (dotcpp.com) #include <iostream> #include <algorithm> using namespace std; #define int long long const int N2e2; int n; struct node{int x,y; }a[N]; int fa[N]; int dist[N][N];//记录两坐标间的曼哈顿距离 int fi…

玩机进阶教程------手机定制机 定制系统 解除系统安装软件限制的一些步骤解析

定制机 在于各工作室与商家合作定制rom中有一些定制机。限制用户私自安装第三方软件。或者限制解锁 。无法如正常机登陆账号等等。定制机一般用于固定行业或者一些部门。专机专用。例如很多巴枪扫描机型等等。或者一些小牌机型。对于没有官方包的机型首先要导出各个分区来制作…

代码随想录算法训练营Day52|LC300 最长递增子序列LC 674 最长连续递增序列LC 718 最长重复子数组

一句话总结&#xff1a;动规做多了就豁然开朗了。 原题链接&#xff1a;300 最长递增子序列 按照动规五部曲&#xff1a; 首先确定dp数组及下标的含义&#xff1a;dp[i]表示以nums[i]结尾的最长子序列的长度&#xff1b;确定状态转移方程&#xff1a;如果nums[i] > nums[j…

风储微网虚拟惯性控制系统simulink建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 风储微网虚拟惯性控制系统simulink建模与仿真。风储微网虚拟惯性控制系统是一种模仿传统同步发电机惯性特性的控制策略&#xff0c;它通过集成风力发电系统、储能系统和其他分…

Java工具类:批量发送邮件(带附件)

​ 不好用请移至评论区揍我 原创代码&#xff0c;请勿转载&#xff0c;谢谢&#xff01; 一、介绍 用于给用户发送特定的邮件内容&#xff0c;支持附件、批量发送邮箱账号必须要开启 SMTP 服务&#xff08;具体见下文教程&#xff09;本文邮箱设置示例以”网易邮箱“为例&…

微服务学习(黑马)

学习黑马的微服务课程的笔记 导学 微服务架构 认识微服务 SpringCloud spring.io/projects/spring-cloud/ 服务拆分和远程调用 根据订单id查询订单功能 存在的问题 硬编码 eureka注册中心 搭建eureka 服务注册 在order-service中完成服务拉取 Ribbon负载均衡 Nacos注册中心…

ELK-Kibana 部署

目录 一、在 node1 节点上操作 1.1.安装 Kibana 1.2.设置 Kibana 的主配置文件 1.3.启动 Kibana 服务 1.4.验证 Kibana 1.5.将 Apache 服务器的日志&#xff08;访问的、错误的&#xff09;添加到 ES 并通过 Kibana 显示 1.6. 浏览器访问 二、部署FilebeatELK&…