利用串口将采集到的温度数据实时发送至上位机,并在上位机软件上显示当前温度值(上位机软件的编写请参考接下来的VB内容)。
关于温度变化的实现,可以参考以下方法: 室温通常在28℃左右。 用手捏住温度传感器,使温度升高。 用低温物体接触温度传感器以降低温度,或将温度传感器放在温度传感器上。 在温度传感器上洒一些水,然后向温度传感器吹气,可以使温度快速下降。 你还可以想其他办法让温度传感器周围的温度在25°C到32°C之间变化。
1、温度传感器概述:
温度传感器是各种传感器中最常用的类型。 早期使用的是模拟温度传感器,例如热敏电阻。 随着环境温度的变化,其阻值也呈线性变化。 处理器用于收集电阻器两端的电压。 ,然后根据一定的公式就可以计算出当前的环境温度。 随着科学技术的进步,现代温度传感器已经数字化,外观小巧,接口简单。 它们广泛应用于生产实践的各个领域,为我们的生活提供了便利。 随着现代仪器仪表的发展,小型化、集成化、数字化正在成为传感器发展的重要方向。 美国DALLAS半导体公司推出的数字温度传感器DS18B20采用单总线协议,这意味着与微控制器的接口只需要一个I/O口,不需要任何外部元件。 它直接将环境温度转换为数字信号,并以数字代码的形式串行输出。 这极大地简化了传感器和微处理器之间的接口。
2、DS18B20温度传感器简介: DS18B20是美国DALLAS半导体公司推出的第一款支持“单线总线”接口的温度传感器。 它具有小型化、低功耗、高性能、抗干扰能力强、易于与微处理器配置等特点。 具有其他优点,温度可以直接转换成串行数字信号供处理器处理。
1、D818B20温度传感器特点:
① 适应电压范围宽,电压范围3.0~5.5V,可通过数据线以寄生电源方式供电。
② 独特的单线接口方式。 连接微处理器时,只需一根端口线即可实现微处理器与DS18B20之间的双向通信。
③ 支持多点组网功能。 只需3根线路即可并联多个DS18B20,实现网络中的多点测温。
④ 使用时无需外接元件。 所有传感元件和转换电路都集成在一个形状像三极管的集成电路中。
⑤ 温度测量范围-55℃~+I25℃,-10℃~+85℃精度为0.5℃。
⑥ 可编程分辨率为9~12位,对应可解析温度分别为0.5℃、0.25℃、0.125℃、0.0625℃,可实现高精度温度测量。
⑦ 9位分辨率下,最长可在93.75ms内将温度转换为数字; 在12位分辨率下,最多750ms内即可将温度转换为数字,显然速度更快。
⑧ 测量结果直接输出数字温度信号,并通过“单线总线”串行传输至CPU。 同时可传输CRC校验码,具有较强的抗干扰和纠错能力。
⑨ 负压特性。 当电源极性接反时,芯片不会因发热而烧毁,但无法正常工作。
2、适用范围:
① 冷冻库、粮仓、储罐、电信设备房、电力设备房、电缆线槽等温度测控领域。
②轴承、气缸、纺织机械、空调等狭小空间工业设备的温度测量与控制。
③汽车空调、冰箱、冰柜、中低温干燥箱等。
④ 供热制冷管道热量计量、中央空调分户热能计量等。
3、引脚介绍:
DS18B20有两种封装:三引脚T0-92插件型(最常用、最常见的封装)和八引脚SOIC贴片型。
4、硬件连接:
我们先来了解一下“单总线”的概念。 目前,微控制器与外设之间常用的数据传输串行总线主要有I2C、SPI和SCI总线。 其中,l2C总线采用同步串行两线方式通信(一根时钟线、一根数据线),SPI总线采用同步串行三线方式通信(一根时钟线、一根数据输入线、一根数据线)。 SCI总线以异步方式通信(一根数据输入线,一根数据输出线)。 这些总线需要至少两条或更多信号线。 DS18B20采用的单线总线技术与上述总线不同。 它采用单根信号线既传输时钟又传输数据,且数据传输是双向的,因此这种单总线技术具有线路简单、硬件开销小、成本低、易于总线扩展和维护等优点。 单总线适用于单主系统,可以控制一个或多个从设备。
主设备可以是微控制器,从设备可以是单总线设备,它们之间的数据交换仅通过一根信号线。 当只有一台从设备时,系统可以作为单节点系统运行; 当有多个从设备时,系统可以作为多节点系统运行。 设备(主设备或从设备)通过开漏或三态端口连接到该数据线,允许设备在不发送数据时释放总线并允许其他设备使用总线。 单总线通常需要外部5kΩ左右的上拉电阻。 芯片手册中的典型连接如下所示。
DS18B20与单片机的连接非常简单。 该微控制器只需要一个I/O端口即可控制DS18B20。 该图中的连接方式是单片机与一颗DS18B20通信。 如果要控制多个DS18B20进行温度采集,只需将所有DS18B20的所有I/O端口连接在一起即可。 具体操作时,通过读取DS18B20内部各芯片的序列号来识别。 在本章中,我们仅操作一个 DS18B20 来进行温度采集。 掌握本章知识后,您可以轻松扩展和设计多点温度采集系统。
5、工作原理:
硬件电路连接好后,单片机需要如何工作来读取DS18B20中的温度数据呢? 下面将进行详细分析。
首先我们看一下控制DS18B20的指令:
① 33H——读ROM。 读取DS18B20温度传感器ROM中的代码(即64位地址)。
② 55H——配套ROM。 发出该命令后,再发出64位ROM代码,访问单总线上该代码对应的DS18B20,并使其响应,为下一步读写DS18B20做准备。
③ FOH——搜索ROM。 用于确定连接到同一总线上的DS18B20的数量,识别64位ROM地址,并为操作每个设备做好准备。
④ CCH——跳过ROM。 忽略64位ROM地址,直接向18B20发送温度转换命令,适合作为从机工作。
⑤ ECH——报警搜索命令。 执行后,只有温度超过设定值上下限的芯片才会响应。 上述指令涉及的存储器为64位光刻ROM,下表列出了其定义。
64位光刻ROM中的序列号在出厂前已被光刻。 可以看作是DS18B20的地址序列码。 位的顺序为:前 8 位是产品型号,接下来的 48 位是 DS18B20 本身的序列号,最后 8 位是 CRC 循环冗余校验码的前 56 位(CRC= X8+X5+X4+ 1)。 光刻ROM的目的是使每个DS18B20都不同,以便可以将多个DS18B20连接到一条总线上。
下面介绍一下上述指令的用法。 当主机需要操作多台在线DS18B20中的一台时,首先应将主机与DS18B20逐一连接,并读出其序列号; 然后将所有的DS18B20连接到总线上,微控制器发出匹配的ROM命令(55H),紧接着主机提供的64位序列(包括DS18B20的48位序列号)的操作是针对DS18B20的。
如果主机只操作一颗DS18B20,则无需读取ROM代码并匹配ROM代码。 只要使用skip ROM(CCH)命令,就可以进行以下温度转换和读取操作。
① 44H—温度换算。 启动DS18B20进行温度转换,12位转换最长时间为750ms(9位转换为93.75ms)。 结果存储在内部 9 字节 RAM 中。
② BEH——读临时寄存器。 读取内部 RAM 中的 9 字节温度数据。
③ 4EH——写临时寄存器。 发出命令将温度上限和下限数据写入内部 RAM 的第 2 和第 3 字节。 紧接着该命令,传输两个字节的数据。
④ 48H——复制临时寄存器。 将 RAM 中字节 2 和 3 的内容复制到 E2PROM。
⑤88H—E2PROM 复位。 将E2PROM的内容恢复到RAM中的第3和第4字节。
⑥84H——读取电源模式。 读取DS18B20的供电模式。 寄生供电时,DS18B20发送0; 当由外部电源供电时,DS18B20发送1。
上述指令涉及的存储器为高速寄存器RAM和电可擦除E2PROM,见下表。
暂存器 RAM 由 9 字节存储器组成。 第0~1字节为温度显示位; 第2、3个字节复制TH、TL,可更新第2、3个字节中的数字; 第4个字节是配置寄存器,第4个字节中的数字可以更新; 第 5、6、7 字节被保留。 电可擦除E2PROM还包括温度触发器TH和TL以及配置寄存器。 大家了解这些就足够了。
下表列出了暂存器 RAM 字节 0 和 1 中温度数据的存储格式。
DS18B20出厂时默认配置为12位,其中最高位为符号位,即温度值共有11位。 单片机读取数据时,一次会读取2个字节,总共16位。 读取后,将二进制的低11位数字转换为十进制数后,再乘以0.0625,即得到实际测量的温度值。 另外,还需要判断温度是正值还是负值。 前 5 个数字是符号位。 这5位同时改变。 我们只需要判断11位即可。 当前五位为1时,读取的温度为负值,需要将测量值取反,加1,然后乘以0.0625,得到实际温度值。 当前五位为0时,读取的温度为正值,当温度为正值时,只需将测量值乘以0.0625即可得到实际温度值。
6、工作时序图:
下图展示了时序图中各总线的状态。
(1)初始化(见下面时序图)
① 首先将数据线设置为高电平1。
②延迟(时间要求不是很严格,但应尽可能短)。
③ 将数据线拉至低电平0。
④ 延时750μs(时间范围可以是480~960μs)。
⑤ 将数据线拉至高电平1。
⑥ 拖延等待。 如果初始化成功,在15~60ms内会产生DS18B20返回的低电平0,根据该状态可以判断其存在。 但需要注意的是,不能无限等待,否则程序会进入死循环,所以必须进行超时判断。
⑦ 如果CPU读取数据线上的低电平0,仍然需要延时。 从发出高电平开始(从步骤@开始),延迟时间至少为480μs。
哈喽)再次将数据线拉至高电平1结束。
(2)DS18B20写入数据(见下面时序图)
①先将数据线设置为低电平0。
②确定的延迟时间为15μs。
③ 按照从低位到高位的顺序发送数据(一次只发送一位)。
④ 延迟时间为45μs。
⑤ 将数据线拉至高电平1。
⑥ 重复步骤①~⑤,直至发送完所有字节。
⑦最后将数据线拉高至1。
(3)DS18B20读取数据(见下面时序图)
① 将数据线拉高至1。
② 延迟2μs。
③ 将数据线拉至0。
④ 延迟6μs。
⑤ 将数据线拉高至1。
⑥ 延迟4μs。
⑦ 读取数据线的状态,得到状态位,并进行数据处理。
⑧ 延迟30μs。
⑨ 重复步骤①~⑦,直至读完一个字节。
#include //编译器自带的库用 编译器包含C52的定义
#include "DS18B20_Sum.h"
#include "delay_Sum.h"
#define uchar unsigned char
#define uint unsigned int
sbit DS18B20=P2^2; //温度传感器信号线
uint temp;
float f_temp;
long int temperature=0;
DS18B20初始化
/*
① 先将数据线置高电平 1。
② 延时(该时间要求不是很严格,但是要尽可能短一点)。
③ 数据线拉到低电平 0。
④ 延时750μs(该时间范围可以在480~960μs) 。
⑤ 数据线拉到高电平 l 。
⑥ 延时等待。如果初始化成功则在15~60ms内产生一个由DS18B20返回的低电平0, 据该状态可以确定它的存在。
但是应注意,不能无限地等待,不然会使程序进入死循环,所以要进行超时判断。
⑦ 若 CPU 读到数据线上的低电平 0 后,还要进行延时, 其延时的时间从发出高电平算起(第⑤步的时间算起)最少要 480μs。
⑧ 将数据线再次拉到高电平 l 后结束。
*/
uchar reset_ds18b20()
{
uchar presence;
DS18B20=0;
delay_ds18b20(29); //延时480 - 960 us
DS18B20=1;
delay_ds18b20(3); //延时 15 - 60 us
presence=DS18B20;
delay_ds18b20(25); //延时 60 - 240 us
return(presence);
}
DS18B20读取一字节数据
/*
① 将数据线拉高到 1。
② 延时2μs。
③ 将数据线拉低到 0。
④ 延时6μs。
⑤ 将数据线拉高到 1。
⑥ 延时4μs。
⑦ 读数据线的状态得到一个状态位,并进行数据处理。
⑧ 延时30μs。
⑨ 重复①~⑦步骤,直到读取完一个字节。
*/
uchar read_bit_ds18b20()
{
uchar i;
DS18B20=1;
delay_ds18b20(1);
DS18B20=0;
//delay(1); //延时 15us 也可以不延时
DS18B20=1;
//delay(3); //延时 1 - 45 us
for(i=0;i<3;i++);
return(DS18B20);
}
DS18B20写一字节数据
/*
① 数据线先置低电平 0。
② 延时确定的时间为 15μs。
③ 按从低位到高位的顺序发送数据(一次只发送一位)。
④ 延时时间为 45μs。
⑤ 将数据线拉到高电平 l 。
⑥ 重复①~⑤步骤,直到发送完整个字节。
⑦ 最后将数据线拉高到 1。
*/
void write_bit_ds18b20(uchar dat)
{
DS18B20=0; //置0 无需延时
if(dat==1)
DS18B20=1;
delay_ds18b20(1); //延时 60 - 120 us
DS18B20=1;
delay_ds18b20(1); //延时 1 - ∞ us
}
DS18B20写数据
void write_byte_ds18b20(uchar dat)
{
uchar i,j;
for(i=0;i>i)&0x01);
write_bit_ds18b20(j);
//delay(1); //延时 1 - ∞ us
}
}
DS18B20读数据
uchar read_byte_ds18b20()
{
uchar dat=0;
uchar i;
for(i=0;i<8;i++)
{
if(read_bit_ds18b20())
dat|=0x01<<i;
//delay(1); //延时 1 - ∞ us
}
return(dat);
}
int read_temp_ds18b20()
{
uchar templ=0,temph=0;
int temp=0;
reset_ds18b20();//复位
write_byte_ds18b20(0xcc); //跳过ROM
write_byte_ds18b20(0x44); //跳过温度采集
delay_ds18b20(10); //750ms
reset_ds18b20();
write_byte_ds18b20(0xcc); //跳过ROM
write_byte_ds18b20(0xbe); //准备好数据(开始温度转换采集)
templ=read_byte_ds18b20();//读低字节温度值
temph=read_byte_ds18b20();//读低字节温度值
temp=(templ+(temph*256));
return(temp);
}
float read_temp_ten_ds18b20()
{
float tt;
uchar templ=0,temph=0;
int temp=0;
reset_ds18b20();//复位
write_byte_ds18b20(0xcc); //跳过ROM
write_byte_ds18b20(0x44); //跳过温度采集
delay_ds18b20(10); //750ms
reset_ds18b20();
write_byte_ds18b20(0xcc); //跳过ROM
write_byte_ds18b20(0xbe); //准备好数据(开始温度转换采集)
templ=read_byte_ds18b20();//读低字节温度值
temph=read_byte_ds18b20();//读低字节温度值
temp=temph;
temp<0) //判断温度数据 是否是负温度
;//Disp_1602(7,1,"-",1); //在1602上显示一个 ” - “ 负温度标志
else ;//Disp_1602(7,1,"+",1); //否则在1602上显示一个 ” + “ 负温度标志
temperature=read_temp_ds18b20(); //读ds18b20 温度值,赋给 temperature
delay(1);
//write_oneline_DS18b20_1602(8,(temperature&0x07ff)*0.625); //把读出的温度 转换成实际温度 ,并显示在1602上
return((temperature&0x07ff)*0.625); //十六进制
//十进制 temperature=temperature*(0.0625*10);
}
#include //编译器自带的库用 编译器包含C52的定义
#include
#include "DS18B20_Sum.h"
#include "delay_Sum.h"
#include "printf_sum.h"
#define uchar unsigned char
#define uint unsigned int
float temperature2=0;
void InitUART(uint choose)//使用定时器1作为串口波特率发生器
{
TH1 = 0xFD; //晶振11.0592mhz 波特率设为9600
TL1 = TH1;
TMOD |= 0x20; //定时器1方式2
SCON = 0x50; //串口接收使能
ES = 1; //串口中断使能
TR1 = 1; //定时器1使能
TI = 1; //发送中断标记位,必须设置
EA = choose; //开总中断
}
void main()
{
InitUART(0);
while(1)
{
temperature2= read_temp_ten_ds18b20();
printf("%.1f",temperature2/10);
delay(200);
}
}