微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > AVR的DS18B20温度程序

AVR的DS18B20温度程序

时间:10-02 整理:3721RD 点击:
参照网上的资料和DATESHEET写了一个DS18B20的程序,单片机为ATMEL128,晶振为8M,但是温度一直显示为255,从早上开始找原因,没有找到。现在把源代码发上来,各位能帮我分析一下原因吗?(程序未完整,只是发了温度部分,显示部分就不发了,调试是成功了)
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/iom128.h>
#include <string.h>
#define  FREQ  8         //芯片工作频率
#define uchar unsigned char
#define uint  unsigned int
/*******************温度设定********************/
#define DQ_H PORTA|= (1<<PA3) //DQ_H置高
#define DQ_L PORTA&= ~(1<<PA3) //DQ_L置低
#define DQ_R PINA        //读取总线数据
#define DQ_IN DDRA&=~(1<<PA3) //设置PA3为输入
#define DQ_OUT DDRA|=(1<<PA3)//设置PA3为输出
static uchar *table[10]={"0","1","2","3","4","5","6","7","8","9",};
/******延时函数********/
void delay_nms(uint n)        
   {
      uint i=0 ;
      for (i=0 ;i<n ;i++)
      _delay_loop_2(250*FREQ) ;
   }
/********************************************************/
/*                                                      */
/* y*us延时函数                                         */
/*                                                      */
/********************************************************/   
void  delay(uint y)
  {
    _delay_loop_2(2*y);
  }

/***************************DS18B20复位程序**************************/
void reset(void)
{
        uchar flag;
        flag=1;
        while(flag)
        {
                DQ_L;
                delay(600);        //拉低总线600us,发送复位命令
                DQ_H;
                DQ_IN;
                delay(60);        //等待回应
        
                if(PINA&_BV(PA3))
                                delay(350);        //延时后继续复位        
                else
                        flag=0;                        //跳出复位        
        }                        
        delay(350);//初始化完成,恢复高电平
        DQ_OUT;
        delay(2);
}
/**********************向DS18B20发送数据(从低位到高位)*******************/
void send_date1(uchar date)
{
        uchar temp,i;
        for(i=8;i>0;i--)
        {
                temp=(date&0x01);        //检测date第一位是否为1
                DQ_L;
                delay(15);//产生发送时序
                if(temp)        
                        DQ_H;               
                else               
                        DQ_L;        //发送数据
                        
                delay(60);        //等待DS18B20采样
                DQ_H;
                delay(2);        //结束发送,进入下一个字节发送
                date=(date>>1);
        }
                                
}

/********************从DS18B20读数据(高位到低位)***********/
uchar read_date1(void)
{
        uchar date,i;
        date=0x00;
        for(i=8;i>0;i--)
        {        
                DQ_L;
                delay(1);        //产生读时序
                date=(date>>1);               
                DQ_H;                //发送读取命令
                DQ_IN;
                delay(3);//释放总线
                if((DQ_R&=(1<<PA3)))
                date=(date|0x80);        //如果总线数据为1,那么高位置1
                delay(60);                //一个读周期
                DQ_H;        //恢复总线        
                DQ_OUT;
                delay(1);
        }
        return(date);
}
/**********************************温度函数**********************/
unsigned int readtemp(void)
{
        uchar TVL,TVH;
        unsigned int tempvalue,temp;
        tempvalue=0;
        temp=0;
        reset();
        send_date1(0xCC);        //忽略RAM匹配
        send_date1(0x44);        //发送温度查询命令

        reset();                //复位
        send_date1(0xCC);
        send_date1(0xBE);        //读取暂存器上的温度数据        
        
        TVL=read_date1();        //温度低8位
        TVH=read_date1();        //温度高8位
//        TVL=0x55;
//        TVH=0x02;
        temp=TVH;
        temp=(temp<<8);
        tempvalue=(temp|TVL);
        tempvalue=(tempvalue*0.0625);
        
        return tempvalue;
}

#define DQ_data PORTC.7
#define DQ_bus(x) DDRC.7 = x
void DS18B20_Init()
{
    uint i = 0;
    DQ_bus(1);
    DQ_data = 1;
    DQ_data = 0;
    delay_us(640);
    DQ_data =1;
   
    DQ_bus(0);
//    delay_us(60);
    while(PINC.7)
    {
        delay_us(60);
        i++;
        if(i >= 10000)
        {
            flag = 1;
            break;
        }      
    }
    delay_us(480);
   
    DQ_bus(1);
    DQ_data = 1;
   
}
void DS18b20_Write(uchar dat)
{
    uchar m;
    DQ_bus(1);
    for(m = 0;m < 8; m++)
    {
        DQ_data = 0;
        delay_us(15);      
        if(dat &(1 << m))
        {
            DQ_data = 1;
            delay_us(15);
            delay_us(15);
            delay_us(15);     
        }
        else
        {
            DQ_data = 0;
            delay_us(15);
            delay_us(15);
            delay_us(15);
            delay_us(15);
      
        }
        DQ_data = 1;        
    }
    DQ_bus(1);
    DQ_data = 1;
}

uchar DS18b20_Read()
{
    uchar n,temp,k;
    temp = 0;
   
   // IO_In;
    for(n = 0;n < 8;n++)
    {
        DQ_bus(1);   
        DQ_data = 1;
        delay_us(2);
        DQ_data = 0;
        delay_us(6);
        DQ_data = 1;
        delay_us(4);
        DQ_bus(0);
        k = (PINC & (1 << 7));
        if(k)
        {
            temp |= (1 << n);
        }
        else
        {
            temp &= ~(1 << n);
        }
        delay_us(30);
    //    DQ_bus(1);     
    }
    return (temp);
}

void Gettemp()
{
    uint w;

  //  uchar i;
    DS18B20_Init();
    DS18b20_Write(0xcc);
    DS18b20_Write(0x44);
    delay_ms(100);
    DS18B20_Init();
    DS18b20_Write(0xcc);
    DS18b20_Write(0xbe);
    templ = DS18b20_Read();
    temph = DS18b20_Read();
   
//    uint w;
//   uchar i;
//    Gettemp();
    w = temph;
    w = w << 8;
    w = w | templ;
    if(w < 0x0fff)
        sign1 = 1;
    else
        {
            w = ~w + 1;
            sign1 = 0;
        }
    w = w * (0.625) - 40;
    e[0] = w / 1000 + 0x30;
    e[1] = w % 1000 / 100 + 0x30;
    e[2] = w % 100 / 10 + 0x30;
    e[3] = w % 10 +0x30;
}

这个程序我测试过了,你自己对一下吧

谢谢分享                              

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top