调试笔记:
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 = 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仿真抓图:
用户222661 2009-4-30 23:37
用户165042 2008-9-30 11:27
用户150889 2008-6-25 11:31
用户149109 2008-5-30 16:53
用户16390 2007-5-28 09:21
果然是没戴眼睛的结果,打搅了,抱歉
用户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
/*延时计算式: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