找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4870|回復(fù): 3
打印 上一主題 下一主題
收起左側(cè)

[求助]ds18b20數(shù)字溫度計(jì)測得溫度時(shí)對時(shí)錯(cuò)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:34421 發(fā)表于 2012-4-24 14:31 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式

大家好!我自己動(dòng)手做了一個(gè)數(shù)字溫度計(jì)。用的是STC12C2052AD單片機(jī),而溫度傳感器用的是DS18B20,12M晶振,用C語言寫(移植)的程序,但是現(xiàn)在溫度可以測出來,只是顯示有時(shí)是對的,有是錯(cuò)的。規(guī)律是:顯示正確溫度2-3秒,跳成850約一秒,然后又顯示正確溫度。對這個(gè)現(xiàn)象,我真是百思不得其解,如果是時(shí)序的問題,那為什么可以測得正確的溫度?

 

還有,資料上說STC12系列的單片機(jī)是不分頻的,那是不是說比如我用12M的晶振,那么執(zhí)行一條指令的時(shí)間不再是1us,而是1/12  us?

 

 

DS18B20是數(shù)字傳感器,讀出的是一個(gè)16bit的數(shù)據(jù),前5bit表示符號,中間八位表示溫度的整數(shù)部分,我是把中間8位取出來,然后用分離出百、十、個(gè)位,送到數(shù)碼管顯示,剛開始用定時(shí)器中斷掃描數(shù)碼管,但因這個(gè)傳感器對時(shí)序要求很嚴(yán)格,便改用了軟件延時(shí),可是用定時(shí)器與用軟件延時(shí)效果是一樣的都是對錯(cuò)對錯(cuò)循還。以下是我的程序,請論壇高手多多指點(diǎn),在下感激不盡!

 

附件是原理圖。

(程序可以顯示正確的溫度,只是會(huì)跳動(dòng))

 

 

 

#include <reg2051.h>
#include<intrins.h>

#define  uchar unsigned char
#define  uint  unsigned int

 

void ow_reset(void);
void delay(uint t);
void write_byte(uchar val);
uint read_temp();
uchar read_byte(void);
work_temp(uint tem);
void chuli(uchar wd); 
void delayms(uint ms);        
void displays();

 

uchar wei=0;
uint temp=0;
uchar wendu=0;
uchar b,s,g,x;          //百位,十位,個(gè)位,小數(shù)
sbit d4=P3^2;         //位選信號端
sbit d3=P3^4;
sbit d2=P3^3;
sbit d1=P3^5;

 

sbit DQ=P3^7;    //接傳感 器

uchar code disdu[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};                            //段選列表
//共陽LED段碼表        "0"  "1"  "2"  "3"  "4"  "5"  "6"  "7"  "8"  "9" "不亮" "-" 
uchar data temp_data[2]={0x00,0x00};             //讀出溫度暫放

uchar code ditab[16]=
{0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x08,0x09,0x09};                   //小數(shù)部分直接查表


void main()
{
 ow_reset();
 write_byte(0xcc);             //Skip ROM
 write_byte(0x44);           //發(fā)轉(zhuǎn)換命令 
            
 while(1)
     {
       work_temp(read_temp());
  
       displays();   
 
 }
 

}


void ow_reset(void)      //復(fù)位
{
char presence=1;
while(presence)
{
  while(presence)
   {
    DQ=1;_nop_();_nop_();//從高拉倒低
 DQ=0;                                       
 delay(50);           //550 us
 DQ=1;                                        
 delay(6);            //66 us
 presence=DQ;  //presence=0 復(fù)位成功,繼續(xù)下一步
 } 
   delay(45);            //延時(shí)500 us
   presence=~DQ;         
}
DQ=1;                  //拉高電平      

}

 

 

/****************DS18B20寫命令函數(shù)************************/
//向1-WIRE 總線上寫1個(gè)字節(jié)
void write_byte(uchar val)
{ 
  uchar i;
  for(i=8;i>0;i--)
  {
   DQ=1;_nop_();_nop_();                 //從高拉倒低
   DQ=0;_nop_();_nop_();_nop_();_nop_();  //5 us
   DQ=val&0x01;                           //最低位移出
   delay(6);                              //66 us
   val=val/2;                             //右移1位
   }
   DQ=1;
   delay(1);
}


/****************DS18B20讀1字節(jié)函數(shù)************************/
//從總線上取1個(gè)字節(jié)
uchar read_byte(void)
{
uchar i;
uchar value=0;
for(i=8;i>0;i--)
{
  DQ=1;_nop_();_nop_();
  value>>=1;
  DQ=0;_nop_();_nop_();_nop_();_nop_();        //4 us
  DQ=1;_nop_();_nop_();_nop_();_nop_();        //4 us
  if(DQ)value|=0x80;
  delay(6);                                     //66 us
}
DQ=1;
return(value);
}

 

uint read_temp()
{
  ow_reset();                  //總線復(fù)位
  delay(200);
  write_byte(0xcc);            //發(fā)命令
  write_byte(0x44);            //發(fā)轉(zhuǎn)換命令
  ow_reset(); 
  delay(1);
  write_byte(0xcc);            //發(fā)命令
  write_byte(0xbe);
  temp_data[0]=read_byte();    //讀溫度值的第字節(jié)
  delay(3);
  temp_data[1]=read_byte();    //讀溫度值的高字節(jié)
  temp=temp_data[1];
  temp<<=8;                                               
  temp=temp|temp_data[0];      // 兩字節(jié)合成一個(gè)整型變量。
  return(temp);                 //返回溫度值
}

 


/****************溫度數(shù)據(jù)處理函數(shù)************************/

//二進(jìn)制高字節(jié)的低半字節(jié)和低字節(jié)的高半字節(jié)組成一字節(jié),這個(gè)
//字節(jié)的二進(jìn)制轉(zhuǎn)換為十進(jìn)制后,就是溫度值的百、十、個(gè)位值,而剩
//下的低字節(jié)的低半字節(jié)轉(zhuǎn)化成十進(jìn)制后,就是溫度值的小數(shù)部分

/********************************************************/
work_temp(uint tem)
{
 uchar n=0;
 if(tem>6348)                        // 溫度值正負(fù)判斷
 {
  tem=65536-tem;
  n=1;
 }
 x=tem&0x0f;            // 取小數(shù)部分的值     

 wendu=tem>>4;             // 取中間八位,即整數(shù)部分的值
 chuli(wendu);   
 if(n)
  b=0x0b;      //負(fù)溫度時(shí)最高位顯示"-"
 
}


void delay(uint t)
{     t=t*12;                                //stc12系列單片機(jī)不分頻,乘以8-12時(shí),延時(shí)約10us
  for (;t>0;t--);
}

 

 

void delayms(uint ms)        
{
 ms=120*2*ms;     //取這個(gè)參數(shù)顯示比較穩(wěn)定(數(shù)碼管不閃爍,也有較高亮度)
 for(;ms>0;ms--)
 ;
}

 

 

void displays()                      //顯示溫度
{
 P1=disdu[ditab[x]];
 d1=0;
 delayms(5);
 d1=1;

 

 P1=disdu[g];

 P1^7=0;      //點(diǎn)亮小數(shù)點(diǎn)
 d2=0;
 delayms(5);
 d2=1;

 

 P1=disdu;
 d3=0;
 delayms(5);
 d3=1;

 

 P1=disdu;
 d4=0;
 delayms(5);
 d4=1;
} 

 

 


void chuli(uchar wd) 
{
 b=wd/100;
 s=wd%100/10;
 g=wd%100%10;
 if(b==0)
  b=10;
 if(s==0)
  s=10;
}

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:1 發(fā)表于 2012-4-24 14:38 | 只看該作者

也不是是1/12  us ,實(shí)際的速度你得把c語言反匯編以后再對照stc的指令周期表 才知道了.

回復(fù)

使用道具 舉報(bào)

板凳
ID:34421 發(fā)表于 2012-4-24 14:51 | 只看該作者
嗯 ,但為什么測得的溫度會(huì)跳動(dòng)呢?而且是一半是對的,一半是錯(cuò)的。我調(diào)節(jié)過那個(gè)讀取溫度的頻率,但都會(huì)出同樣 的錯(cuò)。硬件電路是在覆銅板上用刀刻的,F(xiàn)在才知道做好硬件才是個(gè)開始,程序研究好些日子了,昨天調(diào)試到可以顯溫度,一直找不到跳 動(dòng) 的原因,我試圖將讀出的高字節(jié)和低字節(jié)分別送出顯示,都有跳 動(dòng),也就是說,我從傳感器里讀出的數(shù)就是一個(gè)跳動(dòng)的。有沒有可能是出溫度的那一部分出了錯(cuò),使讀的數(shù)錯(cuò)位了呢?還是它正在轉(zhuǎn)換又接到讀的命令,而沒有對1820讀忙狀態(tài)呢?
回復(fù)

使用道具 舉報(bào)

地板
ID:39301 發(fā)表于 2012-4-27 09:54 | 只看該作者
頂一下,學(xué)習(xí)一下!
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表