打印
[51单片机]

新手求罩,为啥我的DS18B20老是读错?

[复制链接]
862|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
         本人是个新手,大家别笑话。 这个DS18B20驱动程序我写了1星期,参考例程数据手册改了很多次就是没用,甚至还用protues示波器观察仿真波形都没问题,大家能帮我看一下错哪了吗?下面是DS18B20的代码
       /*******************************************************************************                                                                             *
*                       DS18B20.h                                             *
*                                                                             *
******************************************************************************
描述:   的头文件
硬件:
******************************************************************************/
#ifndef   DS18B20_H
#define   DS18B20_H
#include <STC12C5A60S2.H>
//#include <STC89C5xRC.H>
#include  <intrins.h>
#define uchar unsigned char
#define uint unsigned int
//unsigned char data  RomCode[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//存储序列号
unsigned char Temp;
unsigned char  crc;
sbit DQ=P2^4;
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
struct Temperature
{
  uchar LSB;
  uchar MSB;
  uint temper;          // 温度的2进制存储格式
  uchar         flag;    //        负号标志
  float  f_temper;        //温度的浮点数存储格式
  uchar cc;                   //整数
  uchar xs;                  //1位小数
} temperature={0,0,0,0,0.0,0,0};

/***********************函数声明区**************************************************/



/***********************函数定义区**************************************************/

/******************************************************************
函数名:微秒级延时函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
void Delayxus(unsigned int j)           //延时(j+1)*15us
{
            //CLK_DIV=0x03;          //用于stc12系列高速单片
             for(j;j>0;j--)
          {
                 _nop_();_nop_();_nop_();_nop_();
          }     
          _nop_(); _nop_();
                     //CLK_DIV=0x00;

}


/******************************************************************
函数名:DS18B20复位函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
bit DS18_init()
{


   bit presence;
   EA=0;
     DQ = 1;      //DQ复位
     Delayxus(1);    //稍做延时

     DQ = 0;      //将DQ拉低
     Delayxus(32);   //精确延时 大于 480us

     DQ = 1;       //拉高总线
     Delayxus(3);                 //60

     presence = DQ;    //读取存在信号
     Delayxus(32);
     DQ = 1;

     return(presence); //返回信号,0=presence,1= no presence

   EA=1;
}

/******************************************************************
函数名:读1位函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
unsigned char DS18_readbit(void)
{


        bit dat;
   // unsigned char i;
    EA=0;
        DQ=1;
        _nop_();
    DQ=0;                      //将DQ 拉低开始读时间隙
    _nop_();
        DQ=1;                           //释放总线
        _nop_();   
        _nop_();     
        dat=DQ;                        // then return high
        Delayxus(3);                                // 延时60μs
        DQ=1;
        EA=1;
    return(dat);                         // 返回 DQ 线上的电平值

}

/******************************************************************
函数名:写1位函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
void DS18_writebit(unsigned char dat)
{
       
            EA=0;
        DQ = 0;
                _nop_();
                _nop_();                                       // 将DQ 拉低开始写时间隙
        if(dat==1)             
                DQ =1;                                                    // 如果写1,DQ 返回高电平
        Delayxus(4);                                       // 在时间隙内60保持电平值,
        DQ = 1;   
             EA=1;
}


/******************************************************************
函数名:读1字节函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
unsigned char DS18_readbyte(void)
{
unsigned char i = 0;
unsigned char dat = 0;

for (i=0;i<8;i++)
{                                  // 读取字节,每次读取一个字节
  if(DS18_readbit())
   dat|=0x80;           // 然后将其左移
   dat>>=1;  
  }

    return (dat);
}

/******************************************************************
函数名:写1字节函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
void DS18_writebyte(unsigned char dat)
{
  unsigned char i = 0;
  unsigned char temp;

   for (i=0; i<8; i++)         // 写入字节, 每次写入一位
   {                  
   temp=0x01&dat;                 
   DS18_writebit(temp);
   dat>>=1;  
  }
}



/******************************************************************
函数名:温度转换启动函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
void DS18_CONVERT()
{
   bit prese; //返回校验位
/*************启动温度转换****************/
   prese=DS18_init();
   DS18_writebyte(0xcc);
   DS18_writebyte(0x44);
   return prese;
}


/******************************************************************
函数名:DS18B20获取温度函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************/
void  DS18_GET()
{
    bit prese;//返回校验位
        /*************获取温度****************/
   prese=DS18_init();
   DS18_writebyte(0xcc);
   DS18_writebyte(0xbe);
   temperature.LSB=DS18_readbyte();
   temperature.MSB=DS18_readbyte();
/*************数据处理部分****************/
   temperature.temper=temperature.MSB&0x07;
   temperature.temper<<=8;
   temperature.temper=temperature.temper|temperature.LSB;
    if(temperature.MSB>0xf8)
        temperature.flag=1;                  //负号标志置1
   temperature.f_temper=temperature.temper/16;
   temperature.cc=(uchar)temperature.f_temper;
   temperature.xs=(uchar)(temperature.f_temper*10);
   temperature.xs=temperature.xs%10;
}








/******************************************************************
函数名:DS18B20获取ROM函数
调用:
参数:
返回值:
功能:
备注:
******************************************************************
void Read_RomCord(void)
{
     unsigned char j;
     DS18_init();

     DS18_writebyte(0x33);  // 读序列码的操作
     for (j = 0; j < 8; j++)
         {
          RomCode[j] = DS18_readbyte();
         }
}

/******************************************************************
函数名:
调用:
参数:
返回值:
功能:
备注:
******************************************************************
uchar CRC8()
{
   uchar i,x; uchar crcbuff;   
   crc=0;
   for(x = 0; x <8; x++)
   {
    crcbuff=RomCode[x];
    for(i = 0; i < 8; i++)
     {
      if(((crc ^ crcbuff)&0x01)==0)
      crc >>= 1;
       else {
              crc ^= 0x18;   //CRC=X8+X5+X4+1
              crc >>= 1;
              crc |= 0x80;
            }         
      crcbuff >>= 1;      
         }
   }
     return crc;       
}
/***********************************************************/
#endif



仿真.PNG (24.37 KB )

仿真

仿真

相关帖子

沙发
专注于嵌入式| | 2015-10-1 22:20 | 只看该作者
其实还是从时序找,绝对是时序问题。仿真正确,但是,实际中还是有问题的。仿真你也敢信?

使用特权

评论回复
板凳
ZG11211| | 2015-10-5 09:43 | 只看该作者
要保证足够的读写时间差,否则18B20反应不过来。

使用特权

评论回复
地板
无量寿经| | 2015-10-6 12:09 | 只看该作者
只要时序准确,18B20在百米以上距离进行通信也没任何问题。

使用特权

评论回复
5
dirtwillfly| | 2015-10-8 06:35 | 只看该作者
都是时序惹的祸

使用特权

评论回复
6
oldzhang| | 2015-10-8 19:55 | 只看该作者
注意时钟,你可以按照计算用IO输出一个方波,用示波器看周期或频率对不对

使用特权

评论回复
7
Mr_Cheng| | 2015-10-9 07:48 | 只看该作者
仿真跟硬件的18b20的时序有些出入,有硬件最好别用仿真调试

使用特权

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

本版积分规则

4

主题

14

帖子

0

粉丝