找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4867|回复: 3
收起左侧

[求助]ds18b20数字温度计测得温度时对时错

[复制链接]
ID:34421 发表于 2012-4-24 14:31 | 显示全部楼层 |阅读模式

大家好!我自己动手做了一个数字温度计。用的是STC12C2052AD单片机,而温度传感器用的是DS18B20,12M晶振,用C语言写(移植)的程序,但是现在温度可以测出来,只是显示有时是对的,有是错的。规律是:显示正确温度2-3秒,跳成850约一秒,然后又显示正确温度。对这个现象,我真是百思不得其解,如果是时序的问题,那为什么可以测得正确的温度?

 

还有,资料上说STC12系列的单片机是不分频的,那是不是说比如我用12M的晶振,那么执行一条指令的时间不再是1us,而是1/12  us?

 

 

DS18B20是数字传感器,读出的是一个16bit的数据,前5bit表示符号,中间八位表示温度的整数部分,我是把中间8位取出来,然后用分离出百、十、个位,送到数码管显示,刚开始用定时器中断扫描数码管,但因这个传感器对时序要求很严格,便改用了软件延时,可是用定时器与用软件延时效果是一样的都是对错对错循还。以下是我的程序,请论坛高手多多指点,在下感激不尽!

 

附件是原理图。

(程序可以显示正确的温度,只是会跳动)

 

 

 

#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;          //百位,十位,个位,小数
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};                   //小数部分直接查表


void main()
{
 ow_reset();
 write_byte(0xcc);             //Skip ROM
 write_byte(0x44);           //发转换命令 
            
 while(1)
     {
       work_temp(read_temp());
  
       displays();   
 
 }
 

}


void ow_reset(void)      //复位
{
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 复位成功,继续下一步
 } 
   delay(45);            //延时500 us
   presence=~DQ;         
}
DQ=1;                  //拉高电平      

}

 

 

/****************DS18B20写命令函数************************/
//向1-WIRE 总线上写1个字节
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字节函数************************/
//从总线上取1个字节
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();                  //总线复位
  delay(200);
  write_byte(0xcc);            //发命令
  write_byte(0x44);            //发转换命令
  ow_reset(); 
  delay(1);
  write_byte(0xcc);            //发命令
  write_byte(0xbe);
  temp_data[0]=read_byte();    //读温度值的第字节
  delay(3);
  temp_data[1]=read_byte();    //读温度值的高字节
  temp=temp_data[1];
  temp<<=8;                                               
  temp=temp|temp_data[0];      // 两字节合成一个整型变量。
  return(temp);                 //返回温度值
}

 


/****************温度数据处理函数************************/

//二进制高字节的低半字节和低字节的高半字节组成一字节,这个
//字节的二进制转换为十进制后,就是温度值的百、十、个位值,而剩
//下的低字节的低半字节转化成十进制后,就是温度值的小数部分

/********************************************************/
work_temp(uint tem)
{
 uchar n=0;
 if(tem>6348)                        // 温度值正负判断
 {
  tem=65536-tem;
  n=1;
 }
 x=tem&0x0f;            // 取小数部分的值     

 wendu=tem>>4;             // 取中间八位,即整数部分的值
 chuli(wendu);   
 if(n)
  b=0x0b;      //负温度时最高位显示"-"
 
}


void delay(uint t)
{     t=t*12;                                //stc12系列单片机不分频,乘以8-12时,延时约10us
  for (;t>0;t--);
}

 

 

void delayms(uint ms)        
{
 ms=120*2*ms;     //取这个参数显示比较稳定(数码管不闪烁,也有较高亮度)
 for(;ms>0;ms--)
 ;
}

 

 

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

 

 P1=disdu[g];

 P1^7=0;      //点亮小数点
 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;
}

回复

使用道具 举报

ID:1 发表于 2012-4-24 14:38 | 显示全部楼层

也不是是1/12  us ,实际的速度你得把c语言反汇编以后再对照stc的指令周期表 才知道了.

回复

使用道具 举报

ID:34421 发表于 2012-4-24 14:51 | 显示全部楼层
嗯 ,但为什么测得的温度会跳动呢?而且是一半是对的,一半是错的。我调节过那个读取温度的频率,但都会出同样 的错。硬件电路是在覆铜板上用刀刻的。现在才知道做好硬件才是个开始,程序研究好些日子了,昨天调试到可以显温度,一直找不到跳 动 的原因,我试图将读出的高字节和低字节分别送出显示,都有跳 动,也就是说,我从传感器里读出的数就是一个跳动的。有没有可能是出温度的那一部分出了错,使读的数错位了呢?还是它正在转换又接到读的命令,而没有对1820读忙状态呢?
回复

使用道具 举报

ID:39301 发表于 2012-4-27 09:54 | 显示全部楼层
顶一下,学习一下!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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