STC15W4K56S4一线多点DS18B20问题

2019-03-24 17:02发布

#include<STC15.H>
#include "stdio.h"
#include "intrins.h"
#define ulong unsigned long
#define uchar unsigned char     
#define uint unsigned int
#define MAXNUM 5
#define MaxNum 4
sbit temp=P5^5;       //18B20
uchar  ID[4][8]={0};
uint wd;
float tt;
int num=0;
void UartInit(void)  [url=]//9600bps@11.0592MHz[/url]
{
SCON = 0x50;  //8位数据,可变波特率
AUXR |= 0x40;  //定时器1时钟为Fosc,即1T
AUXR &= 0xFE;  //串口1选择定时器1为波特率发生器
TMOD &= 0x0F;  //设定定时器1为16位自动重装方式
TL1 = 0xE0;  //设定定时初值
TH1 = 0xFE;  //设定定时初值
ET1 = 0;  //禁止定时器1中断
TR1 = 1;  //启动定时器1
TI= 1;
}
void Delay_DS18B20(ulong n)
{   
while(n--);
}
/*****初始化DS18B20*****/
void Init_DS18B20(void)
{   
unsigned char x=0;   
temp = 1;          //temp复位   
Delay_DS18B20(2);   //稍做延时4us   
temp = 0;          //单片机将temp拉低   
Delay_DS18B20(90); //精确延时,大于480us  
temp = 1;          //拉高总线   
Delay_DS18B20(20);  
x = temp;            //稍做延时后,如果x=0则初始化成功,x=1则初始化失败   
Delay_DS18B20(20);
}
/*****读一个字节*****/
unsigned char ReadOneChar(void)
{   
unsigned char i=0,j=0;   
unsigned char dat = 0;  
for (i=8;i>0;i--)   
{   
temp = 0;     // 给脉冲信号
j++;j++; j++;j++;  
dat>>=1;
j++;j++; j++;j++;   
temp = 1;     // 给脉冲信号
  j++;j++; j++;j++;
if(temp)   
dat|=0x80;  
Delay_DS18B20(8);  
}   
return(dat);
}
/*********读一位***********/

//bit read1bit(void)
//{     
// bit dat = 0;  
//
// temp = 0;     // 给脉冲信号   
// Delay_DS18B20(1);   
// temp = 1;     // 给脉冲信号
// Delay_DS18B20(1);
// if(temp)   
// dat|=0x01;  
// Delay_DS18B20(5);
// return dat;  
//}

/********读两位************/
unsigned char Read2Bit(void)
{   
unsigned char i=0,j=0;   
unsigned char dat = 0;  
for (i=2;i>0;i--)   
{   
temp = 0;     // 给脉冲信号
j++;j++; j++;j++;  
dat<<=1;
j++;j++; j++;j++;   
temp = 1;     // 给脉冲信号
  j++;j++; j++;j++;
if(temp)   
dat|=0x01;  
Delay_DS18B20(8);  
}   
return(dat);
}
//uchar  Read2Bit(void)
//{
// uchar i,dat=0;
// for(i=0;i<2;i++)
// {
//  dat<<=1;
//  if(read1bit())
//  dat|=1;
//
// }
//
// return dat;
//}

/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{   
unsigned char i=0,j=0;;  
for (i=8; i>0; i--)  
{  
  temp = 0;
  j++;j++;j++;j++;
  temp = dat&0x01;  
  Delay_DS18B20(10);  
  temp = 1;  
  dat>>=1;
  j++;j++;j++;  
  }
}
/*********写一位*********/
void write_bit(unsigned char dat)
{   
unsigned char i=0,j=0;;  
for (i=1; i>0; i--)  
{  
  temp = 0;
  j++;j++;j++;j++;
  temp = dat&0x01;  
  Delay_DS18B20(10);  
  temp = 1;  
  dat>>=1;
  j++;j++;j++;  
  }
}

//void write_bit(unsigned char dat)
//{   
//
// unsigned char i=0;  
// for (i=1; i>0; i--)  
// {  
//  temp = 0;  
//  temp = dat&0x01;  
//  Delay_DS18B20(10);  
//  temp = 1;  
//  Delay_DS18B20(10);  
//  }
//
// }
/*********************/
void Delay1000ms()  [url=]//@11.0592MHz[/url]
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
  do
  {
   while (--k);
  } while (--j);
} while (--i);
}
void tmpchange()
{
temp = 1;
Delay_DS18B20(5);
Init_DS18B20();
WriteOneChar(0xcc);
WriteOneChar(0x44);
Delay_DS18B20(20000);
}
/*
uchar search_rom(void)  
{   
    unsigned char k,l,chongtuwei,m,n;  
    unsigned char zhan[(MAXNUM)]={0};  
    unsigned char ss[64];  
    int num = 0;  
    l=0;  
      
    do  
    {  
      Init_DS18B20();
Delay_DS18B20(100);  
      WriteOneChar(0xf0);
Delay_DS18B20(100);     
        for(m=0;m<8;m++)  
        {  
            unsigned char s=0;  
            for(n=0;n<8;n++)  
            {    t1=0;
     t2=0;
     t3=0;
                k=Read2Bit();//读两位数据
              k=k&0x03;  
                s>>=1;  
                if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应  
                {   t1=1;         
                    write_bit (0);  
                    ss[(m*8+n)]=0;  
                }  
                else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应  
                {  t2=1;
                    s=s|0x80;  
                    write_bit (1);  
                    ss[(m*8+n)]=1;  
                }  
                else if(k==0x00)//00,判断冲突位 冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1  
                {    t3=1;            
                    chongtuwei=m*8+n+1;                  
                    if(chongtuwei>zhan[l])  
                    {                        
                        write_bit (0);  
                        ss[(m*8+n)]=0;                                                
                        zhan[++l]=chongtuwei;                        
                    }  
                    else if(chongtuwei<zhan[l])  
                    {  
                        s=s|((ss[(m*8+n)]&0x01)<<7);  
                        write_bit (ss[(m*8+n)]);  
                    }  
                    else if(chongtuwei==zhan[l])  
                    {  
                        s=s|0x80;  
                        write_bit (1);  
                        ss[(m*8+n)]=1;  
                        l=l-1;  
                    }  
                }  
                else  
                {  
                    return num; //搜索完成,//返回搜索到的个数  
                }
   
            }
   
            ID[num][m]=s;        
        }  
        num=num+1;  
    }  
    while(zhan[l]!=0&&(num<MAXNUM));   
      
    return num;     //返回搜索到的个数  
}
*/
uchar search_rom()  
{   
    uchar k,l=0,chongtuwei,m,n,a;  
    uchar _00web[MAXNUM]={0};
    do  
    {  
  
        Init_DS18B20();  
        WriteOneChar(0xf0);      
        for(m=0;m<8;m++)  
        {  
   char s=0;
            for(n=0;n<8;n++)  
            {  
                k=Read2Bit();//读两位数据  
                k=k&0x03;  
    s>>=1;
                if(k==0x01)//01读到的数据为0 写0 此位为0的器件响应  
                {            
                    write_bit(0);        
                }  
                else if(k==0x02)//读到的数据为1 写1 此位为1的器件响应  
                {  
     s=s|0x80;
                    write_bit(1);  
                    
                }  
                else if(k==0x00)//读到的数据为00 有冲突位 判断冲突位   
                {               //如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1  
                    chongtuwei=m*8+n+1;                  
                    if(chongtuwei>_00web[l])  
                    {                        
                        write_bit(0);  
                                                                 
                        _00web[++l]=chongtuwei;                        
                    }  
                    else if(chongtuwei<_00web[l])  
                    {  
                     a=(ID[num-1][m]>>n)&0x01;
      s=s|(a<<7);
      write_bit(a);
                    }  
                    else if(chongtuwei==_00web[l])  
                    {  
                        s=s|0x80;
      write_bit(1);
      l=l-1;
                    }  
                }  
                else if(k==0x03)   
                {  
                    return (0);
                }  
            }  
    ID[num][m]=s;
        }  
        num++;
                  
    }  
    while((_00web[l]!=0)&&(num<MAXNUM));   
    return (1);      
}   
void tmp(uchar i)
{
uchar a,b,f;
Init_DS18B20();
Delay_DS18B20(1);
WriteOneChar(0x55);   //匹配
for(f=0;f<8;f++)
{
  WriteOneChar(ID[f]);    //发匹配rom
  printf("%02x ",ID[f]);
}
Delay_DS18B20(15);
WriteOneChar(0xbe);
Delay_DS18B20(15);
a=ReadOneChar();
b=ReadOneChar();
wd=b;
wd<<=8;
wd=wd|a;
if((wd&0xf800)==0xf800)
{
  wd=~wd+1;
  tt=wd*0.625+0.5;
  tt=tt*(-1);
}
else
{
  tt=wd*0.625+0.5;
}
}

void main()
{
uchar i;
search_rom();
UartInit();
printf("num=%d ",num);
//
while(1)   
{   tmpchange();
for(i=0;i<num;i++)
{
  tmp(i);
  printf("temp=%f ",tt);
}
   Delay1000ms();
// Init_DS18B20();
// WriteOneChar(0xCC); //跳过读序号列号的操作   
// WriteOneChar(0x44); //启动温度转换   
// Delay_DS18B20(20);  
// Init_DS18B20();   
// WriteOneChar(0xCC); //跳过读序号列号的操作
// WriteOneChar(0xBE); //读取温度寄存器  
// a=ReadOneChar();    //读低8位
// b=ReadOneChar();    //读高8位
// t=b;   
// t<<=8;  
// t=t|a;
// if((t&0xf800)==0xf800)
// {
//   t = ~t;
//  t = t + 1;
//  flag = 1;
//  tt=t*0.0625*10 + 0.5;
//  tt=tt*(-1);  
//  }  
//   else
//   {
//    tt = t*0.0625*10 + 0.5;
//   }
// printf("temp = %.1f ",tt/10);
// Delay1000ms();
}
}

调试了很长时间,一直出不来,获取ROM序列号的时候存在问题,单个DS18B20能正常读取温度,连上多个之后就不行了,大神们帮帮忙~~~
此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
6条回答
yl616768
2019-03-25 04:33
huo_hu 发表于 2018-5-10 17:17
单线要解决供电问题,所以一定要在空闲时间切换到推挽输出,程序就免看了,看也看不出什么来,你调试一下看看问 ...

嗯,我觉得问题在获取ROM的地方,函数里面可以把搭载的器件个数记录下来和ID号存入二维数组,就是这个ID号的问题,单个器件的时候获取ID号和通过二叉树获取的ID号对不上,目前是这个问题,使用一个温度传感器的时候可以正确获得温度值

一周热门 更多>