打印

求DS18B20时序问题,希望能给予自己的见解,复制到好的也可以

[复制链接]
3501|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Step1toStep5|  楼主 | 2011-7-1 17:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 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] = '-';
        }
}

相关帖子

沙发
Step1toStep5|  楼主 | 2011-7-1 17:21 | 只看该作者
调试时发现数据写入应该是正确的,但是读取出来的值一直是FF~就是说读取时候一直返回高电平。。这个时序那里不对啊?

使用特权

评论回复
板凳
plc_avr| | 2011-7-1 19:10 | 只看该作者
https://bbs.21ic.com/icview-227267-1-1.html看这个贴子,现在用于M0的片子上,原先也是在AVR上移值过来的,只要改下端口和延时的时间就可以了。

使用特权

评论回复
地板
plc_avr| | 2011-7-1 19:11 | 只看该作者
时序很重要,否则是读不出正确数据的。

使用特权

评论回复
5
程序会不会| | 2011-7-1 22:01 | 只看该作者
是不是转换的时间不够???

使用特权

评论回复
6
Step1toStep5|  楼主 | 2011-7-4 13:05 | 只看该作者
5# 程序会不会
- - 是对~我一直以为是读时序问题~~结果发现是温度转换时间不够。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:都是鼠标惹得祸

0

主题

63

帖子

1

粉丝