找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3348|回复: 15
收起左侧

51单片机DS18B20温度传感器在LCD1602显示有误,想请教下大佬问题出在哪,小白实在....

  [复制链接]
ID:770162 发表于 2022-1-10 10:23 | 显示全部楼层 |阅读模式
#include<reg51.h>
#include<stdio.h>
#include<intrins.h>   
unsigned int  Real_temp;
unsigned int t;
/***************************************************/
sbit rs =P3^0;       //
sbit rw = P3^1;
sbit e =P3^5;   //
sbit D1=P0^0;
sbit D2=P0^1;
sbit D3=P0^2;
sbit D4=P0^3;
sbit D5=P0^4;
sbit D6=P0^5;
sbit D7=P0^6;
sbit D8=P0^7;
/**********************************************DS18B20****************************************************/
sbit DQ=P1^2;        //定义DS18b20的管脚

/*****延时子程序*****/
void delay(unsigned int t)
{
        for(;t>0;t--);
}

/*****初始化DS18B20*****/
unsigned char Init_DS18B20(void)
{
  unsigned char x=0;
  DQ = 1;      //DQ复位
  delay(8);    //稍做延时
  DQ = 0;      //单片机将DQ拉低
  delay(80);   //精确延时,大于480us
  DQ = 1;      //拉高总线
  delay(8);
  x = DQ;      //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  delay(4);
  return x;
}

/*****读一个字节*****/
unsigned char ReadOneChar(void)
{
  unsigned char i=0;
  unsigned char dat = 0;
  for (i=8;i>0;i--)
  {
    DQ = 0;     // 给脉冲信号
    dat>>=1;
    DQ = 1;     // 给脉冲信号
    if(DQ)
            dat|=0x80;
        delay(4);
  }
  return(dat);
}

/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    DQ = 0;
    DQ = dat&0x01;
        delay(4);
    DQ = 1;
    dat>>=1;
  }
  delay(4);
}

/*****读取温度*****/
int ReadTemperature(void)
{
          unsigned char a=0;
          unsigned char b=0;
          unsigned int t=0;
          t=Init_DS18B20();
          if(t) return Real_temp;
          WriteOneChar(0xCC);  //跳过读序号列号的操作
          WriteOneChar(0x44);  //启动温度转换
          t=Init_DS18B20();
          if(t) return Real_temp;
          WriteOneChar(0xCC);  //跳过读序号列号的操作
          WriteOneChar(0xBE);  //读取温度寄存器
          a=ReadOneChar();     //读低8位
          b=ReadOneChar();     //读高8位
          t=b;
          t<<=8;
          t=t|a;
          if(t<=0||t>0x900)
        return Real_temp;
        t=t*0.625+0.5;
          return(t);
}

/*****************************************LCD1602*************************************************/
void write_com(unsigned char com)  //命令函数
{
        e=0;
        rs=0;
        rw=0;
        P0=com;
        delay(25);
        e=1;
        delay(100);
        e=0;
}
void write_data(unsigned char dat)         //写入数据
{
        e=0;
        rs=1;
        rw=0;
        P0=dat;
        delay(25);
        e=1;
        delay(100);
        e=0;       
}
void write_string(unsigned char hang,unsigned char add,unsigned char *p)  //改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下write_string(1,5,"ab cd ef");
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        while(1)
        {
                if(*p == '\0')  break;
                write_data(*p);
                p++;
        }       
}
void write_zifu(unsigned char hang,unsigned char add,unsigned char date)   //LCD1602上显示特定的字符
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(date);       
}
void write_sfm3_18B20(unsigned char hang,unsigned char add,unsigned int date)  //LCD1602上显示两位十进制数
{
        if(hang==1)   
                write_com(0x80+add);
        else
                write_com(0x80+0x40+add);
        write_data(0x30+date/100%10);
        write_data(0x30+date/10%10);
        write_data(0x30+date%10);       
}
void init_1602()           //LCD1602初始化设置
{
        write_com(0x38);       
        write_com(0x0c);
        write_com(0x06);
        delay(1000);
        write_string(1,0,"sd:                 ");       
        write_string(2,0,"wd:                 ");
        write_zifu(1,12,0xdf);  //显示度       
        write_zifu(2,12, 0xdf);  //显示度       
}
/*****************************************主函数*************************************************/
void main()
{         Init_DS18B20();
    init_1602();
    while(1)
         {
         ReadTemperature();
         write_sfm3_18B20(2,4,t);
         }
}         
回复

使用道具 举报

ID:770162 发表于 2022-1-10 10:30 | 显示全部楼层
显示的结果就是全为000,参照网上其他程序后不知道是不是理解有误,理解成LCD最后一个显示函数能转换读取出的温度值。
屏幕截图 2022-01-10 102541.png
回复

使用道具 举报

ID:213173 发表于 2022-1-10 16:30 | 显示全部楼层
1218829816 发表于 2022-1-10 10:30
显示的结果就是全为000,参照网上其他程序后不知道是不是理解有误,理解成LCD最后一个显示函数能转换读取出 ...

无标题.jpg
  1. #include<reg51.h>
  2. #include<stdio.h>
  3. #include<intrins.h>   
  4. unsigned int Real_temp;
  5. unsigned int t;
  6. /***************************************************/
  7. sbit rs =P3^0;       //
  8. sbit rw = P3^1;
  9. sbit e =P3^5;   //
  10. sbit D1=P0^0;
  11. sbit D2=P0^1;
  12. sbit D3=P0^2;
  13. sbit D4=P0^3;
  14. sbit D5=P0^4;
  15. sbit D6=P0^5;
  16. sbit D7=P0^6;
  17. sbit D8=P0^7;
  18. /**********************************************DS18B20****************************************************/
  19. sbit DQ=P1^2;        //定义DS18b20的管脚

  20. /*****延时子程序*****/
  21. void delay(unsigned int t)
  22. {
  23.         for(;t>0;t--);
  24. }

  25. /*****初始化DS18B20*****/
  26. unsigned char Init_DS18B20(void)
  27. {
  28.   unsigned char x=0;
  29.   DQ = 1;      //DQ复位
  30.   delay(8);    //稍做延时
  31.   DQ = 0;      //单片机将DQ拉低
  32.   delay(80);   //精确延时,大于480us
  33.   DQ = 1;      //拉高总线
  34.   delay(8);
  35.   x = DQ;      //稍做延时后,如果x=0则初始化成功,x=1则初始化失败
  36.   delay(4);
  37.   return x;
  38. }

  39. /*****读一个字节*****/
  40. unsigned char ReadOneChar(void)
  41. {
  42.   unsigned char i=0;
  43.   unsigned char dat = 0;
  44.   for (i=8;i>0;i--)
  45.   {
  46.     DQ = 0;     // 给脉冲信号
  47.     dat>>=1;
  48.     DQ = 1;     // 给脉冲信号
  49.     if(DQ)
  50.             dat|=0x80;
  51.         delay(4);
  52.   }
  53.   return(dat);
  54. }

  55. /*****写一个字节*****/
  56. void WriteOneChar(unsigned char dat)
  57. {
  58.   unsigned char i=0;
  59.   for (i=8; i>0; i--)
  60.   {
  61.     DQ = 0;
  62.     DQ = dat&0x01;
  63.         delay(4);
  64.     DQ = 1;
  65.     dat>>=1;
  66.   }
  67.   delay(4);
  68. }

  69. /*****读取温度*****/
  70. int ReadTemperature(void)
  71. {
  72.         unsigned char a=0;
  73.         unsigned char b=0;
  74.         unsigned int t=0;
  75.         t=Init_DS18B20();
  76.         if(t) return Real_temp;
  77.         WriteOneChar(0xCC);  //跳过读序号列号的操作
  78.         WriteOneChar(0x44);  //启动温度转换
  79.         t=Init_DS18B20();
  80.         if(t) return Real_temp;
  81.         WriteOneChar(0xCC);  //跳过读序号列号的操作
  82.         WriteOneChar(0xBE);  //读取温度寄存器
  83.         a=ReadOneChar();     //读低8位
  84.         b=ReadOneChar();     //读高8位
  85.         t=b;
  86.         t<<=8;
  87.         t=t|a;
  88.         if(t<=0||t>0x630)
  89.         return Real_temp;
  90.         t=t*0.625+0.5;
  91.         return (t);
  92. }


  93. /*****************************************LCD1602*************************************************/
  94. void write_com(unsigned char com)  //命令函数
  95. {
  96.         e=0;
  97.         rs=0;
  98.         rw=0;
  99.         P0=com;
  100.         delay(25);
  101.         e=1;
  102.         delay(100);
  103.         e=0;
  104. }
  105. void write_data(unsigned char dat)         //写入数据
  106. {
  107.         e=0;
  108.         rs=1;
  109.         rw=0;
  110.         P0=dat;
  111.         delay(25);
  112.         e=1;
  113.         delay(100);
  114.         e=0;        
  115. }
  116. void write_string(unsigned char hang,unsigned char add,unsigned char *p)  //改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下write_string(1,5,"ab cd ef");
  117. {
  118.         if(hang==1)   
  119.         write_com(0x80+add);
  120.         else
  121.                 write_com(0x80+0x40+add);
  122.         while(1)
  123.         {
  124.                 if(*p == '\0')  break;
  125.                 write_data(*p);
  126.                 p++;
  127.         }        
  128. }
  129. void write_zifu(unsigned char hang,unsigned char add,unsigned char date)   //LCD1602上显示特定的字符
  130. {
  131.         if(hang==1)   
  132.                 write_com(0x80+add);
  133.         else
  134.                 write_com(0x80+0x40+add);
  135.         write_data(date);        
  136. }
  137. void write_sfm3_18B20(unsigned char hang,unsigned char add,unsigned int date)  //LCD1602上显示两位十进制数
  138. {
  139.         if(hang==1)   
  140.                 write_com(0x80+add);
  141.         else
  142.                 write_com(0x80+0x40+add);
  143.         write_data(0x30+date/100%10);
  144.         write_data(0x30+date/10%10);
  145.         write_data('.');  
  146.         write_data(0x30+date%10);        
  147. }
  148. void init_1602()           //LCD1602初始化设置
  149. {
  150.         write_com(0x38);        
  151.         write_com(0x0c);
  152.         write_com(0x06);
  153.         delay(1000);
  154.         write_string(1,0,"sd:                 ");        
  155.         write_string(2,0,"wd:                 ");
  156.         write_zifu(1,8,0xdf);  //显示度        
  157.         write_zifu(1,9,'C');
  158.         write_zifu(2,8,0xdf);  //显示度        
  159.         write_zifu(2,9,'C');
  160. }
  161. /*****************************************主函数*************************************************/
  162. void main()
  163. {
  164.         Init_DS18B20();
  165.         init_1602();
  166.         while(1)
  167.         {
  168.                 write_sfm3_18B20(2,4,ReadTemperature());
  169.         }
  170. }
复制代码



回复

使用道具 举报

ID:8222 发表于 2022-1-10 17:04 | 显示全部楼层
18B20读写时,总线拉低后没有延时15微秒就读写,造成读写失败。

评分

参与人数 1黑币 +21 收起 理由
1218829816 + 21 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:161164 发表于 2022-1-10 18:05 | 显示全部楼层
unsigned char ReadOneChar(void)
{
  unsigned char i=0;
  unsigned char dat = 0;
  for (i=8;i>0;i--)
  {
    DQ = 1;     // 给脉冲信号<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<先拉高
    DQ = 0;     // 给脉冲信号
    dat>>=1;
    DQ = 1;     // 给脉冲信号
    if(DQ)
            dat|=0x80;
        delay(4);
  }
  return(dat);
}

/*****写一个字节*****/
void WriteOneChar(unsigned char dat)
{
  unsigned char i=0;
  for (i=8; i>0; i--)
  {
    DQ = 1;     // 给脉冲信号<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<先拉高
    DQ = 0;
    DQ = dat&0x01;
        delay(4);
    DQ = 1;
    dat>>=1;
  }
  delay(4);
}


/*****************************************主函数*************************************************/
void main()
{   Init_DS18B20();
    init_1602();
    while(1)
    {
        t = ReadTemperature();//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<取得反回值
        write_sfm3_18B20(2,4,t);
    }
}



你的ReadTemperature();中已有一个区域变数t
混肴了全域变数t
其实全域变数t由始致终都是0
LCD才会显示000


命名变数时不要贪方便只用单字
特别是全域变数

评分

参与人数 1黑币 +30 收起 理由
1218829816 + 30 赞一个!

查看全部评分

回复

使用道具 举报

ID:770162 发表于 2022-1-10 18:08 | 显示全部楼层
温xyz 发表于 2022-1-10 17:04
18B20读写时,总线拉低后没有延时15微秒就读写,造成读写失败。

大佬,18B20读写字节部分在总线拉低后都进行了延时,但还是一样,是不是还有其他问题。
回复

使用道具 举报

ID:770162 发表于 2022-1-10 18:10 | 显示全部楼层
lkc8210 发表于 2022-1-10 18:05
unsigned char ReadOneChar(void)
{
  unsigned char i=0;

可以了,太谢谢大佬了,我再去多了解下区域变数和全域变数
回复

使用道具 举报

ID:711951 发表于 2022-6-5 10:50 来自触屏版 | 显示全部楼层
楼主是怎么解决的呀
回复

使用道具 举报

ID:161164 发表于 2022-6-5 15:07 | 显示全部楼层
wqy12345 发表于 2022-6-5 10:50
楼主是怎么解决的呀

参考我5楼的回贴
回复

使用道具 举报

ID:64283 发表于 2022-6-5 22:36 | 显示全部楼层
分两步来做,每一步,查看18B20能不能读出数据
第二步,LCD1602以膛能正常显示
这两个驱动解决后,你需要将18B20读出来的数值化为相应的字符,显示到1602相应的位置上
就是这么简单
回复

使用道具 举报

ID:61140 发表于 2022-6-7 21:26 | 显示全部楼层
1218829816 发表于 2022-1-10 18:10
可以了,太谢谢大佬了,我再去多了解下区域变数和全域变数

应该叫局部变量和全局变量
回复

使用道具 举报

ID:1033546 发表于 2022-6-9 17:38 来自触屏版 | 显示全部楼层
lkc8210 发表于 2022-6-5 15:07
参考我5楼的回贴

那如果是LCD屏直接不显示应该是怎么办呀?
回复

使用道具 举报

ID:1049557 发表于 2023-5-13 20:43 | 显示全部楼层
来了来了噗 发表于 2022-6-9 17:38
那如果是LCD屏直接不显示应该是怎么办呀?

请问解决了吗
回复

使用道具 举报

ID:1064915 发表于 2023-7-18 17:02 | 显示全部楼层
在我的51学习板上,却是运行正常
回复

使用道具 举报

ID:40039 发表于 2023-8-27 18:42 | 显示全部楼层
  t=t*0.625+0.5;
这在单片机上无法运算呀?
回复

使用道具 举报

ID:1092048 发表于 2023-8-27 21:27 | 显示全部楼层
P3_5在温度读取期间应该置1,不然就会读取出错
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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