找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4136|回复: 6
收起左侧

单片机数码管显示ds18b20温度值不正常

[复制链接]
ID:481844 发表于 2019-3-20 08:31 | 显示全部楼层 |阅读模式
本帖最后由 心灵的尘埃 于 2019-3-20 08:34 编辑

#include <reg52.h>
#include <intrins.h>


#define uchar unsigned char
#define uint unsigned int
sbit du26=P2^6;//数码管段选
sbit we27=P2^7;//数码管位选
sbit DS=P2^2;//温度传感器
uchar sum;//将温度值送到数码管显示
uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9数码管段表
uchar code smgwei[]={0xfe,0xfd,0xfb};       //1~3数码管位表


void we(uchar z) //位选
{
        P0=z;
        we27=1;
        we27=0;        
}


void du(uchar z)   //段选
{         
        P0=z;
        du26=1;
        du26=0;        
}
void display(uchar z) //三个数码管显示
{
        static uchar wei;
        switch(wei)
        {
                case 0:we(smgwei[wei]);du(led[z/100]);break;
                case 1:we(smgwei[wei]);du(led[z%100/10]|0x80);break;
                case 2:we(smgwei[wei]);du(led[z%10]);break;
        }
        wei++;
        if(wei==3)
                wei=0;
}


void timer0int() interrupt 1 //定时器,定时5ms
{
        TH0=(65535-5000)/256;
        TL0=(65535-5000)%256;
        display(sum);         
}
void delay_us(uchar us)        //延时函数
{
         while(us--);
}


//单总线初始化时序         
bit ds_init()
{
        bit i;
        DS=1;
        _nop_();
        DS=0;
        delay_us(75);//拉低总线499.45us,总线上的温度传感器将会被全部复位
        DS=1;//释放总线
        delay_us(4);//延时37.95us,等待温度传感器发回存在信号
        i=DS;
        delay_us(20);//延时141.95us,读取温度传感器存在的时间
        DS=1;
        _nop_();
        return (i);
}
//写一个字节
void write_byte(uchar dat)
{
        uchar i;
        for(i=0;i<8;i++)
        {
                DS=0;
                _nop_(); //产生写时序
                DS=dat&0x01;
                delay_us(10);//延时76.95us
                DS=1;//释放总线准备下一次数据的写入
                _nop_();
                dat>>=1;
        }
}
//读一个字节
uchar read_byte()
{
        uchar i,j,dat;
        for(i=0;i<8;i++)
        {
                DS=0;
                _nop_();//产生读时序
                DS=1;
                _nop_();//释放总线
                j=DS;
                delay_us(10);//76.95us
                DS=1;
                _nop_();
                dat=(j<<7)|(dat>>1);
        }
        return (dat);
}  
void main()
{        
        uint i;
        uchar L,M;
        EA=1;
        ET0=1;
        TR0=1;
        TMOD=0X01;
        TH0=(65535-5000)/256;
        TL0=(65535-5000)%256;


        
        while(1)           
        {
                ds_init();//初始化温度传感器
                write_byte(0xcc);//发送跳跃ROM指令
                write_byte(0x44);//发送温度转换指令
                ds_init();//初始化温度传感器
                write_byte(0xcc);//发送跳跃ROM指令
                write_byte(0xbe);//读取温度传感器暂存器的值
                L=read_byte();
                M=read_byte();
                i=M;
                i<<=8;
                i|=L;          //将读出来的数据合并存到i中
                i=i*0.625*10+0.5;
        i=sum;
                                
        } 求问题出在哪里,谢谢!!!      
}


回复

使用道具 举报

ID:443783 发表于 2019-3-20 09:50 | 显示全部楼层
没的图纸 怎么帮?
回复

使用道具 举报

ID:437981 发表于 2019-3-20 13:48 | 显示全部楼层
ds18b20是单总线通信,它对时序要求非常高,你可能需要检查你的延迟
回复

使用道具 举报

ID:164602 发表于 2019-3-20 14:38 | 显示全部楼层
试试我的程序:
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit DS=P2^2;   
uint temp;        
uchar flag1;        
sbit dula=P2^6;
sbit wela=P2^7;
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
                        0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code table1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,
                        0x87,0xff,0xef};

void delay(uint count)   
{
  uint i;
  while(count)
  {
    i=200;
    while(i>0)
    i--;
    count--;
  }
}


void dsreset(void)  
{
  uint i;
  DS=0;                              
  i=103;                               
  while(i>0)i--;
  DS=1;                               
  i=4;                                       
  while(i>0)i--;

}

bit tmpreadbit(void)   
{
   uint i;
   bit dat;
   DS=0;i++;      
   DS=1;i++;i++;
   dat=DS;
   i=8;while(i>0)i--;
   return (dat);
}

uchar tmpread(void)
{
  uchar i,j,dat;
  dat=0;
  for(i=1;i<=8;i++)
  {
    j=tmpreadbit();
    dat=(j<<7)|(dat>>1);
  }
  return(dat);
}

void tmpwritebyte(uchar dat)  
{
  uint i;
  uchar j;
  bit testb;
  for(j=1;j<=8;j++)
  {
    testb=dat&0x01;
    dat=dat>>1;
    if(testb)   
    {
      DS=0;
      i++;i++;
      DS=1;
      i=8;while(i>0)i--;
    }
    else
    {
      DS=0;     
      i=8;while(i>0)i--;
      DS=1;
      i++;i++;
    }

  }
}

void tmpchange(void)
{
  dsreset();
  delay(1);
  tmpwritebyte(0xcc);
  tmpwritebyte(0x44);

}

uint tmp()            
{
  float tt;
  uchar a,b;
  dsreset();
  delay(1);
  tmpwritebyte(0xcc);
  tmpwritebyte(0xbe);
  a=tmpread();
  b=tmpread();
  temp=b;
  temp<<=8;         
  temp=temp|a;
  tt=temp*0.0625;
  temp=tt*10+0.5;
  return temp;
}

void readrom()      
{
  uchar sn1,sn2;
  dsreset();
  delay(1);
  tmpwritebyte(0x33);
  sn1=tmpread();
  sn2=tmpread();
}


void delay10ms()      
  {
    uchar a,b;
    for(a=10;a>0;a--)
      for(b=60;b>0;b--);
   }

void display(uint temp)               
{
   uchar A1,A2,A2t,A3,ser;
   ser=temp/10;
   SBUF=ser;
   A1=temp/100;
   A2t=temp%100;
   A2=A2t/10;
   A3=A2t%10;
   dula=0;
   P0=table[A1];       
   dula=1;
   dula=0;

   wela=0;
   P0=0xfe;
   wela=1;
   wela=0;
   delay(1);

   dula=0;
   P0=table1[A2];               
   dula=1;
   dula=0;

   wela=0;
   P0=0xfd;
   wela=1;
   wela=0;
   delay(1);

   P0=table[A3];       
   dula=1;
   dula=0;

   P0=0xfb;
   wela=1;
   wela=0;
   delay(1);
}


void main()
{
uchar a;
  do
  {
    tmpchange();
  

for(a=100;a>0;a--)
  {   display(tmp());
  }
  }                while(1);
}

回复

使用道具 举报

ID:491577 发表于 2019-3-20 21:24 | 显示全部楼层
数码管显示语句有问题:
                case 0:we(smgwei[wei]);du(led[z/100]);break;
                case 1:we(smgwei[wei]);du(led[z%100/10]|0x80);break;
                case 2:we(smgwei[wei]);du(led[z%10]);break;
回复

使用道具 举报

ID:213173 发表于 2019-3-20 21:49 | 显示全部楼层
改为6位数码管显示-55~128度,保留2位小数。 无标题.jpg

  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. /************定义端口*************/
  6. sbit du26=P2^6;//数码管段选
  7. sbit we27=P2^7;//数码管位选
  8. sbit DS=P2^2;//温度传感器
  9. /************定义全局变量*************/
  10. uchar code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9数码管段表
  11. uchar code smgwei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};       //1~6数码管位表
  12. uchar TempData[6]; //存储显示值的全局变量
  13. bit ReadTempFlag;        //读时间标志

  14. /*------------------------------------------------
  15.                   函数声明
  16. ------------------------------------------------*/
  17. void WriteOneChar(uchar dat);        //写入DS18B20一个字节
  18. uchar ReadOneChar(void);                //读取DS18B20一个字节
  19. uint ReadTemperature(void);        //读取DS18B20温度值
  20. bit Init_DS18B20(void);                        //初始化DS18B20
  21. void Display(void);                                        //数码管显示函数
  22. void Init_Timer0(void);                        //定时器初始化
  23. void DelayUs2x(uchar t);                //uS延时函数
  24. void DelayMs(uchar t);                        //mS延时函数
  25. void we(uchar z); //位选
  26. void du(uchar z);   //段选
  27. /*------------------------------------------------
  28.                     主函数
  29. ------------------------------------------------*/
  30. void main()
  31. {                  
  32.         uint temp;
  33.         long tempM;
  34.         bit negative;//负数标志
  35.         uchar TempH,TempL,TempK;
  36.         Init_Timer0();
  37.         TempData[5]=0x39;                //显示C
  38.         while(1)         //主循环
  39.         {
  40.                 if(ReadTempFlag==1)//定时标志
  41.                 {
  42.                         ReadTempFlag=0;
  43.                         temp=ReadTemperature();//读取温度
  44.                         if(temp&0x8000)
  45.                         {
  46.                                 negative=1;                //负号标志
  47.                                 temp=~temp;                //取反加1
  48.                                 temp +=1;
  49.                         }
  50.                         else negative=0;        //正数

  51.                         tempM=temp*0.0625*100;        //换算为10进制温度值再放大100倍
  52.                         TempH=tempM/100;                                //分解出整数值       
  53.                         TempL=tempM%100;                                //分解出小数值
  54.                         TempL=(TempL+TempK)/2+0.5;//小数取两次平均值加四舍五入
  55.                         TempK=TempL;
  56.                        
  57.                         if(negative==1)
  58.                                 TempData[0]=0x40;//显示负号
  59.                         else if(TempH/100==0)//小于100
  60.                                 TempData[0]=0;                                                                                        //百位消隐
  61.                         else
  62.                                 TempData[0]=led[TempH/100];                         //显示百位温度
  63.        
  64.                         if((TempH/100==0)&&((TempH%100)/10==0))
  65.                                 TempData[1]=0;                                                                                        //十位消隐
  66.                         else
  67.                                 TempData[1]=led[(TempH%100)/10];                //显示十位温度
  68.                         TempData[2]=led[(TempH%100)%10]|0x80;//显示个位温度,带小数点
  69.                         TempData[3]=led[TempL/10];                                //显示温度小数1位
  70.                         TempData[4]=led[TempL%10];                                //显示温度小数2位       

  71.                 }
  72.         }
  73. }
  74. void we(uchar z) //位选
  75. {
  76.         P0=z;
  77.         we27=1;
  78.         we27=0;        
  79. }
  80. void du(uchar z)   //段选
  81. {         
  82.         P0=z;
  83.         du26=1;
  84.         du26=0;
  85. }
  86. /*------------------------------------------------
  87.                                 6位动态数码管显示函数
  88. ------------------------------------------------*/
  89. void Display() //6个数码管显示
  90. {
  91.         static uchar wei;
  92.         switch(wei)
  93.         {
  94.                 case 0:we(smgwei[wei]);du(TempData[wei]);break;
  95.                 case 1:we(smgwei[wei]);du(TempData[wei]);break;
  96.                 case 2:we(smgwei[wei]);du(TempData[wei]);break;
  97.                 case 3:we(smgwei[wei]);du(TempData[wei]);break;
  98.                 case 4:we(smgwei[wei]);du(TempData[wei]);break;
  99.                 case 5:we(smgwei[wei]);du(TempData[wei]);break;
  100.         }
  101.         wei++;
  102.         wei%=6;
  103. }

  104. /*------------------------------------------------
  105.             定时器初始化子程序
  106. ------------------------------------------------*/
  107. void Init_Timer0(void)
  108. {
  109.          TMOD |= 0x01;
  110.          TH0=(65536-2000)/256;              //给定初值
  111.          TL0=(65536-2000)%256;
  112.          EA=1;            //总中断打开
  113.          ET0=1;           //定时器中断打开
  114.          TR0=1;           //定时器开关打开
  115. }
  116. /*------------------------------------------------
  117.                  定时器中断子程序
  118. ------------------------------------------------*/
  119. void Timer0_isr(void) interrupt 1
  120. {
  121.         static uint num;
  122.         TH0=(65536-2000)/256;        //重新赋值 2ms
  123.         TL0=(65536-2000)%256;
  124.        
  125.         Display();       // 调用数码管扫描
  126.         num++;
  127.         if(num>=250)        //500ms
  128.         {
  129.                 num=0;
  130.                 ReadTempFlag=1; //读标志位置1
  131.         }
  132. }

  133. /*------------------------------------------------
  134.          2uS延时函数
  135. ------------------------------------------------*/
  136. void DelayUs2x(uchar t)
  137. {   
  138.         while(--t);
  139. }
  140. /*------------------------------------------------
  141.         1mS延时函数
  142. ------------------------------------------------*/
  143. void DelayMs(uchar t)
  144. {
  145.         while(t--)
  146.         {
  147.                 //大致延时1mS
  148.                 DelayUs2x(245);
  149.                 DelayUs2x(245);
  150.         }
  151. }
  152. /*------------------------------------------------
  153.                     18b20初始化
  154. ------------------------------------------------*/
  155. bit Init_DS18B20(void)
  156. {
  157.         bit dat=0;
  158.         DS = 1;                    //DS复位
  159.         DelayUs2x(5);   //稍做延时
  160.         DS = 0;         //单片机将DS拉低
  161.         DelayUs2x(200); //精确延时 大于 480us 小于960us
  162.         DelayUs2x(200);
  163.         DS = 1;        //拉高总线
  164.         DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲
  165.         dat=DS;        //如果x=0则初始化成功, x=1则初始化失败
  166.         DelayUs2x(25); //稍作延时返回
  167.         return dat;
  168. }

  169. /*------------------------------------------------
  170.                     读取一个字节
  171. ------------------------------------------------*/
  172. uchar ReadOneChar(void)
  173. {
  174.         uchar i=0;
  175.         uchar dat = 0;
  176.         for (i=8;i>0;i--)
  177.         {
  178.                 DS = 0; // 给脉冲信号
  179.                 dat>>=1;
  180.                 DS = 1; // 给脉冲信号
  181.                 if(DS)
  182.                 dat|=0x80;
  183.                 DelayUs2x(25);
  184.         }
  185.         return(dat);
  186. }
  187. /*------------------------------------------------
  188.                     写入一个字节
  189. ------------------------------------------------*/
  190. void WriteOneChar(uchar dat)
  191. {
  192.         uchar i=0;
  193.         for(i=8; i>0; i--)
  194.         {
  195.                 DS = 0;
  196.                 DS = dat&0x01;
  197.                 DelayUs2x(25);
  198.                 DS = 1;
  199.                 dat>>=1;
  200.         }
  201.         DelayUs2x(25);
  202. }

  203. /*------------------------------------------------
  204.                     读取温度
  205. ------------------------------------------------*/
  206. uint ReadTemperature(void)
  207. {
  208.         uchar a=0;
  209.         uint b=0;
  210.         uint t=0;
  211.         Init_DS18B20();
  212.         WriteOneChar(0xCC); // 跳过读序号列号的操作
  213.         WriteOneChar(0x44); // 启动温度转换
  214.         DelayMs(10);
  215.         Init_DS18B20();
  216.         WriteOneChar(0xCC); //跳过读序号列号的操作
  217.         WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
  218.         a=ReadOneChar();   //低位
  219.         b=ReadOneChar();   //高位
  220.         b<<=8;
  221.         t=a+b;
  222.         return(t);
  223. }
复制代码



评分

参与人数 1黑币 +6 收起 理由
心灵的尘埃 + 6

查看全部评分

回复

使用道具 举报

ID:383721 发表于 2019-3-21 13:53 | 显示全部楼层
如果是实际电路的话,DS18B20温度转换最少要93.57ms(9位),最多要750ms(12位),之后才能读取到正确的数据,protues仿真就不需要
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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