搜索
bottom↓
回复: 23

ds18b20测温初学,测试失败啦麻烦大家给我看看

[复制链接]

出0入0汤圆

发表于 2012-5-19 13:10:49 | 显示全部楼层 |阅读模式
本帖最后由 yesno 于 2012-5-19 15:29 编辑

#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char  
#define uint unsigned int
sbit dula=P2^6;  
sbit wela=P2^7;
sbit DQ=P2^2;
uint temp;
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};          //0-9数字
void delay (uint x)                 //延时函数        
{        
uchar i;
        while(x--)
        for(i=0; i<120; i++);
        }
void delay1(uint a)                 //延时函数
{   
while(--a);
}
void disp(uchar num)  //显示函数
{
  uchar shi,ge;   
shi=num/10;   
ge=num%10;  
dula=1;  
P0=table[shi];
  dula=0;  
P0=0xff;   
wela=1;
  P0=0xfe;  
wela=0;   
delay(5);   
dula=1;  
P0=table[ge];  
dula=0;   
P0=0xff;  
wela=1;  
P0=0xfd;   
wela=0;   
delay(5);
}          
void init_18b20() //  初始化
{
DQ=1;
delay1(8);
DQ=0;
delay1(90);
DQ=1;
_nop_();
_nop_();
delay1(100);
DQ=1;
}        
void write(uchar dat)          //写字节
{
uchar i;        
for(i=0; i<8; i++)        
        {
                DQ=0;        
        DQ=dat&0x01;        
        delay1(5);                
        DQ=1;        
        dat>>=1;                
        }                
      delay1(4);
}  
uchar read()                   //读字节
{
uchar i, dat=0;
DQ=1;  
_nop_();  
for(i=0; i<8; i++)
{
   DQ=0;  
   _nop_();
   _nop_();
    dat>>=1;
    DQ=1;
    _nop_();
    _nop_();  
    if(DQ)
    dat|=0x80;
    delay1(30);
    DQ=1;
  }  
return dat;
}
uchar read_tu()                          //  温度转换
{
uchar a,b;
init_18b20();
delay1(100);
write(0xcc);
write(0x44);
init_18b20();
write(0xcc);
write(0xbe);
a=read();
b=read();
b<<=4;
b+=(a&0xf0)>>4;
return b;
}   
void main()                                                 //主函数
{
delay(30);
        while(1)
        {
        temp=read_tu;
        disp(temp);        
         }
}


这个初学仔细检查啦视乎没错,可是下载到板子里面就不行啦。其他的情况也没什么就是温度没反应,数码管就是显示70,任凭我怎么触摸传感器都是没反应既不升温也不降温。



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2012-5-19 13:12:55 | 显示全部楼层
楼主,关注你的delay函数,无符号整形的形参,延时时间和你预想的不同的!

可以看你编译时的汇编文件。

出0入0汤圆

 楼主| 发表于 2012-5-19 13:21:18 | 显示全部楼层
無智 发表于 2012-5-19 13:12
楼主,关注你的delay函数,无符号整形的形参,延时时间和你预想的不同的!

可以看你编译时的汇编文件。 ...

怎么看啊。汇编看不懂诶

出0入0汤圆

发表于 2012-5-19 13:54:34 | 显示全部楼层
哪款单片机

出0入0汤圆

发表于 2012-5-19 14:12:10 | 显示全部楼层
  1. void delay_15us( uchar times )
  2. {
  3.         do
  4.         {
  5.                 _nop_ ();
  6.                 _nop_ ();
  7.                 _nop_ ();
  8.                 _nop_ ();
  9.                 _nop_ ();
  10.                 _nop_ ();
  11.                 _nop_ ();
  12.                 _nop_ ();
  13.                 _nop_ ();
  14.                 _nop_ ();
  15.                 _nop_ ();
  16.                 _nop_ ();
  17.                 _nop_ ();
  18.                
  19.                 times--;       
  20.         }while(times);
  21. }

  22. //初始化函数
  23. void DS18B20_reset(void)
  24. {
  25.         uchar x=0;
  26.        
  27.         DQ = 1; //DQ复位
  28.         delay_15us (3); //稍做延时
  29.         DQ = 0; //单片机将DQ拉低
  30.         delay_15us(33); //精确延时 大于 480us          33           大于10即可
  31.         DQ = 1; //拉高总线
  32.         delay_15us(6);        //等待大于60us       有无都可以
  33.         x = DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
  34.         delay_15us(6);
  35. }

  36. //读一个字节
  37. uchar DS18B20_read(void)
  38. {
  39.         uchar i=0;
  40.         uchar dat = 0;
  41.        
  42.         for (i=0;i<8;i++)
  43.         {
  44.                 DQ = 1;                        //高电平
  45.                 _nop_();_nop_();//延时2us
  46.                 DQ = 0;                 //低电平 开始时间片
  47.                 dat>>=1;
  48.                 DQ = 1;                 //高电平 DS18B20开始输出
  49.                 if(DQ)                       
  50.                 {
  51.                         dat|=0x80;        //如果是高电平就在最高位写入1,低电平则保留原来的0
  52.                 }
  53.                 delay_15us(2);        //延时30us
  54.         }
  55.        
  56.         return(dat);
  57. }

  58. //写一个字节
  59. void DS18B20_write(uchar dat)
  60. {
  61.         uchar i=0;
  62.        
  63.         for (i=8; i>0; i--)
  64.         {
  65.                 DQ = 0;
  66.                 delay_15us(1);
  67.                 DQ = dat&0x01;
  68.                 delay_15us(2);
  69.                 DQ = 1;
  70.                 dat>>=1;
  71.         }
  72. }

  73. void DS18B20_convert( void )
  74. {
  75.         DS18B20_reset();
  76.         DS18B20_write(0xCC); // 跳过读序号列号的操作
  77.         DS18B20_write(0x44); // 启动温度转换
  78. }

  79. //读取温度
  80. uint get_temperature(void)
  81. {
  82.         uchar tempL=0;
  83.         uchar tempH=0;
  84.         uint t=0;
  85.         DS18B20_convert();
  86.         DS18B20_reset();
  87.         DS18B20_write(0xCC); //跳过读序号列号的操作
  88.         DS18B20_write(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  89.         tempL=DS18B20_read();
  90.         tempH=DS18B20_read();

  91.         t = (tempH*256 + tempL)*0.625+0.5;
  92.         return(t);
  93. }
复制代码

出0入0汤圆

 楼主| 发表于 2012-5-19 14:41:47 | 显示全部楼层
BXAK 发表于 2012-5-19 13:54
哪款单片机

51单片机啊

出0入0汤圆

发表于 2012-5-19 14:51:47 | 显示全部楼层
yesno 发表于 2012-5-19 14:41
51单片机啊


具体型号,因为有些新51和旧51指令速度不同,delay延时就不通用了,
如果你的是STC 1T系列,就用这贴的就可以:STC 1T DS18B20通用操作模块,正 / 负温度,适应晶振:1 ~ 45MHz
如果是AT89C52的话,你把工程发上来,今天比较有空,帮你改改

出0入0汤圆

 楼主| 发表于 2012-5-19 14:57:17 | 显示全部楼层
BXAK 发表于 2012-5-19 14:51
具体型号,因为有些新51和旧51指令速度不同,delay延时就不通用了,
如果你的是STC 1T系列,就用这贴的就 ...

stc89c52rc

出0入0汤圆

 楼主| 发表于 2012-5-19 15:03:43 | 显示全部楼层
BXAK 发表于 2012-5-19 14:51
具体型号,因为有些新51和旧51指令速度不同,delay延时就不通用了,
如果你的是STC 1T系列,就用这贴的就 ...

你的那个贴真复杂啊,看的头晕。你就帮我改改这个程序吧。

出0入0汤圆

 楼主| 发表于 2012-5-19 15:09:44 | 显示全部楼层
BXAK 发表于 2012-5-19 14:51
具体型号,因为有些新51和旧51指令速度不同,delay延时就不通用了,
如果你的是STC 1T系列,就用这贴的就 ...

有qq吗发个qq具体说说

出0入0汤圆

发表于 2012-5-19 15:12:33 | 显示全部楼层
yesno 发表于 2012-5-19 15:09
有qq吗发个qq具体说说

把工程传上来帮你改改,还有晶振是多少

出0入0汤圆

 楼主| 发表于 2012-5-19 15:15:50 | 显示全部楼层
BXAK 发表于 2012-5-19 15:12
把工程传上来帮你改改,还有晶振是多少

怎么上传工程啊??就是上面的代码啊。

出0入0汤圆

发表于 2012-5-19 15:24:48 | 显示全部楼层
yesno 发表于 2012-5-19 15:15
怎么上传工程啊??就是上面的代码啊。


编译环境是用keil还是TKStudio,晶振多少,懒得新建工程,你把这个项目的文件夹压缩成rar或者zip,然后上传附件

出0入0汤圆

 楼主| 发表于 2012-5-19 15:47:40 | 显示全部楼层
BXAK 发表于 2012-5-19 15:24
编译环境是用keil还是TKStudio,晶振多少,懒得新建工程,你把这个项目的文件夹压缩成rar或者zip,然后上 ...

rar在上面啊

出0入0汤圆

 楼主| 发表于 2012-5-19 16:09:38 | 显示全部楼层
BXAK 发表于 2012-5-19 15:24
编译环境是用keil还是TKStudio,晶振多少,懒得新建工程,你把这个项目的文件夹压缩成rar或者zip,然后上 ...

测试的怎么样啦

出0入0汤圆

发表于 2012-5-19 16:58:06 | 显示全部楼层
yesno 发表于 2012-5-19 13:21
怎么看啊。汇编看不懂诶

51单片机是8位的系统,当一个变量用32位定义时,编译器会对该变量做一系列寄存器操作。
你期望延时100us,但实际上会长很多。

出0入0汤圆

发表于 2012-5-19 17:15:02 | 显示全部楼层

//**********************************************************************************
//延时函数, 对于12MHz时钟, 例z=10,则大概延时10ms.  

void delay(uint z)
{
    uint x,y;
    for(x=z;x>0;x--);
        for(y=124;y>0;y--);  
}     

//**********************************************************************************

//**********************************************************************************
//初始化DS18B20
//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动
void dsreset(void)        
{  //对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us
    uint i;
    ds=0;
    i=103;    //拉低约800us, 符合协议要求的480us以上
    while(i>0)i--;
    ds=1;    //产生一个上升沿, 进入等待应答状态
    i=4;
    while(i>0)i--;
}
//**********************************************************************************

//**********************************************************************************
//向DS18B20读取一位数据
//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,
//之后DS18B20则会输出持续一段时间的一位数据
bit tempreadbit(void)
{  
    uint i;
    bit dat;
    ds=0;
    i++;      //i++起延迟作用  延时约8us, 符合协议要求至少保持1us
    ds=1;
    i++;i++;  //延时约16us, 符合协议要求的至少延时15us以上
    dat=ds;
    i=8;
    while(i>0)i--; //延时约64us, 符合读时隙不低于60us要求
    return(dat);
}
//**********************************************************************************

//**********************************************************************************
//读取一字节数据, 通过调用tempreadbit()来实现
uchar tempread(void)      
{
    uchar i,j,dat;
    dat=0;
    for(i=1;i<=8;i++)
    {
        j=tempreadbit();
        dat=(j<<7)|(dat>>1);  //读出的数据最低位在最前面,这样刚好一个字节在dat里   
    }
    return(dat);
}
//**********************************************************************************

//**********************************************************************************
//向DS18B20写入一字节数据
void tempwritebyte(uchar dat)   
{
    uint  i;
    uchar j;
    bit testb;
    for(j=1;j<=8;j++)
    {
        testb=dat&0x01;
        dat=dat>>1;
        if(testb)    //写"1", 将ds拉低15us后, 在15us~60us内将ds拉高, 即完成写1
        {
            ds=0;
            i++;i++;  //拉低约16us, 符号要求15~60us内
            ds=1;
            i=8;while(i>0)i--;  //延时约64us, 符合写时隙不低于60us要求
        }
        else      //写"0", 将ds拉低60us~120us
        {
            ds=0;  
            i=8;while(i>0)i--;  //拉低约64us, 符号要求      
            ds=1;
            i++;i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了   
        }   
    }
}
//**********************************************************************************

//**********************************************************************************
//向DS18B20发送温度转换命令
void tempchange(void)   
{
    dsreset();   //初始化DS18B20, 无论什么命令, 首先都要发起初始化
    delay(1);    //延时1ms, 因为DS18B20会拉低ds 60~240us作为应答信号
    tempwritebyte(0xcc);   //写跳过读ROM指令
    tempwritebyte(0x44);   //写温度转换指令
}
//**********************************************************************************

//**********************************************************************************
//向DS18B20发送读取数据命令  获取当前温度值
uint tmp()  
{
    float tt;
  //  int tt;
    uchar low,high;
    dsreset();
    delay(1);
    tempwritebyte(0xcc); //写入跳过序列号命令字 Skip Rom
    tempwritebyte(0xbe); //写入读取数据令字 Read Scratchpad
    //连续读取两个字节数据
    low =tempread();   //读低8位
    high=tempread();   //读高8位
    temp=high;   //高8位赋予temp
    temp<<=8;    //将高低两个字节合成一个整形变量 temp为16位 高8位左移8位 低8位补0
    temp=temp|low;  //高低8位相或=temp为16位=高8位+低8位

    xs=low&0x0f; //低4位为小数部分
    tt=temp>>4; //整数部分
  //  temp=tt*100+xs*100/16;  

     temp=tt*10+((((xs*5)>>2)+1)>>1);
  //   **************************************
   //y=(((x*5)>>2)+1)>>1;
//等效y=((x*5)/4+1)/2;
//再等效y=((x*20)/16+1)/2;
//y=2*(x*10/16+0.5)/2;
//实际上y=x*10/16+0.5;  //+0.5为 四舍五入
//  **********************************************
  // tt=temp*0.0625;  //DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度   
// temp = tt * 100 + (temp > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5  
//   temp=tt*100;  //将它放大100倍, 使显示时可显示小数点后两位(t=11.0625,计算得temp = 1106, 即11.06 度)
    return temp; //temp是整型
}
//**********************************************************************************

//**********************************************************************************
//显示函数
void display(uint t)
{
     unsigned char a1=0,a2=0,a3=0,a4=0;        //临时变量
     static int k=0;   
      
      a1=t/1000;     //取t的千位//
      a2=t%1000/100;//取t的百位//
      a3=t%100/10; //取t的十位//
      a4=t%10;    //取t的个位//

      if     (k==0){A1=1;A2=0;A3=0;A4=0;P0=yima[a1];}
      else if(k==1){A1=0;A2=1;A3=0;A4=0;P0=yima[a2];}
      else if(k==2){A1=0;A2=0;A3=1;A4=0;P0=yima[a3];}
      else if(k==3){A1=0;A2=0;A3=0;A4=1;P0=yima[a4];}   

      k++;
      if(k>3) k=0;
}      

出0入0汤圆

发表于 2012-5-19 17:24:45 | 显示全部楼层

*******************************************************************************************
//读取温度
unsigned char ReadTemperature(void)
{
unsigned char a=0;
unsigned char b=0;
long int t=0;
Init_DS18B20();
WriteOneChar(0xCC); // 跳过读序号列号的操作
WriteOneChar(0x44); // 启动温度转换
delay(200);
Init_DS18B20();
WriteOneChar(0xCC); //跳过读序号列号的操作
WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
a=ReadOneChar();
b=ReadOneChar();

b<<=4;
b+=(a&0xf0)>>4; //b=b+(a&0xf0)>>4
t=b;
return(t);

******************************************************************************************

出0入0汤圆

发表于 2012-5-19 17:29:51 | 显示全部楼层
yesno 发表于 2012-5-19 16:09
测试的怎么样啦

官网提供的

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-5-19 17:52:57 | 显示全部楼层
18B20:
    测量数据以16位带符号位扩展的二进制补码形式存放
    单片机读取温度,一次读2字节16位,读完将低11位的二进制转化为十进制后乘0.0625即为实际温度,只

需要判断11位即可
还需要判断温度正负:前5位为符号位,1为负,0为正
1)前5位为1时,读取温度为负值,实际温度=测得数值需要取反加1再乘0.0625
  -55  ——11111 10010010000——低11位取反011 0110 1111(十进制879)——加1(880)——乘0.0625——

实际温度-880*0.0625 (11111为负)   
2)前5位为0时,读取温度为正值,实际温度=测得数值乘0.0625
  +125 ——00000 11111010000——低11位十进制为2000 ——2000*0.0625=125  (00000位正)

//移位原理:
//用10进制来理解,如果把123456这个数右移4位,是不是得到12?也就是除以10的4次方10000得到的(因为是整型,小数部分被舍去了)。
//二进制右移4位,自然是除以2的4次方16了。
//因0.0625=1/16 所以T*0.0625=T/16=T>>4
//若除4096则是右移12位 因2的12次方=4096

*************************************************************************************
AVR优化算法:
x为小数部分0-15之间的数,y为最后输出的数,为什么偷笑?因为只要10个周期。
y=(((x*5)>>2)+1)>>1;   //小数输出 10T
y=(((x*5)>>2)+1)>>1;
等效y=((x*5)/4+1)/2;
再等效y=((x*20)/16+1)/2;
实际上y=x*10/16;
由于定义的类型都是整数,单片机计算完后是取整数部份,所以要进行四舍五入
y=x*10/16+0.5;
所以y=2*(x*10/16+0.5)/2;
y=(x*20/16+1)/2;
*****************************************************

出0入0汤圆

发表于 2012-5-19 19:00:21 | 显示全部楼层
yao1 发表于 2012-5-19 17:52
18B20:
    测量数据以16位带符号位扩展的二进制补码形式存放
    单片机读取温度,一次读2字节16位,读完 ...

哪那么复杂

bit    P_N;
unsigned char   msb,lsb;

/*****************************************************
函数:温度转换命令 + 读取计算保存
要求:在主程序中循环调用此函数,调用速度随意
比如:P_N = 0,msb = 20,lsb = 4,即+20.4℃
          P_N = 1,msb = 14,lsb = 3,即-14.3℃
*****************************************************/
void Conversion_Update_Temp(void)
{       
    …………
       
    a = DS18B20_ReadByte();             //读温度低字节           
    b = DS18B20_ReadByte();             //读温度高字节
               
    P_N = (bit)( b & 0x80 );            //P_N=1负温,P_N=0正温
    if ( P_N ) {    b = 255 - b;  if( a )a = 256 - a;  else b++; }   //负温计算方法1:65536减去后,按正温计算
    …………                                                                           //负温计算方法2:取反加1后,按正温计算                                      

    msb = (b<<4) | (a>>4);       //温度整数                                      相当于 (b<<8 + a)*0.0625
    //lsb = ((a&0x0F)*10)/16;     //温度小数保留1位(不带四舍五入)相当于 ( (b<<8 + a)*0.0625*10) %10
    lsb = ((a&0x0F)*10+8)/16;    //温度小数保留1位(带四舍五入)  相当于 ( (b<<8 + a)*0.0625*10 +5 ) %10
}

出0入0汤圆

 楼主| 发表于 2012-5-19 19:29:57 | 显示全部楼层
BXAK 发表于 2012-5-19 19:00
哪那么复杂

bit    P_N;

忘记打括号啦

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2012-5-19 20:49:12 | 显示全部楼层
yesno 发表于 2012-5-19 19:29
忘记打括号啦

编译没报错或者警告?

出0入0汤圆

 楼主| 发表于 2012-5-19 22:13:20 | 显示全部楼层
BXAK 发表于 2012-5-19 20:49
编译没报错或者警告?

很多网友也觉得奇怪都说为什么没报警,问题是它就是没报警,郁闷
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 02:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表