本帖最后由 Step1toStep5 于 2011-7-1 17:20 编辑
求DS18B20时序问题,希望能给予自己的见解,复制到好的也可以。
弄18B20两天了,时序这里一直不对,仿真出了,但是实际的时序一直不行。
怎么办?谁能给个意见。我用的是AVR 4M的晶振。。
//------------------------------------------------------------
// 名称:DS18B20温度传感器程序
//
//------------------------------------------------------------
/*
//#define F_CPU 1000000UL //4MHz
#include <avr/io.h>
#include <util/delay.h>
#include <stdint.h>
//#include "DS18B20.h"
//#define uint8_t unsigned char
#include <avr/interrupt.h>
//DS18B20引脚定义
#define DQ PC6
//设置数据方向
//设置数据方向
#define DQ_DDR_0() DDRC &= ~_BV(DQ)
#define DQ_DDR_1() DDRC |= _BV(DQ)
//温度管引脚操作定义
#define DQ_1() PORTC |= _BV(DQ)
#define DQ_0() PORTC &= ~_BV(DQ)
#define RD_DQ_VAL() (PINC & _BV(DQ))
//温度小数位对照表
const uint8_t df_Table[] = {0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,9};
//当前读取的温度整数部分
uint8_t CurrentT = 0;
//从DS18B20读取的温度值
uint8_t Temp_Value[] = {0x00,0x00};
//待显示的各温度数位
uint8_t Display_Digit[] = {0,0,0,0};
//传感器状态标志
uint8_t DS18B20_ERROR = 0;
//当前温度显示缓冲
char Current_Temp_Display_Buffer[] = {"TEMP: "};
uint8_t status = 0x01;
uint8_t dat = 0x00;
//---------------------------------------------------------
// 初始化DS18B20
//---------------------------------------------------------
uint8_t Init_DS18B20()
{
//uint8_t status;
cli();
DQ_DDR_1();
DQ_0();
_delay_us(500); //主机拉低DQ,占领总线
DQ_DDR_0(); //DQ设为输入
DQ_1();
_delay_us(68);
status = RD_DQ_VAL();
_delay_us(500); //读总线,为0时器件在线
//while(!status);
sei();
DQ_DDR_1(); DQ_1(); //释放总线
return status; //返回器件状态(0为正常)
}
//------------------------------------------------------------
// 读一字节
//------------------------------------------------------------
uint8_t ReadOneByte()
{
uint8_t i;
dat=0x50;
for(i=0;i<8;i++)
{
DQ_DDR_1(); DQ_1();//delay2us();
DQ_0(); //写0拉低DQ占领总线
//Delayxus_DS18B20(1);
//delay2us();delay2us();delay2us();delay2us();
_delay_us(8);
DQ_1();//Delayxus_DS18B20(1);
DQ_DDR_0(); //读DQ引脚
//delay2us();
if(RD_DQ_VAL()) dat|= _BV(i); //读取第i位放入dat内对应位置
_delay_us(80); //延时
//Delayxus_DS18B20(14);
}
DQ_DDR_1();DQ_1();
return dat; //返回读取的1字节数据
}
//------------------------------------------------------------
// 写一字节
//------------------------------------------------------------
void WriteOneByte(uint8_t dat)
{
uint8_t i;
for(i=0x01;i!=0x00;i<<=1)
{
DQ_DDR_1();DQ_0(); //写0拉低DQ占领总线
if(dat&i) DQ_1();else DQ_0(); //想数据线写0或者1
_delay_us(80); //延时
DQ_1(); //释放总线
}
}
//------------------------------------------------------------
// 读取温度值
//------------------------------------------------------------
void Read_Temperature()
{
if(Init_DS18B20()!=0x00)
DS18B20_ERROR = 1;
//else
{
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0x44); //启动温度转换
Init_DS18B20(); //重新启动DS18B20
WriteOneByte(0xcc); //跳过序列号
WriteOneByte(0xbe); //读取温度寄存器
Temp_Value[0] = ReadOneByte(); //温度低八位
Temp_Value[1] = ReadOneByte(); //温度高八位
//DS18B20_ERROR = 0;
}
}
//------------------------------------------------------------
// 温度值转换
//------------------------------------------------------------
void Temperature_Convert(void)
{
uint8_t ng = 0; //负数标识
//如果不用查表法换算小数时可以使用下面两行
//uint8_t i; float Temp_Df = 0.0;
//如果为负数则取反加1,并设置负数标识
//按照技术手册说明,高5位为符号位,应与上0xF8进行+/-判断
if((Temp_Value[1]&0xF0) == 0xF0)
{
Temp_Value[1] = ~Temp_Value[1];
Temp_Value[0] = ~Temp_Value[0] + 1;
if(Temp_Value[0] == 0x00) Temp_Value[1]++;
//负数标识置为1
ng = 1;
}
//查表得到温度小数部门
Display_Digit[0] = df_Table[Temp_Value[0] & 0x0F];
//------不使用查表法获取温度小数部分时可使用下面代码-----
//for(i=0;i<4;i++)
//{ //根据低4位是否为1,分别累加:1.0/2,1.0/4,1.0/8,1.0/16
// if(Temp_Value[0]&_BV(i)) Temp_Df += 1.0/_BV(4-i);
//}
//Display_Digit[0] = (uint8_t)((Temp_Df+0.05)*10); //第二位小数四舍五入
//-------------------------------------------------------
//获取温度整数部分(无符号)
CurrentT = (Temp_Value[0]>>4)|(Temp_Value[1]<<4);
//将整数部分分解为3位待显示数字
Display_Digit[3] = CurrentT / 100;
Display_Digit[2] = CurrentT % 100 / 10;
Display_Digit[1] = CurrentT % 10;
//刷新LCD显示缓冲
Current_Temp_Display_Buffer[11] = Display_Digit[0] + '0';
Current_Temp_Display_Buffer[10] = '.';
Current_Temp_Display_Buffer[9] = Display_Digit[1] + '0';
Current_Temp_Display_Buffer[8] = Display_Digit[2] + '0';
Current_Temp_Display_Buffer[7] = Display_Digit[3] + '0';
//高位为0时不显示
if(Display_Digit[3] == 0) Current_Temp_Display_Buffer[7] = ' ';
//高位为0且次高位为0时,次高位不显示
if(Display_Digit[2] == 0 && Display_Digit[3] == 0)
Current_Temp_Display_Buffer[8]=' ';
//负数符号显示在恰当位置
if(ng)
{
if(Current_Temp_Display_Buffer[8] == ' ')
Current_Temp_Display_Buffer[8] = '-';
else
if(Current_Temp_Display_Buffer[7] == ' ')
Current_Temp_Display_Buffer[7] = '-';
else
Current_Temp_Display_Buffer[6] = '-';
}
} |