找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3314|回复: 2
打印 上一主题 下一主题
收起左侧

DS18B20仿真后,LCD显示的温度和实际模拟温度不一致,跪求大佬指教啊

[复制链接]
楼主
ID:213173 发表于 2019-12-31 11:00 | 显示全部楼层
楼主的程序基本没有问题,关键是参考的程序MCU时钟与楼主选用的不同导致时序误差而产生读取错误。

  1. #include<reg51.h>
  2. #include<intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. #define delayNop(); {_nop_();_nop_();_nop_();_nop_();};

  6. uchar code table[]=" ERROR!!!       ";
  7. uchar code table1[]="xianzaiwendu    ";
  8. uchar code table2[]="Temp=    .  Cent";
  9. uchar code table3[10]="0123456789";

  10. sbit lcd_rs=P1^0;
  11. //sbit lcd_rw=P1^1;
  12. sbit lcd_en=P2^5;
  13. sbit DQ=P2^2;
  14. uchar num,time;

  15. void DelayUs2x(uchar t)
  16. {   
  17.         while(--t);
  18. }

  19. void delay(uint t)
  20. {
  21. unsigned char n;
  22.    while(t--)
  23.    {
  24.      for(n = 0; n<250; n++)
  25.     {
  26.       _nop_();
  27.       _nop_();
  28.      _nop_();
  29.       _nop_();
  30.     }
  31.    }
  32. }

  33. void write_com(uchar com)    //写命令
  34. {
  35.         //lcd_rw=0;
  36.         //delay(5);
  37.         lcd_rs=0;
  38.         lcd_en=0;
  39.         _nop_();
  40.         _nop_();
  41.         P0=com;
  42.         delayNop();
  43.         lcd_en=1;  
  44.         delay(1);
  45.         lcd_en=0;
  46. }

  47. void write_date(uchar date)      //写数据
  48. {
  49.         //lcd_rw=0;
  50.         // delay(5);
  51.         lcd_rs=1;
  52.         lcd_en=0;
  53.         _nop_();
  54.         _nop_();
  55.        
  56.         P0=date;        
  57.         delayNop();
  58.         lcd_en=1;                                                         
  59.         delay(1);
  60.         lcd_en=0;               
  61. }

  62. void init()       //初始化函数
  63. {
  64.         // dula=0;
  65.         // wela=0;
  66.         lcd_en=0;  //可以试试不加这一句看结果怎样
  67.         write_com(0x38);
  68.         write_com(0x0c);
  69.         write_com(0x06);
  70.         write_com(0x01);
  71. }

  72. uchar init_DS18bB20()
  73. {
  74.         bit flag;
  75.         DQ=1;                                          //人为拉高
  76.         DelayUs2x(5);   //稍做延时                       //稍微延时6US;
  77.         DQ=0;                                                        //认为拉低
  78.         DelayUs2x(200); //精确延时 大于 480us 小于960us
  79.         DelayUs2x(200);
  80.         DQ=1;                                                                   //被上拉电阻拉高        (仿真里面没有上拉,有没有都需要人为拉高)
  81.         DelayUs2x(50); //15~60us 后 接收60-240us的存在脉冲                         // 延时60US检测
  82.         flag=DQ;                                                                //这时又被DS18B20拉低,
  83.         DelayUs2x(25); //稍作延时返回                   //延时600US检测时间
  84.         return flag;                     //返回0表示存在
  85. }

  86. void Write_Byte(uchar dat)                 //写一个字节,单片机向DS18B20写命令,确定DS18B20的工作方法之类的
  87. {
  88.         unsigned char i=0;
  89.         for (i=0; i<8; i++)
  90.         {
  91.                 DQ =1;         // 先将数据线拉高
  92.                 _nop_();             //等待一个机器周期         
  93.                 DQ=0;          //将数据线从高拉低时即启动写时序      
  94.                 DQ=dat&0x01;   //利用与运算取出要写的某位二进制数据,
  95.                 //并将其送到数据线上等待DS18B20采样        
  96.                 DelayUs2x(25);        
  97.                 //延时约30us,DS18B20在拉低后的约15~60us期间从数据线上采样
  98.                 DQ=1;          //释放数据线,也就是被上拉电阻拉高,反正就是要把这个口释放,然后来执行下一个命令                    
  99. //                for(time=0;time<1;time++)
  100. //                ;//延时3us,两个写时序间至少需要1us的恢复期
  101.                 dat>>=1;       //将dat中的各二进制位数据右移1位
  102.         }
  103.         DelayUs2x(25);
  104.          //稍作延时,给硬件一点反应时间
  105. }

  106. uchar Read_Byte()
  107. {
  108.         uchar i=0;
  109.         uchar dat;//用来储存读出的一个字节,默认为0
  110.         for(i=0;i<8;i++)
  111.         {
  112.                 DQ=1;
  113.                 _nop_();
  114.                 DQ=0;        //读命令一定得是低电平
  115.                 dat>>=1;   //读取数据是从高位开始读,dat默认是0,也就是0000 0000,
  116.                 //  这是下标是指向最高位的,所以得先右移一位让出一个位置
  117.                 _nop_();        //需要>1US;
  118.                 DQ=1;                //又被上拉电阻拉高
  119. //                for(time=0;time<2;time++);
  120.                 if(DQ==1)                   //由DQ发送的信号来决定,发送的是高电平还是低电平
  121.                 dat|=0x80;           //高电平就或0x80,1000 0000
  122.                 else
  123.                 dat|=0x00;         //低电平就或,0x00
  124.                 DelayUs2x(25);//延时10US左右,因为需要在15US内完成读取
  125.         }                                 
  126.         return dat;
  127. }

  128. void Readyread()//做好读温度准备。。。。可以加在主函数里面,但是分出来比较清晰明了
  129. {
  130.         init_DS18bB20();
  131.         Write_Byte(0xcc);        //跳过读序号
  132.         Write_Byte(0x44);   //启动温度转换
  133.         for(time=0;time<100;time++);
  134.         init_DS18bB20();           //再初始化一下
  135.         Write_Byte(0xcc);  //跳过读序号
  136.         Write_Byte(0xbe);  //都温度寄存器,前两个分别是温度的,低,高位
  137. }

  138. void display()                                                //显示第一行说明
  139. {
  140.         write_com(0x80);
  141.         for(num=0;num<16;num++)
  142.         {
  143.                 write_date(table[num]);
  144.                 //        delay(1);
  145.         }  
  146.         while(1);
  147. }

  148. void display1()                                        //显示第二行说明
  149. {
  150.         write_com(0x80);
  151.         for(num=0;num<16;num++)
  152.         {
  153.                 write_date(table1[num]);
  154.                 //        delay(1);
  155.         }
  156. }

  157. void display2()
  158. {
  159.         write_com(0x80+0x40);
  160.         for(num=0;num<16;num++)
  161.         {
  162.                 write_date(table2[num]);
  163.                 //delay(1);
  164.         }
  165. }
  166.                                                 
  167. void display_temp(uchar x)          //显示温度整数部分
  168. {
  169.         uchar bai,shi,ge;
  170.         bai=x/100;
  171.         shi=(x%100)/10;
  172.         ge=x%10;
  173.         write_com(0x80+0x46);
  174.         write_date(table3[bai]);
  175.         write_date(table3[shi]);
  176.         write_date(table3[ge]);
  177. }

  178. void display1_temp(uchar x)          //显示温度小数部分
  179. {
  180.         write_com(0x80+0x4a);
  181.         write_date(table3[x]);
  182. }
  183. void main()
  184. {
  185.         uchar TL;//储存暂存器的温度最高位
  186.         uchar TH;//储存暂存器的温度最低位
  187.         uchar TN; //储存温度整数部分
  188.         uchar TD; //储存温度小数部分
  189.         init();
  190.         if(init_DS18bB20()==1)
  191.         display();
  192.         display1();
  193.         display2();
  194.         while(1)
  195.         {
  196.                 Readyread();
  197.                 TL=Read_Byte();
  198.                 TH=Read_Byte();
  199.                 TN=TH*16+TL/16;      //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16
  200.                 //这样得出的是温度的整数部分,小数部分被丢弃了
  201.                 TD=(TL%16)*10/16;    //计算温度的小数部分,将余数乘以10再除以16取整,
  202.                 //这样得到的是温度小数部分的第一位数字(保留1位小数)
  203.                
  204.                 display_temp(TN);
  205.                 display1_temp(TD);
  206.                 _nop_(); _nop_();
  207.         }       
  208. }
复制代码



回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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