单片机学习(十二)1-Wire通信协议和DS18B20温度传感器
一、DS18B20
1. DS18B20简介
DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点
- 测温范围:-55°C 到 +125°C
- 通信接口:1-Wire(单总线)
- 其它特征:可形成总线结构、内置温度报警功能、可寄生供电
2. 电路原理图
其中1和3号引脚分别连接GND
和VCC
,而二号引脚则用于使用1-Wire(单总线)接口进行通信。
即:
3. 内部结构
内部完整结构框图
- 64-BIT ROM:作为器件地址,用于总线通信的寻址
- SCRATCHPAD(暂存器):用于总线的数据交互
- EEPROM:用于保存温度触发阈值和配置参数
其中配置寄存器可以配置温度变化的精度值。
存储器结构
当我们希望修改EEPROM中存储的内容时,我们需要先将数据写入到暂存器中,然后再发送一条指令使从机将暂存器中的数据写入到EEPROM中。
二、单总线(1-Wire BUS)
由于DS18B20使用的通信接口是1-Wire,因此我们需要学习1-Wire相关的通信协议,这样才能使单片机和它进行通信。
1. 单总线简介
单总线(1-Wire BUS)是由Dallas
公司开发的一种通用数据总线
- 一根通信线:DQ
- 异步、半双工
- 单总线只需要一根通信线即可实现数据的双向传输,当采用寄生供电时,还可以省去设备的VDD线路,此时,供电加通信只需要DQ和GND两根线
2. 电路规范
- 设备的DQ均要配置成开漏输出模式
- DQ添加一个上拉电阻,阻值一般为4.7KΩ左右
- 若此总线的从机采取寄生供电,则主机还应配一个强上拉输出电路
3. 单总线的时序结构
① 初始化:
- 主机将总线拉低至少480us
- 然后释放总线,等待15~60us
- 存在的从机拉低总线60~240us以响应主机
- 最后从机将释放总线
对应的信号时序图:
② 发送一位:
- 主机将总线拉低60~120us,然后释放总线,表示发送0;
- 主机将总线拉低1~15us,然后释放总线,表示发送1。
- 从机将在总线拉低30us后(典型值)读取电平,整个时间片应大于60us
对应的信号时序图:
③ 接收一位:
- 主机将总线拉低1~15us,然后释放总线
- 然后主机在拉低后15us内读取总线电平(尽量贴近15us的末尾)
- 读取为低电平则为接收0,读取为高电平则为接收1 ,整个时间片应大于60us
对应的信号时序图:
④ 发送一个byte和接收一个byte:
这个过程和使用I2C发送和接收一个字节的数据的过程类似,都是重复发送一位或接受一位8次即可发送或接受一个byte的数据了:
注意发送和接收到的数据都是低位在前的。
4. DS18B20操作流程
- 初始化:从机复位,主机判断从机是否响应
- ROM操作:ROM指令+本指令需要的读写操作
- 功能操作:功能指令+本指令需要的读写操作
对应的ROM操作和功能操作的指令如下:
ROM指令 | 功能指令 |
---|---|
SEARCH ROM [0xF0] | CONVERT T [0x44] |
READ ROM [0x33] | WRITE SCRATCHPAD [0x4E] |
MATCH ROM [0x55] | READ SCRATCHPAD [0xBE] |
SKIP ROM [0xCC] | COPY SCRATCHPAD [0x48] |
ALARM SEARCH [0xEC] | RECALL E2 [0xB8] |
READ POWER SUPPLY [0xB4] |
各个功能指令的作用:
- CONVERT T:使用温度传感器更新温度值
- WRITE SCRATCHPAD:将各个EEPROM中的值写入到暂存器中
- READ SCRATCHPAD:读取暂存器中的值
- COPY SCRATCHPAD:将暂存器中的内容复制到EEPROM中
- RECALL E2:将EEPROM中的内容复制到暂存器中
- READ POWER SUPPLY:读取设备的供电模式【独立供电|寄生供电】
5. DS18B20数据帧
① 温度变换:初始化→跳过ROM →开始温度变换
② 温度读取:初始化→跳过ROM →读暂存器→连续的读操作
6. 温度的存储格式
里面的温度是使用补码形式存储的,具体的例子如下:
温度表示的范围是-55到+125度
三、编码实现
1. 单总线部分
我们将这部分编写到OneWire
模块中
首先是DQ引脚,根据电路原理图我们可以知道他对应的是芯片的P37
引脚,因此先把它定义出来:
sbit OneWire_DQ = P3 ^ 7;
① 初始化:
unsigned char OneWire_Init() {
unsigned char i;
unsigned char Ack;
EA=0;
{
OneWire_DQ = 1;
OneWire_DQ = 0; // 拉低
i = 227; while (--i); // delay 500μs
OneWire_DQ = 1; // 释放
i = 29; while (--i); // delay 70μs,等待从机将电平拉低
// 获取从机应答
Ack = OneWire_DQ;
i = 227; while (--i); // delay 500μs 等待时序走完
}
EA=1;
// 将从机应答返回,0表示有应答,1表示无应答
return Ack;
}
可以发现,我们的代码中出现了EA=0;
和EA=1;
,这两句代码分别是操作终端系统的总开关进行关闭和开启中断系统的,因为在单总线发送信号的过程中,如果突然来了中断,CPU转而运行中断程序,那么延时就会受到巨大的影响:
例如当前运行到delay 70μs的位置,此时来了一个中断信号,当运行完中断程序回来的时候,可能就已经延时了10ms了,这对单总线通信的影响是致命的,故我们在使用单总线发送或接受信号时都需要先关闭中断。
tips:其中的延时代码都是使用stc-isp软件进行生成的,在生成代码时需要注意晶振和8051指令集的选择:
② 发送一位:
void OneWire_SendBit(unsigned char Bit) {
unsigned char i;
EA=0;
{
OneWire_DQ = 0; // 拉低
i = 3; while (--i); // delay 10μs
// 若为1则释放总线,代表发送1;若为0一直为低电平,代表发送0
OneWire_DQ = Bit;
i = 22; while (--i); // delay 50μs
OneWire_DQ = 1; // 最后释放总线
}
EA=1;
}
③ 接收一位:
unsigned char OneWire_ReceiveBit() {
unsigned char i;
unsigned char Bit;
EA=0;
{
OneWire_DQ = 0; // 拉低
i = 1; while (--i); // delay 5μs
OneWire_DQ = 1; // 释放
i = 1; while (--i); // delay 5μs
Bit = OneWire_DQ; // 采样
i = 22; while (--i); // delay 50μs
}
EA=1;
return Bit;
}
④ 发送一个byte和接收一个byte:
void OneWire_SendByte(unsigned char byte) {
unsigned char i;
for(i = 0; i < 8; i++) {
OneWire_SendBit(byte & (0x01 << i));
}
}
unsigned char OneWire_ReceiveByte() {
unsigned char i;
unsigned char byte = 0x00;
for(i = 0; i < 8; i++) {
if(OneWire_ReceiveBit()) {
byte |= (0x01 << i);
}
}
return byte;
}
2. DS18B20模块
首先我们把需要的命令和依赖的模块(OneWire模块)添加进来:
#include "OneWire.h"
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
① 温度转换:
void DS18B20_ConvertT() {
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_CONVERT_T);
}
② 温度读取:
float DS18B20_ReadT() {
unsigned char TLSB, THSB;
int Temp;
float T;
OneWire_Init();
OneWire_SendByte(DS18B20_SKIP_ROM);
OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
TLSB = OneWire_ReceiveByte(); // 接收低八位
THSB = OneWire_ReceiveByte(); // 接收高八位
Temp = (THSB << 8) | TLSB;
T = Temp / 16.0; // 转换成float类型
return T;
}
3. main.c部分
void main() {
float T, TShow;
LCD_Init();
DS18B20_ConvertT();
Delay(1000);
while (1) {
DS18B20_ConvertT(); // 温度转换
T = DS18B20_ReadT(); // 读取温度
// 显示符号位
if (T < 0) {
LCD_ShowString(2, 0, "-");
TShow = -T;
} else {
LCD_ShowString(2, 0, "+");
TShow = T;
}
LCD_ShowNum(2, 2, TShow, 3); // 整数部分
LCD_ShowString(2, 5, "."); // 小数点
LCD_ShowNum(2, 6, (unsigned long) (TShow * 10) % 10, 1); // 小数部分,一位小数
}
}
这样我们就可以实时地展示温度了。
tips:在开头进行一次温度转换并
Delay(1000);
的原因是:温度转换是需要一定的时间的,如果我们不进行延时而直接取出温度值就会得到初始值25.0。
单片机学习(十二)1-Wire通信协议和DS18B20温度传感器的更多相关文章
- (转)SpringMVC学习(十二)——SpringMVC中的拦截器
http://blog.csdn.net/yerenyuan_pku/article/details/72567761 SpringMVC的处理器拦截器类似于Servlet开发中的过滤器Filter, ...
- Scala学习十二——高阶函数
一.本章要点 在Scala中函数是”头等公民“(可以作为参数,返回值,赋值给其他); 可以创建匿名函数,通常还会交给其他函数; 函数参数可以给出需要稍后执行的行为; 许多集合方法都接受函数参数,将函数 ...
- 自制单片机之十二……AT89C2051烧写器的制做与调试
现在都用S52了,还用C2051干嘛!价格也差不多.但是C2051的体积要比S51.S52小很多,而且引脚只有20只,在一些简单的控制中,这些引脚已足够了,小的体积更具有优势些.但目前好像还没有支持在 ...
- JVM学习十二:JVM之性能监控工具
前面我们学习了很多JVM相关的理论知识,那么本节将重点讲述的是工具的使用,正所谓:工欲善其事,必先利其器.因此,本节介绍常用的性能监控工具,用于性能监控和问题排查. 一.系统性能监控 系统性能工具用于 ...
- Java编程思想学习(十二) 数组和容器
一.数组 1).数组的多种初始化方式 下面总结了初始化数组的多种方式,以及如何对指向数组的引用赋值,使其指向另一个数组对象.值得注意的是:对象数组和普通数组的各种操作基本上都是一样的:要说有什么不同的 ...
- java web 学习十二(session)
一.Session简单介绍 在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下).因此,在需要保存用户数据时,服务 ...
- 强化学习(十二) Dueling DQN
在强化学习(十一) Prioritized Replay DQN中,我们讨论了对DQN的经验回放池按权重采样来优化DQN算法的方法,本文讨论另一种优化方法,Dueling DQN.本章内容主要参考了I ...
- Linux网络编程学习(十二) ----- 结语
该书提前看完了,重点看了第四章和第六章,第七章以后只是大致浏览了一下,如果以后工作中涉及这一块再仔细研究一下,大概花了二十天的样子,主要了解了进程间的通信方式.socket编程以及五种I/O模式,看的 ...
- springMVC学习 十二 拦截器
一 拦截器概述 拦截器技术比较像java web技术中的过滤器技术,都是发送 请求时被拦截器拦截,在控制器的前后添加额外功能.但是和Spring中的Aop技术是由区别的.AOP 在特定方法前后扩充(一 ...
随机推荐
- windows 10家庭版安装SQL Server 2014出现.net 3.5失败问题解决。
在安装SQL Server 2014的过程中,出现.net 3.5缺失,导致失败问题. 后来,研究了下,解决思路如下: 先将电脑更新到了windows 10专业版,(因为需要用到专业版才有的组策略管理 ...
- Python实用案例,Python脚本,Python实现自动监测Github项目并打开网页
往期回顾 Python实现文件自动归类 前言: 今天我们就利用Python脚本实现Github项目的更新,提醒方式是邮箱.直接开整~ 项目地址: https://github.com/kenwoodj ...
- K-Fold 交叉验证
转载--原文地址 www.likecs.com 1.K-Fold 交叉验证概念 在机器学习建模过程中,通行的做法通常是将数据分为训练集和测试集.测试集是与训练独立的数据,完全不参与训练,用于最终模型的 ...
- 透视RPC协议:SOFA-BOLT协议源码分析
前提 最近在看Netty相关的资料,刚好SOFA-BOLT是一个比较成熟的Netty自定义协议栈实现,于是决定研读SOFA-BOLT的源码,详细分析其协议的组成,简单分析其客户端和服务端的源码实现. ...
- 【NLP学习其四】如何构建自己用于训练的数据集?什么是词性标注?
数据集与词性标注 数据集是NLP中的重要一环. 但是提到数据集,很多人的第一个想法可能是:"这玩意从网上下载就好了,不用管". 真的不用管?最开始我也是这么认为的 于是我直奔CoN ...
- CentOS 8.0 安装docker 报错:Problem: package docker-ce-3:19.03.4-3.el7.x86_64 requires containerd.io >= 1
1.错误内容 package docker-ce-3:19.03.2-3.el7.x86_64 requires containerd.io >= 1.2.2-3, but none of th ...
- linux笔记1(不全,无图版)随笔
1.ls 查看当前目录下的所有内容 黑色的是文件,蓝色的是文件夹,也就是目录 2.rm -f anaconda-ks. cfg 彻底删除文件(如不确定,则需要先保存备份,也就是快照) 3.ifconf ...
- k8s之数据存储-配置存储
ConfigMap configmap是一种比较特殊的存储卷,它的主要作用是用来存储配置信息的 创建configmap.yaml,内容如下 apiVersion: v1 kind: ConfigMap ...
- centos7.5 安装jdk环境
最新下载地址 历史下载地址 [root@manage ~]# mkdir /application/ [root@manage ~]# tar -xf jdk-8u112-linux-x64.gz - ...
- 【springboot】集成Druid 作为数据库连接池
转自:https://blog.csdn.net/cp026la/article/details/86508139 1. 引言 用户的每一次请求几乎都会访问数据库,访问数据库需要向数据库获取链接,而数 ...