历史上的今天
返回首页

历史上的今天

今天是:2024年12月24日(星期二)

正在发生

2021年12月24日 | 51单片机系列——单总线通信方式——DS18B20温度检测的设计

2021-12-24 来源:eefocus

这个电路仿真的原理是因为:根据普中科技上的编程(一模一样),但用proteus7.8仿真的时候却仿真不出来,经过小编的一段时间的思考解决了用软件仿真DS18B20温度检测的电路。我先讲仿真电路图与源码分享给大家。


仿真电路图:
图1

temp.h //温度检测模块头文件


#ifndef __TEMP_H_

#define __TEMP_H_


#include

//---重定义关键词---//

#ifndef uchar

#define uchar unsigned char

#endif


#ifndef uint 

#define uint unsigned int

#endif


//--定义使用的IO口--//

sbit DSPORT=P3^7;


//--声明全局函数--//

void Delay1ms(uint );

uchar Ds18b20Init();

void Ds18b20WriteByte(uchar com);

uchar Ds18b20ReadByte();

void  Ds18b20ChangTemp();

void  Ds18b20ReadTempCom();

int Ds18b20ReadTemp();


#endif


temp.c //温度检测模块的驱动函数库文件


#include"temp.h"

#include


/*******************************************************************************

* 函 数 名         : Delay1ms

* 函数功能     : 延时函数

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void Delay1ms(uint y)  

{

 uint x;

 for( ; y>0; y--)

 {

  for(x=110; x>0; x--);

 }

}

/*延时500us函数*/

void delay500us(void)   //误差 0us

{

    unsigned char a,b;

    for(b=71;b>0;b--)

        for(a=2;a>0;a--);

}

/*延时80us函数*/

void delay80us(void)   //误差 0us

{

    unsigned char a,b;

    for(b=11;b>0;b--)

        for(a=2;a>0;a--);

}

/*延时48us函数*/

void delay48us(void)   //误差 0us

{

    unsigned char a,b;

    for(b=9;b>0;b--)

        for(a=1;a>0;a--);

}

/*延时6us函数*/

void delay6us(void)   //误差 0us

{

    unsigned char a;

    for(a=1;a>0;a--);

    _nop_();  //if Keil,require use intrins.h

}



/*******************************************************************************

* 函 数 名         : Ds18b20Init

* 函数功能     : 初始化

* 输    入         : 无

* 输    出         : 初始化成功返回1,失败返回0

*******************************************************************************/

uchar Ds18b20Init()

{

 uchar i;

 DSPORT = 0;    //将总线拉低480us~960us

    delay500us();

 DSPORT = 1;   //然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低

 i = 0;

 while(DSPORT) //等待DS18B20拉低总线

 {

  delay80us();

  i++;

  if(i>5)//等待>5MS

  {

   return 0;//初始化失败

  }

 

 }

 return 1;//初始化成功

}


/*******************************************************************************

* 函 数 名         : Ds18b20WriteByte

* 函数功能     : 向18B20写入一个字节

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void Ds18b20WriteByte(uchar dat)

{

 uint i, j;

 for(j=0; j<8; j++)

 {

  DSPORT = 0;         //每写入一位数据之前先把总线拉低1us

  i++;

  DSPORT = dat & 0x01;  //然后写入一个数据,从最低位开始

  delay80us();

  DSPORT = 1; //然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值

  dat >>= 1;

 }

}


/*******************************************************************************

* 函 数 名         : Ds18b20ReadByte

* 函数功能     : 读取一个字节

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

uchar Ds18b20ReadByte()

{

 uchar byte, bi;

 uint i, j; 

 for(j=8; j>0; j--)

 {

  DSPORT = 0;//先将总线拉低1us

  i++;

  DSPORT = 1;//然后释放总线

     delay6us();   //误差 0us

  bi = DSPORT;  //读取数据,从最低位开始读取

  /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。*/

  byte = (byte >> 1) | (bi << 7);        

  delay48us();   //误差 0us

  DSPORT = 1;

 }    

 return byte;

}


/*******************************************************************************

* 函 数 名         : Ds18b20ChangTemp

* 函数功能     : 让18b20开始转换温度

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void  Ds18b20ChangTemp()

{

 Ds18b20Init();

 Delay1ms(1);

 Ds18b20WriteByte(0xcc);  //跳过ROM操作命令   

 Ds18b20WriteByte(0x44);     //温度转换命令

 //Delay1ms(100); //等待转换成功,而如果你是一直刷着的话,就不用这个延时了  

}


/*******************************************************************************

* 函 数 名         : Ds18b20ReadTempCom

* 函数功能     : 发送读取温度命令

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

void  Ds18b20ReadTempCom()

 Ds18b20Init();

 Delay1ms(1);

 Ds18b20WriteByte(0xcc);  //跳过ROM操作命令

 Ds18b20WriteByte(0xbe);  //发送读取温度命令

}


/*******************************************************************************

* 函 数 名         : Ds18b20ReadTemp

* 函数功能     : 读取温度

* 输    入         : 无

* 输    出         : 无

*******************************************************************************/

int Ds18b20ReadTemp()

{

 int temp = 0;

 uchar tmh, tml;

 Ds18b20ChangTemp();     //先写入转换命令

 Ds18b20ReadTempCom();   //然后等待转换完后发送读取温度命令

 tml = Ds18b20ReadByte();  //读取温度值共16位,先读低字节

 tmh = Ds18b20ReadByte();  //再读高字节

 temp = tmh;

 temp <<= 8;

 temp |= tml;

 return temp;

}


main.c //主函数


/**************************************************************************************

*                DS18B20温度传感器实验              *

实现现象:下载程序后,在温度传感器接口处,按照丝印方向插好温度传感器,数码管就会显示

   检测的温度值,

注意事项:                      

***************************************************************************************/


#include "reg52.h"    //此文件中定义了单片机的一些特殊功能寄存器

#include"temp.h" 


typedef unsigned int u16;   //对数据类型进行声明定义

typedef unsigned char u8;


sbit LSA=P2^2;

sbit LSB=P2^3;

sbit LSC=P2^4;


char num=0;

u8 DisplayData[8];

u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};


/*******************************************************************************

* 函 数 名         : delay

* 函数功能     : 延时函数,i=1时,大约延时10us

*******************************************************************************/

void delay(u16 i)

{

 while(i--); 

}


/*******************************************************************************

* 函 数 名         : datapros()

* 函数功能     : 温度读取处理转换函数

* 输    入         : temp

* 输    出         : 无

*******************************************************************************/

void datapros(int temp)   

{

    float tp;  

 if(temp< 0)    //当温度值为负数

   {

  DisplayData[0] = 0x40;    //   -

  //因为读取的温度是实际温度的补码,所以减1,再取反求出原码

  temp=temp-1;

  temp=~temp;

  tp=temp;

  temp=tp*0.0625*100+0.5; 

  //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点

  //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就

  //算加上0.5,还是在小数点后面。

 

   }

  else

   {   

  DisplayData[0] = 0x00;

  tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量

  //如果温度是正的那么,那么正数的原码就是补码它本身

  temp=tp*0.0625*100+0.5; 

  //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点

  //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就

  //算加上0.5,还是在小数点后面。

 }                

 DisplayData[1] = smgduan[temp / 10000];

 DisplayData[2] = smgduan[temp % 10000 / 1000];

 DisplayData[3] = smgduan[temp % 1000 / 100] | 0x80;

 DisplayData[4] = smgduan[temp % 100 / 10];

 DisplayData[5] = smgduan[temp % 10];

}


/*******************************************************************************

* 函数名         :DigDisplay()

* 函数功能   :数码管显示函数

* 输入           : 无

* 输出           : 无

*******************************************************************************/

void DigDisplay()

{

 u8 i;

 for(i=0;i<6;i++)

 {

  switch(i)  //位选,选择点亮的数码管,

  {

   case(0):

    LSA=0;LSB=0;LSC=0; break;//显示第0位

   case(1):

    LSA=1;LSB=0;LSC=0; break;//显示第1位

   case(2):

    LSA=0;LSB=1;LSC=0; break;//显示第2位

   case(3):

    LSA=1;LSB=1;LSC=0; break;//显示第3位

   case(4):

    LSA=0;LSB=0;LSC=1; break;//显示第4位

   case(5):

    LSA=1;LSB=0;LSC=1; break;//显示第5位 

  }

  P0=DisplayData[5-i];//发送数据

  delay(100); //间隔一段时间扫描 

  P0=0x00;//消隐

 }  

}


/*******************************************************************************

* 函 数 名       : main

* 函数功能   : 主函数

* 输    入       : 无

* 输    出      : 无

*******************************************************************************/

void main()

 while(1)

 {

  datapros(Ds18b20ReadTemp());  //数据处理函数

  DigDisplay();//数码管显示函数  

 }  

}


仿真后的结果:下图分别是显示正数/负数温度:

图2
图3

为什么用普中科技的程序在仿真软件上显示的结果就不理想呢?
小编经过反复的软件仿真验证发现:软件仿真时对时序的要求极高,例如在编程DS18B20的读写函数和初始化函数时,它们的时序应满足下图:
图4
图5
图6

从三张图中看出需要延时函数的处理。


**结论:**普中科技在编写读写和初始化函数时,延时大都通过while(i){i–;}或几个i++,来完成延时的,如果你尝试使用一下Debug调试一下,会发现这种延时并不准确,相差还很大。在硬件实战时这种不准确的延时也许影响不大(有时候可能还需要这样的做)。

推荐阅读

史海拾趣

Chemi-Con公司的发展小趣事

随着电子行业的快速发展,Chemi-Con公司不断加大对研发的投入,致力于技术创新和产品升级。公司研发团队在铝电解电容器的基础上,不断推出性能更优、体积更小、寿命更长的产品,满足了市场对于高效、可靠电容器的迫切需求。此外,Chemi-Con还积极拓展产品线,涉足了多层陶瓷电容器、薄膜电容器等多个领域,为客户提供更加丰富的选择。

Applied Engineering Products (AEP)公司的发展小趣事

在环保意识日益增强的今天,AEP公司积极响应国家号召,致力于绿色环保和可持续发展。公司投入大量资金研发环保型电子元器件,减少生产过程中的废弃物排放。同时,公司还建立了完善的废旧产品回收机制,对废旧产品进行环保处理,实现资源的循环利用。这一举措不仅提升了AEP公司的社会形象,也为公司的可持续发展注入了新的动力。

Frequency Management International公司的发展小趣事

随着业务的不断发展,FMI开始积极拓展国内外市场。公司凭借高品质的产品和专业的服务,赢得了众多客户的信赖和支持。同时,FMI还积极实施国际化战略,通过参加国际展会、建立海外销售网络等方式,不断提升品牌国际影响力。目前,FMI的产品已经广泛应用于计算机外设、工业仪器、局域网/广域网、光网络、过程控制、电信和无线产品等多个领域,并远销全球多个国家和地区。

Allied Controls Incorporated公司的发展小趣事

随着业务的不断发展,FMI开始积极拓展国内外市场。公司凭借高品质的产品和专业的服务,赢得了众多客户的信赖和支持。同时,FMI还积极实施国际化战略,通过参加国际展会、建立海外销售网络等方式,不断提升品牌国际影响力。目前,FMI的产品已经广泛应用于计算机外设、工业仪器、局域网/广域网、光网络、过程控制、电信和无线产品等多个领域,并远销全球多个国家和地区。

Computer Conversions Corp公司的发展小趣事

随着公司技术的成熟和知名度的提升,Computer Conversions Corp开始将目光投向国际市场。公司派出专业的市场拓展团队,深入欧洲、亚洲等多个地区进行市场调研。经过一系列精准的市场分析和产品定位,公司成功地将产品推向了全球市场。这一过程中,他们不仅赢得了众多国际客户的信赖,还通过与当地企业的合作,进一步提升了品牌的影响力和市场份额。

Cristek Interconnects Inc公司的发展小趣事

随着市场竞争的加剧,Cristek Interconnects Inc公司意识到质量管理的重要性。于是,公司投入大量资源,建立了一套完善的质量管理体系,从原材料采购到生产流程控制,再到产品出厂检验,每一个环节都严格把关。这种严谨的质量管理态度,使得Cristek的产品在行业中享有良好的声誉,赢得了客户的信赖。

问答坊 | AI 解惑

车载移动电视接收的系统方案

在柏林推出的DVB T(地面数字广播)数字电视也已经影响到汽车娱乐系统中的电视接收。现在,汽车电视接收机不仅能够接收模拟电视信号(它仍将在城市以外的地区继续存在数年),而且也能够接收和处理DVB T信号。Hirschmann Electronic ...…

查看全部问答>

S3C2410完全开发流程

这是一篇关于s3c2410的开发文档的资料,以及linux的一些实验…

查看全部问答>

关于论坛的改版

论坛改版的挺好看的,从收藏夹进去是会进入新的版面的 但是如果点击了一个版块之后在点击上一根目录“电子工程世界—论坛”就还是回到了老的版面了 不知道是不是改版的一点不完善,望管理员看一下把………

查看全部问答>

无线收发模块汇总

本帖最后由 paulhyde 于 2014-9-15 09:12 编辑 :P :P :P :P :P :P :P :P :P :P :P 好东西与各位分享!  …

查看全部问答>

nRF2401A的程序问题

本人用的是C8051F410单片机,载入2401A的程序,总共2个2401,一个主发,一个主收,无法实现接收,希望有经验的前辈能指点一下。 程序在附件中…

查看全部问答>

医用自动洗片机控制器的研制

  1 引 言   洗片机是各医院影像科的必需设备。医院影像科每天要冲洗大量的x-射线透射胶片,工作量大,且洗片操作有一定难度,对操作人员专业技术要求高,另外,洗片时化学药液对人体有伤害。因此,目前医院大多采用医用自动洗片机。进口的 ...…

查看全部问答>

51中的端口的理解

一个51单片机的程序如下: #include main() {    int results;    results=P2*196;    .........     ......... }复制代码 我对其中的P2不能理解,看了reg51.h中P2定义为: sfr P2  = 0xA0;&nb ...…

查看全部问答>

WINCE 5.0 输入法如何实现,

我使用 ARM 2440开发板, 使用WINCE 5.0 (中文)OS, 现在想实验软键盘 汉字输入 和手写 输入。 请前辈们 描述一下实现 思路。 …

查看全部问答>

串口接收不定长字符串

void InitSio(void) {         u16 RELOAD_COUNT = 0;                 //使用独立波特率发生器作为波特率发生器     S2CON    =   0x50;  ...…

查看全部问答>

电脑拆卸后无法开机

我的电脑拆卸了一次再重新装上后就无法启动了,按电源后只显示品牌标志.…

查看全部问答>