目录
本章内容将引进DS18B20单总线数字温度传感器,并使用51单片机对实践内容进行软件仿真和实物操作,需要的相关软件如KEIL、Proteus及其相关操作可查看往期博客或者查看其他博客进行下载、学习。
实践内容:
使用51单片机的一个 IO 口模拟单总线时序与温度传感器DS18B20通信,将检测的环境温度读取出来。
一、DS18B20单总线数字温度传感器
原件介绍
DS18B20是一种数字温度传感器,采用单总线接口进行通信。它可以测量环境温度,并将其转换为数字信号输出。DS18B20具有高精度、数字输出、工作电压范围广、低功耗等特点,常用于各种温度监测应用中,如室内温度监控、工业自动化等。由于采用单总线接口,它可以方便地与微控制器等设备进行通信,并且可以通过一条总线连接多个DS18B20传感器,简化了布线结构。
DS18B20传感器有几种不同的封装类型,包括TO-92、TO-220、TO-263等,适用于不同的应用场景和安装需求。此外,DS18B20传感器还有一些衍生型号,如DS18S20、DS1822等,它们在功能和特性上与DS18B20类似,但可能有一些微小的差异。
工作原理
利用温度对其内部芯片的电特性产生微小的电压变化,这一变化被转换为数字信号。它采用了一种称为单总线协议的通信方式,即通过一个总线进行数据传输和通信。在通信过程中,主控设备发送指令给DS18B20传感器,传感器接收指令并执行相应的操作,如测量温度,并将结果通过总线返回给主控设备。由于采用单总线接口,DS18B20传感器可以通过一根总线连接到主控设备,简化了连接结构,并且可以方便地与微控制器等设备进行通信。
相关知识的详细讲解可以参考以下博客:
DB18B20的时序图讲解
https://blog.csdn.net/qzs_13933908434/article/details/8680623
DS18B20 时序完全解读
https://blog.csdn.net/farsight2009/article/details/51122678
DS18B20时序分析详细步骤
引脚功能
引脚1为地(GND)引脚,连接到电路的地;
引脚2为数据引脚(DQ),用于与单总线通信;
引脚3为电源引脚(VCC),连接到电路的电源。
单总线时序
单总线时序是一种用于串行通信的协议,通常用于单线(单总线)连接的设备之间进行通信。它允许多个设备通过共享单个数据线进行通信,从而简化了硬件连接。单总线时序具有以下特点:
单线连接:所有设备都连接到同一根数据线上,通过在线路上发送不同的电平信号来表示不同的数据或控制信息。
异步通信:单总线通常是异步通信的,即设备之间的通信不需要共享时钟信号。每个设备在适当的时机发送和接收数据,而不需要与其他设备同步。
时序规范:单总线时序规定了数据和控制信号的传输时机和格式。这包括起始位、数据位、校验位、停止位等。
主从结构:在单总线通信中通常存在主设备和从设备的概念。主设备负责发起通信请求和控制通信的时序,而从设备则响应主设备的请求并提供所需的数据。
冲突检测与解决:由于所有设备共享同一条数据线,可能会出现冲突情况。单总线协议通常包括机制来检测和解决冲突,以确保数据的正确传输。
错误检测与校正:单总线协议通常也包括一些机制来检测和校正数据传输过程中的错误,例如使用校验位或CRC校验等。
它的优点是简化了硬件连接,但也存在一些局限性,例如通信速率较低、抗干扰能力相对较弱等。
二、任务实现
proteus仿真电路原理图
代码示例
#include "reg51.h"
#include "intrins.h"
#define uchar unsigned char
#define uint unsigned int
#define out P0
sbit smg1=out^4;
sbit smg2=out^5;
sbit DQ=P3^7;
void delay5(uchar); // 延时函数
void init_ds18b20(void); //DS18B20初始化
uchar readbyte(void); // 读取一个字节数据
void writebyte(uchar); // 写入一个字节数据
uchar retemp(void); //读取温度函数
void main(void)
{
uchar i,temp;
delay5(1000); // 延时等待DS18B20初始化
while(1)
{
temp=retemp(); // 读取温度值
for(i=0;i<10;i++) // 循环显示温度值
{
out=(temp/10)&0x0f; // 写入P0端口(十位)
smg1=0; // smg1置0,控制第一个数码管
smg2=1; // smg2置1,控制第二个数码管
delay5(1000);
out=(temp%10)&0x0f; // 写入P0端口(个位)
smg1=1; // smg1置1,控制第一个数码管
smg2=0; // smg2置0,控制第二个数码管
delay5(1000);
}
}
}
void delay5(uchar n)
{
do
{
_nop_(); // 空,延时
_nop_();
_nop_();
n--;
}
while(n);
}
void init_ds18b20(void)
{
uchar x=0;
DQ =0;
delay5(120);
DQ =1;
delay5(16);
delay5(80);
}
uchar readbyte(void)
{
uchar i=0;
uchar date=0;
for (i=8;i>0;i--)
{
DQ =0;
delay5(1);
DQ =1;
date>>=1;
if(DQ)
date|=0x80;
delay5(11);
}
return(date); // 返回读取的数据
}
void writebyte(uchar dat)
{
uchar i=0;
for(i=8;i>0;i--)
{
DQ =0;
DQ =dat&0x01; // 写入数据
delay5(12);
DQ = 1;
dat>>=1;
delay5(5);
}
}
uchar retemp(void)
{
uchar a,b,tt;
uint t;
init_ds18b20(); // 初始化DS18B20
writebyte(0xCC);
writebyte(0x44);
init_ds18b20();
writebyte(0xCC);
writebyte(0xBE);
a=readbyte();
b=readbyte();
t=b; /
t<<=8;
t=t|a;
tt=t*0.0625;
return(tt); // 返回温度值
}