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

2007-1-17 08:25 9388 9 26 分类: MCU/ 嵌入式

调试笔记:


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、转换后的温度数据格式:


48c0ca7b-081e-468d-beb6-29d5e99e18d1.JPG


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 = 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

文章评论17条评论)

登录后参与讨论

用户222661 2009-4-30 23:37

找个程序不能实现实时的数据传输。温度改了就要重启单片机啊

用户165042 2008-9-30 11:27

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

用户150889 2008-6-25 11:31

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

用户149109 2008-5-30 16:53

dasdasd

用户16390 2007-5-28 09:21

icon

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

用户68356 2007-5-28 06:20

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

#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

用户16390 2007-5-27 21:12

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

用户68356 2007-5-27 17:06

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

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

用户16390 2007-5-27 14:27

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

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


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

用户16390 2007-5-27 09:34

谢谢你的回答,再请教一个问题,在你的程序中只有见到一个 #include "Includes.h",对这个我不懂,期盼你的解答
相关推荐阅读
用户68356 2007-06-10 09:23
canopen
我申请了恒润科技的试用光盘(VectorDemoCDV8.3),里边coe_canopen.exe因损坏无效,是不是每张光盘都这样?...
用户68356 2007-05-19 03:39
本博公告
本博暂停更新,稍后就回。欢迎访问:canopen.onlyblog.com...
用户68356 2007-03-14 22:17
ARM7TDMI-S后缀解释
T:Thumb代码支持,16bits指令结构;D:Debug硬件调试模块支持;M:加强的乘法操作支持(硬件乘法器),64位乘法结果;I:EmbededICE Logic,支持片上断点和调试点;S:sy...
用户68356 2007-03-14 04:44
老子-道德经
老子道德经--白话文注解:http://www.xet.cn/_game/lib/01_laozi/...
用户68356 2007-03-08 00:56
ARM完整定义
     ARM是英国一家电子公司的名字,全名的意思是Advanced RISC Machine。ARM首创了chipless的生产模式,即该公司既不生产芯片,也不设计芯片,而是设计出高效的IP内核,...
用户68356 2007-03-08 00:24
CPU基本概念
1.主频       主频也叫时钟频率,单位是MHz,用来表示CPU的运算速度。CPU的主频=外频×倍频系数。很多人认为主频就决定着CPU的运行速度,这不仅是个片面的,而且对于服务器来讲,这个认识也出...
我要评论
17
9
关闭 站长推荐上一条 /2 下一条