EDN首页   博客首页

日志档案

发表于 2007-1-17 8:25:28

4

标签: Proteus  

数字温度传感器DS18B20的Proteus仿真

调试笔记:

1、DS18B20重新启动单总线,然后使用0xbe读取转换的温度值,不能写入0x44(启动转换)命令之后延时750ms接着就读取scratchpad,这样是没有意义的,参见DS18b20 Datasheet中的访问流程图;

 

2、用单片机模拟单总线需要精确的微秒级延时,因此,延时程序的编制太重要不过了;本例程编制中参考了网络原创贴:51单片机 Keil C 延时程序的简单研究(by: InfiniteSpace Studio),具体如下:

/*延时计算式:2 × x+5;Step:2us;*/
extern void Delay_Xus(int8u x)  //x取值1~255;
{ while(--x); }


3、Read time slot中必须对DQ写1后再读,否则,读出来的温度转换值将是不预期的垃圾;

 

4、内部框图:

点击看大图

5、转换后的温度数据格式:

6、内部Memory组织:

点击看大图

7、时序:

点击看大图

点击看大图

8、子模块例程(One-Wire.c):

/******************************************************************************/
/**
/** 模 块 名: -------------------One-Wire.C----------------------------------
/**            -----------------DS18B20单总线模块----------------------------*/
/** 功能描述:
/**
/** 创 建 人: huangtiexiong    日期:2006-11-28   */
/** 修 改 人:                         日期:2006-11-28   */
/** 其他说明:
/******************************************************************************/

#include "Includes.h"   //文件包含

/*************************************************
    模块级变量申明                
*************************************************/
static void  OneWire_Rst(void);
static void  OneWire_Init(void);
static void  OneWire_WriteByte(int8u cmd);
static int8u  OneWire_ReadByte(void);
static void  OneWire_Idle(void);


/*************************************************
    子函数定义                 
*************************************************/

/*******************************************************************************
*** 函 数 名: static void OneWire_Init(void)
*** 功能描述:
*** 全局变量:
*** 输  入: NO !
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明: 单总线数据传输初始化;
/******************************************************************************/
static void OneWire_Init(void)
{
 DQ = 1; NOP();
 DQ = 0;      //拉低数据线,准备Reset OneWire Bus;
 Delay_Xus(125);  //延时510us,Reset One-Wire Bus.
 Delay_Xus(125);
 
 DQ = 1;      //提升数据线;
 Delay_Xus(15);  //延时35us;
 
 while(DQ)     //等待Slave 器件Ack 信号;
 { NOP(); }
 Delay_Xus(60);  //延时125us; 
 DQ = 1;      //提升数据线,准备数据传输;
 }
/*******************************************************************************
*** 函 数 名: static void OneWire_Rst(void)
*** 功能描述:
*** 全局变量: No !
*** 输  入: NO !
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明: 单总线Reset pulse;
/******************************************************************************/
static void OneWire_Rst(void)
{
 DQ = 0;      //拉低数据线,准备Reset OneWire Bus;
 Delay_Xus(125);  //延时511us,Reset One-Wire Bus.
 DQ = 0; Delay_Xus(125);
 }
/*******************************************************************************
*** 函 数 名: static void OneWire_WriteByte(int8u cmd)
*** 功能描述: 写一个字节;
*** 全局变量: NO !
*** 输  入: cmd:8bit;
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明: cmd主要有Rom操作指令和E2Ram操作指令两种;
/******************************************************************************/
static void OneWire_WriteByte(int8u cmd)
{
 int8u i;
 for(i=0;i<8;i++)
 {if(cmd & 0x01)  //低位在前;
   {DQ = 0;    //结束Recovery time;
    NOP();NOP();NOP();
    DQ = 1;   } //发送数据;
  else
   {DQ = 0;    //结束Rec time;
    NOP();NOP();NOP();  
    //DQ = 0;  } //发送数据;
  Delay_Xus(30);  //等待Slave Device采样;
  DQ = 1;      //Recovery;
  NOP();      //Recovery Time Start;
  cmd >>= 1;
  }
 }
/*******************************************************************************
*** 函 数 名: static int8u OneWire_ReadByte(void)
*** 功能描述: 读取一个字节;
*** 全局变量: NO !
*** 输  入: NO !
*** 输  出: 8bit data;
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明: 读之前必须首先写1;
/******************************************************************************/
static int8u OneWire_ReadByte(void)
{
 int8u i;
 int8u tmp = 0;
 DQ = 1;  NOP();     //准备读;
 for(i=0;i<8;i++)
 {
  tmp >>= 1;    //低位先发;
  DQ = 0;      //Read init;
  _nop_();     //2ms;
  DQ = 1;      //必须写1,否则读出来的将是不预期的数据;
  Delay_Xus(2);   //延时9us;
  _nop_();
  if(DQ)      //在12us处读取数据;
   tmp |= 0x80;
  Delay_Xus(30);  //延时55us;
  DQ = 1;   NOP();   //恢复One Wire Bus;
  }
 return tmp; }
/*******************************************************************************
*** 函 数 名: static void OneWire_Idle(void)
*** 功能描述: 总线空闲模式;
*** 全局变量: NO !
*** 输  入: NO !
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明:
/******************************************************************************/
static void OneWire_Idle(void)
{ DQ = 1; NOP();}
/*******************************************************************************
*** 函 数 名: extern void DS18B20_Init(void)
*** 功能描述: 器件DS18B20初始化;
*** 全局变量: NO !
*** 输  入: NO !
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明:
/******************************************************************************/
extern void DS18B20_Init(void)
{ OneWire_Init();}
/*******************************************************************************
*** 函 数 名: extern void DS18B20_RomCmd(int8u romCmd)
*** 功能描述: DS18B20Rom操作命令写;
*** 全局变量: NO !
*** 输  入: romCmd;
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明: 0x33:Read Rom; 0x55:Match Rom; 0xcc:Skip rom; 0xf0: Search rom;
       0xec:Alarm Search.
/******************************************************************************/
extern void DS18B20_RomCmd(int8u romCmd)  //仅写了SkipRom例程;
{switch(romCmd){
   case 0xcc:   //Skip Rom command;
     OneWire_WriteByte(0xcc);
     break;
   default:
     break;}}
/*******************************************************************************
*** 函 数 名: extern void DS18B20_MemCmd(int8u memCmd)
*** 功能描述: DS18B20Memory 操作命令;
*** 全局变量: NO !
*** 输  入: NO !
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明: 仅写了ConvertT(0x44) 和0xBE命令;
       0x44:Convert T; 0xbe:Read Scratch-pad;
/******************************************************************************/
extern void DS18B20_MemCmd(int8u memCmd) {
 switch(memCmd){
  case 0x44:  //Start to Convert temperature;
   OneWire_WriteByte(0x44);  NOP();
   DS18B20_Busy();
   Delay_Xms(250);  Delay_Xms(250);   Delay_Xms(250); //延时750ms;
    break;
  
  case 0xbe:  //Read scratchpad;
   OneWire_WriteByte(0xbe);
   break;
 default: break; }}
/*******************************************************************************
*** 函 数 名: extern void DS18B20_ReadDat(int8u len,int8u *buf)
*** 功能描述: 读取DS18B20内部的Scratchpad内容;
*** 全局变量: NO !
*** 输  入: len:将要读取的数据长度;
*** 输  出: buf:数据缓存;
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明:
/******************************************************************************/
extern void DS18B20_ReadDat(int8u len,int8u *buf)
{
 int8u i;
 for(i=0;i { buf[i] = OneWire_ReadByte();}
 OneWire_Rst();OneWire_Idle(); }
/*******************************************************************************
*** 函 数 名: extern void DS18B20_Busy(void)
*** 功能描述: 内部模数转换中,忙
*** 全局变量: NO !
*** 输  入: NO !
*** 输  出: NO !
*** 创 建 人:huangtiexiong     日期:2006-11-28
*** 修 改 人:           日期:2006-11-28
*** 函数说明:
/******************************************************************************/
extern void DS18B20_Busy(void)
{OneWire_Idle();}

/*******************************************************************************
****                              End Of File
*******************************************************************************/

9、Proteus仿真抓图:

点击看大图

附件:rar

系统分类: 单片机   |   用户分类: 无分类   |   来源: 原创   |   【推荐给朋友】   |   【添加到收藏夹】

    阅读(2379)    回复(19)  

投一票您将和博主都有获奖机会!

最新评论

  • wolfhust

    2007-5-19 3:31:57

    整个Project包括code、dsn已附,请自个查阅。

  • hopingjian

    2007-5-15 12:58:07

    你好,我刚接触proteus和keil c51,需要做一个温度控制系统的仿真,希望你能传我一份单点温度仿真(用DS18B20的)的源文件做初步学习,谢谢

    我的邮箱:hopingjian@163.com

  • hgirui

    2007-5-17 15:18:21

    我现在急需要设计一个电路和C语言,是用PIC877和DSB18B设计的实验,用数码管显示的.如果可以的话请发到我的邮箱:hgirui@163.com。谢谢!

  • 李勇

    2007-1-19 1:04:45

    你好...我最近也在学习proteus仿真DS18B20.

    但是在搭出电路后仿真总不成功...

    说是D1WIO.DLL failed to create DSIM model for primitive type 'D1WIO'.

    想请教你是怎么实现的...期待你的来信 easttt@qq.com

     

  • wolfhust

    2007-1-19 8:43:11

    你用6.9版的sp4试试,只要时序控制的好一定是可以成的。我以前用的6.7版sp3(比较经典的一个版本),也出现这种情况,因为这个版本里边还没有DS18B20的单总线仿真模型。

  • hope

    2007-5-28 9:21:36

    icon

    果然是没戴眼睛的结果,打搅了,抱歉

  • wolfhust

    2007-5-28 6:20:32

    压缩包里边有,戴眼镜找找

    #ifndef __Includes_h__
    #define __Includes_h__

    #include   <reg52.h>
    #include    <intrins.h>
    #include    <string.h>
    #include   "Defines.h"
    #include   "LCD.H"
    #include   "One-Wire.h"
    #include   "Delay.h"
    #endif

  • hope

    2007-5-27 21:12:56

    谢谢你的回答,对于第一个问题(#include "Includes.h"),其实我想问的是,我并没有见到你程序中的"Includes.h"文件,因此不知道在这个文件里包含了什么头文件,我属初学,希望您对我的菜鸟问题不吝赐教,谢谢

  • hope

    2007-5-27 9:34:08

    谢谢你的回答,再请教一个问题,在你的程序中只有见到一个 #include "Includes.h",对这个我不懂,期盼你的解答

  • wolfhust

    2007-5-27 17:06:20

    1、这是编程习惯的问题,C的优势在于它的模块化,一般一个功能模块由一个/若干个源文件和一个/若干个头文件搭建,在工程项目中新增一个Includes.h文件将所有的头文件包含然后每个源文件仅使用一条预处理指令:#include "Includes.h"即可;这种实现方式虽然增加了编译器的负荷(譬如编译时间会稍长)但对最终代码的质量没有任何影响,最重要的:省事~~~,当然你也可以采用其他的方法;

    2、Keil项目工程中的晶振频率一般仅在使用某些串口调试器对目标板硬调试时,为同步需要必须与目标板设置一致,大多情况下无效,最终一条指令的执行时间由目标板实际晶振频率决定,本人的proteus仿真文件(DS18B20.DSN)中的晶振频率为12MHz,请注意。

  • hope

    2007-5-27 14:27:25

    请问你一下,在你的delayus函数中,

    /*延时计算式:2 × x+5;Step:2us;*/
    extern void Delay_Xus(int8u x)  //x取值1~255;
    { while(--x); }


    可是你选用的CPU的晶振频率为24MHZ,也就是0.5us一个周期,那么你的step应该是1us才对,诚心请教

  • hope

    2007-5-26 21:28:23

    请教下,程序中的int8u是什么数据类型

  • wolfhust

    2007-5-26 23:17:02

    typedef unsigned  char   int8u;
    typedef signed   char   int8s;
    typedef unsigned  int   int16u;
    typedef signed   int   int16s;
    typedef unsigned  long   int32u;
    typedef signed   long  int32s;

  • canopen

    2007-5-25 7:06:52

    一个简单的方法是:DS18B20及LCD初始化之后,将命令转换、温度值读取、LCD显示置于一个While循环即可实现,或者利用定时器中断

  • luoxuan_345

    2007-5-24 20:32:18

    我想请问一下 如果要让它实现实时测量 应该怎样修改程序,谢谢

  • JY860824

    2008-5-30 16:53:26

    dasdasd

  • purple333

    2008-6-25 11:31:00

    请问楼主,我用PTOTEUS仿真,为什么下载的这个显示出来的温度值与DS18B20上的数据不一样呢??

  • carrick

    2008-9-30 11:27:15

    请问你的调试笔记: 1、DS18B20重新启动单总线,然后使用0xbe读取转换的温度值,不能写入0x44(启动转换)命令之后延时750ms接着就读取scratchpad,这样是没有意义的,参见DS18b20 Datasheet中的访问流程图; 什么意思? 不延时750ms就读取温度,那要干什么? 诚恳请教!!!!

  • carrick

    2008-9-30 11:27:42

    请问你的调试笔记: 1、DS18B20重新启动单总线,然后使用0xbe读取转换的温度值,不能写入0x44(启动转换)命令之后延时750ms接着就读取scratchpad,这样是没有意义的,参见DS18b20 Datasheet中的访问流程图; 什么意思? 不延时750ms就读取温度,那要干什么? 诚恳请教!!!!