前言

DS18B20是单片机课设或者仿真项目中一个比较常用的数字温度传感器,因此使用DS18B20仿真一个简易的温控器,超过温度就打开风扇,低于某温度就用继电器打开加热丝。整个程序我都会附在最后,如果懒得复制粘贴,要所有的工程以及仿真的话,就给我点赞赏吧。

整个仿真如图:

首先便是查找DS18B20的手册,编写DS18B20的驱动程序。阅读手册可知:

DS18B20的数据类型

DS18B20提供9位与12位摄氏温度测量进度,上电默认是12位,如果我们就用默认的12位精度的话,那么最后从DS18B20读出来的数据要乘以0.0625,之后得到的就是实际温度,单位摄氏度。测量范围为 -55℃至125℃。

DS18B20的通信方式

DS18B20是单总线接口,也就是说,只需要一个通信接口与单片机进行通信,DS18B20看起来就比较像三极管,但它是两根电源线+一根通信线,每个DS18B20都有一个独一无二的64位序列号,也就是说,在一个总线上可以连接多个DS18B20设备,控制不同的DS18B20来读取多点温度。

DS18B20的外围电路

DS18B20的电路部分也很简单,不需要外围元件,使用3V-5.5V供电。

DS20B20的控制流程

DS18B20上电默认是12位精度,主设备必须向DS18B20发送温度转换命令[44H]才能开始温度转换。当然DS18B20进行温度转换需要时间,当发送完[44H]读命令之后,主设备就可以执行读数据时序了,等待DS18B20转换完成,在DS18B20转换完成之前,都会返回0,转换完成之后,就会返回1。

DS18B20的温度数据是以一个16位二进制补码数的形式存储在温度寄存器中。我们现在就确定使用12位精度的形式,那么首位就为符号位,之后是数据位,如图:

此外要注意这个上电复位时默认是85℃,有些人看到上电85度还以为是错的,因此疯狂修改程序,其实是正常现象,自己程序注意一下即可。

了解了这些,我们就开始着手写DS18B20的驱动程序。
手册上对于事件流程的说明如图:

注意最后一句话:当执行完这些ROM命令之后,主设备必须回到上述步骤中的第一步。也就是说,我们首先需要进行初始化,然后发送ROM命令,然后发送功能命令。之后便是等待ROM命令执行完,如果要发送下一个ROM命令,则又需要重新回到第一步初始化,再发送下一个ROM命令,再发送功能命令。这一点需要记住。

那么我们的整个读取流程就基本确定了:
初始化->跳过读序列号(ROM命令)->启动温度转化(功能命令)->延时等待ROM命令与温度转换执行结束->初始化->跳过读序列号(ROM命令)->读取温度(功能命令)

因为我们就使用一个DS18B20,因此可以跳过这个读序列号。下面我们就按照这个流程来编写各部分程序。

初始化

由时序图可知,初始化程序首先需要将总线拉为低电平至少480us的时间,然后释放总线,总线置为高电平,DS18B20就会检测这个上升沿,检测到上升沿之后,等待15-60us,将总线再拉低至少480us,也就是说,高电平的时间也要持续15-60us。

初始化程序如下:

/@@****************************************************************************
函数功能:延时子程序
****************************************************************************/
void delay(uint k)
{while(k--);
}
/@@****************************************************************************
函数功能:DS18B20初始化子程序
****************************************************************************/
void ds18b20_init(void)
{DQ=1; //DQ先置高delay(16); //延时DQ = 0; //发送复位脉冲delay(80); //延时(>480us)DQ = 1; //拉高数据线delay(16); //等待(15~60us)delay(60);DQ = 1;
}

写数据

写数据分为写0和写1,在DS18B20中分为写0时段和写1时段,每个写时段最小必须由60us的时序时间并且要有1us的恢复时间。

在写1时段,在总线拉低之后,主设备必须在15us之内释放总线,总线释放后,上拉电阻将总线拉高;在写0时段,在总线拉低后,整个时段必须一致拉低总线,至少60us。

简单来说,就是这样:在主设备初始化写时段后,DS18B20会在15-60us内对总线进行采样,如果采样时候是高电平,则DS18B20会写入1,反之则写入0。

程序如下:

/****************************************************************************函数功能:向DS18B20写一字节数据入口参数:dat出口参数:****************************************************************************/
void WriteOneChar(uchar dat)
{uchar i=0;DQ=1;delay(1);for(i=8;i>0;i--){DQ=0;DQ=dat&0x01;delay(5);DQ=1;dat>>=1;}
}

读数据

主设备在执行完读暂存寄存器[BEh]之后,需要即使生成读时段,才可以读取数据。每个读时段最小必须有60us的持续时间与1us的恢复时间。从DS18B20中发送出来的数据在读时序后仅有15us的有效时间,因此,主设备在开始读时段后的15us之内必须释放总线来读取数据。时序如上图所示。

程序如下:

/****************************************************************************函数功能:向DS18B20读一字节数据入口参数:出口参数:dat****************************************************************************/uchar ReadOneChar(void){uchar i=0;uchar dat=0;DQ=1;delay(1);for (i=8;i>0;i--){DQ=0;dat>>=1;DQ=1;delay(1);if(DQ)dat|=0x80;delay(30);DQ=1;}return dat;
}

然后就是根据手册查找一些重要的命令,包括跳过读序列号,读取温度命令等等,这一部分就不再赘述。然后我们就可以按照我们之前总结的读取温度的流程来编写整个读取温度的程序:

/****************************************************************************函数功能:向DS18B20读温度值
入口参数:
出口参数:temperature温度读取流程: 初始化->跳过读序列号->启动温度转化->延时->初始化->跳过读序列号->读取温度并显示****************************************************************************/
float ReadTemperature(void)
{float  temperature = 0.0;uint  temflag = 0;uint  tt = 0;uchar tempL=0; //临时变量低位uchar tempH=0; //临时变量高位ds18b20_init(); //初始化WriteOneChar(0xcc); //跳过读序列号的操作WriteOneChar(0x44); //启动温度转换delay(125); //转换需要一点时间,延时ds18b20_init(); //初始化WriteOneChar(0xcc); //跳过读序列号的操作WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)tempL=ReadOneChar(); //读出温度的低位LSBtempH=ReadOneChar(); //读出温度的高位MSB//温度转换,把高低位做相应的运算转化为实际温度tt = tempH<<8;tt = tt|tempL;if(tt&0xf800) //判断是否是负温度{ //是负温度tt = ~tt + 1; temflag = 0;}else{tt = tt; temflag = 1;}temperature = (float)tt;temperature = temperature * 0.0625;
//  delay(200);/*负温度*/if(temflag == 0){temperature = -temperature;}/*正温度*/else{temperature = temperature;}return temperature;  //返回温度值
}

然后就是用1602来显示出来,看一下我们的程序对不对,关于1602的驱动程序,在我之前的文章中有说明,这里就不再说明。

测试主程序如下:

/@@*显示函数*/
void display(void)
{char *string1 = "TEM : ";char *string2 = " C   ";char *string3 = "High:";char *string4 = "Low:";    char Display1[16];  //第一行显示数组char Display2[16];  //第二行显示数组//显示温度sprintf((char*)Display1,"%s%d%s",string1,temp,string2);                           print_string(Display1,1);    //显示过温低温点sprintf((char*)Display2,"%s%d   %s%d",string3,tempOver,string4,tempLow);    print_string(Display2,2);
}
void main()
{lcd_init();SW = 0;Motor = 0;while(1){temp = (int)ReadTemperature();   //读取温度display();  //显示}
}

测试结果:

这里的显示程序中我加了阈值显示,这里设置的是高温阈值为30,低温阈值为27。因为为了后续方便,所以我就把阈值设置得比较近,这个可以自行修改。

之后就是比较简单的逻辑了,超过高温阈值就关闭加热丝打开风扇,低于低温阈值就关闭风扇,打开加热丝。主程序如下:

void main()
{lcd_init();SW = 0;Motor = 0;while(1){temp = (int)ReadTemperature();   //读取温度display();  //显示/*过温  打开风扇,关闭加热丝*/if(temp > tempOver){SW = 0;   Motor = 1;}/*低温  关闭风扇,打开加热丝*/else if(temp < tempLow){SW = 1;Motor = 0;}}
}

关于风扇的电路,我这里就直接用了一个ULN2003,这个是小电流电机的,如果要更换24V大电流电机驱动,或者要加上PWM调速,我后续会更新这方面的文章。

效果如下:

如果要全部的工程,仿真就点赞私聊我喔。

1602程序在之前的文章中有发,因此1602程序就不发了。我的工程目录如下:

所有源代码如下:

main.c

#include <reg52.h>
#include <stdio.h>
#include "1602.h"
#include "ds18b20.h"
#define uchar unsigned char
#define uint unsigned intsbit SW = P1^0;    //继电器控制加热丝
sbit Motor = P1^1; //电机接口int temp = 0;   //存储温度
int tempOver = 30;   //过温温度
int tempLow  = 27;   //低温温度
sbit key1 = P3^0;  //增加过温温度
sbit key2 = P3^1;  //减小过温温度
sbit key3 = P3^0;  //增加低温温度
sbit key4 = P3^1;  //减小低温温度uint key_result = 0;  //保存按键结果void key_delay(uchar t)
{ int j;  for(;t!=0; t--)  for (j=0;j<255;j++);  }/*按键检测  如果按键1被按下就返回1
如果按键2被按下就返回2  如果没有按键按下就返回0*/
uint key_scan(void)
{uint result = 0;/*先将按键电平拉高*/key1 = 1;key2 = 1;/*检测按键1是否被按下*/if(key1 == 0){key_delay(5);if(key1 == 0){result = 1;}}/*检测按键2是否被按下*/if(key2 == 0){key_delay(5);if(key2 == 0){result = 2;}}    return result;
}/*显示函数*/
void display(void)
{char *string1 = "TEM : ";char *string2 = " C   ";char *string3 = "High:";char *string4 = "Low:";   char Display1[16];  //第一行显示数组char Display2[16];  //第二行显示数组//显示温度sprintf((char*)Display1,"%s%d%s",string1,temp,string2);                          print_string(Display1,1);    //显示过温低温点sprintf((char*)Display2,"%s%d   %s%d",string3,tempOver,string4,tempLow); print_string(Display2,2);
}void main()
{lcd_init();SW = 0;Motor = 0;while(1){temp = (int)ReadTemperature();   //读取温度display();  //显示/*过温  打开风扇,关闭加热丝*/if(temp > tempOver){SW = 0;   Motor = 1;}/*低温  关闭风扇,打开加热丝*/else if(temp < tempLow){SW = 1;Motor = 0;}}
}

DS18B20源文件:

#include <reg52.h>
#include <stdio.h>
#include "ds18b20.h"/***************************温度传感器信号引脚******************************************/
sbit DQ=P1^5; //数据传输线接单片机的相应的引脚/****************************************************************************函数功能:延时子程序****************************************************************************/
void delay(uint k)
{while(k--);
}/****************************************************************************函数功能:DS18B20初始化子程序****************************************************************************/
void ds18b20_init(void)
{DQ=1; //DQ先置高delay(16); //延时DQ = 0; //发送复位脉冲delay(80); //延时(>480us)DQ = 1; //拉高数据线delay(16); //等待(15~60us)delay(60);DQ = 1;
}/****************************************************************************函数功能:向DS18B20读一字节数据入口参数:出口参数:dat****************************************************************************/uchar ReadOneChar(void){uchar i=0;uchar dat=0;DQ=1;delay(1);for (i=8;i>0;i--){DQ=0;dat>>=1;DQ=1;delay(1);if(DQ)dat|=0x80;delay(30);DQ=1;}return dat;
}/****************************************************************************函数功能:向DS18B20写一字节数据入口参数:dat出口参数:****************************************************************************/
void WriteOneChar(uchar dat)
{uchar i=0;DQ=1;delay(1);for(i=8;i>0;i--){DQ=0;DQ=dat&0x01;delay(5);DQ=1;dat>>=1;}
}/****************************************************************************函数功能:向DS18B20读温度值
入口参数:
出口参数:temperature温度读取流程: 初始化->跳过读序列号->启动温度转化->延时->初始化->跳过读序列号->读取温度并显示****************************************************************************/
float ReadTemperature(void)
{float  temperature = 0.0;uint  temflag = 0;uint  tt = 0;uchar tempL=0; //临时变量低位uchar tempH=0; //临时变量高位ds18b20_init(); //初始化WriteOneChar(0xcc); //跳过读序列号的操作WriteOneChar(0x44); //启动温度转换delay(125); //转换需要一点时间,延时ds18b20_init(); //初始化WriteOneChar(0xcc); //跳过读序列号的操作WriteOneChar(0xbe); //读温度寄存器(头两个值分别为温度的低位和高位)tempL=ReadOneChar(); //读出温度的低位LSBtempH=ReadOneChar(); //读出温度的高位MSB//温度转换,把高低位做相应的运算转化为实际温度tt = tempH<<8;tt = tt|tempL;if(tt&0xf800) //判断是否是负温度{ //是负温度tt = ~tt + 1; temflag = 0;}else{tt = tt; temflag = 1;}temperature = (float)tt;temperature = temperature * 0.0625;
//  delay(200);/*负温度*/if(temflag == 0){temperature = -temperature;}/*正温度*/else{temperature = temperature;}return temperature;  //返回温度值
}

ds18b20温度转换指令_【Proteus】DS18B20简易温控器相关推荐

  1. ds18b20温度转换指令_学习心得 | 温度检测工程模块划分总结与案例分析

    本文为明德扬原创文章,转载请注明出处! 很多朋友在学习FPGA的时候会发现模块划分很令人头大,今天我就通过明德扬温度检测工程来与大家分享一下本人的划分思路. 明德扬温度检测工程是基于FPGA的一个实用 ...

  2. ds18b20温度转换指令_DS18B20温度传感器(附代码并浅谈与或运算)

    DS18B20使用的是一种比较特殊的传输协议,仅需一个接线口就能实现通信 前言 DS18B20独特的单线接口仅需一个端口引脚进行通讯,这让每一个学习到这里的人都感到很神奇.在这篇文章中我们将通过学习1 ...

  3. ds18b20温度转换指令_51单片机驱动DS18B20温度传感器程序及心得

    关于DS18B20温度传感器,在没有硬件设备的辅助下,写内部程序有些困难,因为看不到实际信号波形.对于单片机,我...渐渐的有些心灰意冷..虽然掌握了1_WIRE总线,却少了很多喜悦,下雨了...它是 ...

  4. ds18b20温度转换指令_STM32接口DS18S20温度传感器

    关联知识 STM32 介绍 在本文中,我们将学习DS18B20温度传感器与STM32微控制器的接口. DS18B20不支持Arduino Dallas库和OneWire库. 这就是我们必须不使用库而编 ...

  5. ds18b20温度转换指令_ds18b20如何读取温度?温度数据怎么换算? - 全文

    DS18B20是温度传感器,读写数据有一定的时序: 1.写操作 (1) 数据线先置低电平"0". (2) 延时确定的时间为15微秒. (3) 按从低位到高位的顺序发送字节(一次只发 ...

  6. ds18b20温度转换指令_DS18B20温度传感器使用方法以及代码

    第 7 章 DS18B20 温度传感器 7.1 温度传感器概述 温度传感器是各种传感器中最常用的一种, 早起使用的是模拟温 度传感器, 如热敏电阻, 随着环境温度的变化, 它的阻值也发生线性 变化, ...

  7. ds18b20温度转换指令_ds18b20温度数据怎么换算? - ds18b20如何读取温度?温度数据怎么换算?...

    ds18b20温度数据怎么换算? 高五位S为符号位,分辨率为0.0625.正温度把16进制数转成10进制即可:负温度把16进制数取反后加1再转成10进制数,第一个是00FA是(15*16+10)*0. ...

  8. ds18b20温度转换指令_DS18B20传感器温度转换指令( )。

    解析: [解析题]甲骨文是哪一历史时期的代表性文字 [解析题]下列分子中含有不同长度共价键的是 [解析题]肝性脑病的诱因包括 [解析题]教学语言包括 [解析题]地球会因大气升温而灭亡. [解析题]中国 ...

  9. DS18B20温度转换与显示

    单片机练习 - DS18B20温度转换与显示 最近都在学习和写单片机的程序, 今天有空又模仿DS18B20温度测量显示实验写了一个与DS18B20基于单总线通信的程序. DS18B20 数字温度传感器 ...

最新文章

  1. 数据结构—顺序表的插入算法
  2. linux下挂载windows目录
  3. 苹果外包爆料:你手机里的Siri,听到了嘿嘿嘿的声音
  4. bootstraptable获得所有行_“安全超新星”集结出道,共创交通美好未来 2020广汽本田安全中国行首届道路安全创新大赛成功举办...
  5. 光纤收发器常见六大故障,三分钟全部搞定
  6. 15款提高表格操作的jQuery插件
  7. BGP——路由汇总造成次优选路问题
  8. linux运算_linux中的计算【转】
  9. java 正则表达式 分组(group)
  10. Android Camera架构浅析
  11. 20191230每日一句
  12. 1-7 Graph 可视化
  13. 台式计算机cpu多高,台式机硬件正常温度是多少
  14. 地学计算方法/地统计学(第二章地理数据及其采集与预处理)
  15. 三角函数π/2转化_三角函数不会做?看这里,带你搞定
  16. 打开计算机左侧的桌面不见了,Win7资源管理器左侧桌面快捷方式不见了怎么办?...
  17. 浅谈,如何获取MTK CPU信息 请看我是如何做的。一步步来吧
  18. android中按两次返回键返回桌面或退出程序
  19. Maven学习笔记__上篇
  20. 大数问题:大数加法 与 大数乘法 最简单大数乘法

热门文章

  1. 成为 Linux 终端高手的七种武器
  2. rop的noejs客户端
  3. Broadcom NetXtreme II BCM5706/5708/5709/5716 Driver 驱动问题处理办法
  4. SQL批量更新DateTime中的年、月、日
  5. weblogic9修改线程数设置
  6. 软件更新点的配置—SUP
  7. 解决WebBrowser控件会导致应用程序占用内存居高不下问题
  8. Go 导入当前项目下的包
  9. WebClient 通过get和post请求api
  10. JavaWeb学习总结(五十)——文件上传和下载