找回密码
 立即注册

QQ登录

只需一步,快速开始

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

各位大神,DS18B20读取温度,加上CRC校验后,温度值不正确,帮忙看看问题出在哪?

[复制链接]
ID:814785 发表于 2021-5-11 13:23 | 显示全部楼层 |阅读模式
程序如下:
  1. #include "reg52.h"
  2. #include "intrins.h"
  3. #define uint unsigned int
  4. #define uchar unsigned char
  5. sbit _RD=P2^6;
  6. sbit _WR=P2^5;
  7. sbit _EN=P2^7;
  8. sbit DQ=P3^7;
  9. uchar code table[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39};
  10. uchar  code CrcTable [256]={
  11. 0,  94, 188,  226,  97,  63,  221,  131,  194,  156,  126,  32,  163,  253,  31,  65,
  12. 157,  195,  33,  127,  252,  162,  64,  30,  95,  1,  227,  189,  62,  96,  130,  220,
  13. 35,  125,  159,  193,  66,  28,  254,  160,  225,  191,  93,  3,  128,  222,  60,  98,
  14. 190,  224,  2,  92,  223,  129,  99,  61,  124,  34,  192,  158,  29,  67,  161,  255,
  15. 70,  24,  250,  164,  39,  121,  155,  197,  132,  218,  56,  102,  229,  187,  89,  7,
  16. 219,  133, 103,  57,  186,  228,  6,  88,  25,  71,  165,  251,  120,  38,  196,  154,
  17. 101,  59, 217,  135,  4,  90,  184,  230,  167,  249,  27,  69,  198,  152,  122,  36,
  18. 248,  166, 68,  26,  153,  199,  37,  123,  58,  100,  134,  216,  91,  5,  231,  185,
  19. 140,  210, 48,  110,  237,  179,  81,  15,  78,  16,  242,  172,  47,  113,  147,  205,
  20. 17,  79,  173,  243,  112,  46,  204,  146,  211,  141,  111,  49,  178,  236,  14,  80,
  21. 175,  241, 19,  77,  206,  144,  114,  44,  109,  51,  209,  143,  12,  82,  176,  238,
  22. 50,  108,  142,  208,  83,  13,  239,  177,  240,  174,  76,  18,  145,  207,  45,  115,
  23. 202,  148, 118,  40,  171,  245,  23,  73,  8,  86,  180,  234,  105,  55,  213, 139,
  24. 87,  9,  235,  181,  54,  104,  138,  212,  149,  203,  41,  119,  244,  170,  72,  22,
  25. 233,  183,  85,  11,  136,  214,  52,  106,  43,  117,  151,  201,  74,  20,  246,  168,
  26. 116,  42,  200,  150,  21,  75,  169,  247,  182,  232,  10,  84,  215,  137,  107,  53};
  27. uchar flag=0;                //负显标志,为0时表示温度高于零度,为1时,表示温度低于0度
  28. uchar *p;
  29. uchar  temp_buff[9]; //存储读取的字节,read scratchpad为9字节,read rom ID为8字节
  30. uchar id_buff[8];
  31. /**********************************************************************
  32. 函数功能:微秒级延时子函数
  33. 入口参数:设置延时时长
  34. 说明:12MHz晶振下,n为1时,延时约14us
  35. 时间:2019年08月09日
  36. **********************************************************************/
  37. void delayus(uint n)
  38. {
  39.         while(--n);
  40. }
  41. /**********************************************************************
  42. 函数功能:毫秒级延时子函数
  43. 入口参数:设置延时时长
  44. 说明:12MHz晶振下,z为1时,延时约1ms
  45. 时间:2019年08月09日
  46. **********************************************************************/
  47. void delayms(uint z)
  48. {
  49.         uint x,y;
  50.         for(x=z;x>0;x--)
  51.                 for(y=122;y>0;y--);
  52. }
  53. //**************************************DS18B20驱动*****************************************************
  54. void dsreset(void)    //18B20复位,初始化函数
  55. {
  56.   DQ=0;
  57.   delayus(100);
  58.   DQ=1;
  59.   delayus(20);
  60. }
  61. void Write_Byte(uchar com)
  62. {
  63.         uchar i;
  64.         for(i=0;i<8;i++)
  65.         {
  66.                 DQ=0;
  67.                 DQ=com&0x01;
  68.                 delayus(20);
  69.                 DQ=1;
  70.                 com>>=1;
  71.         }
  72. }
  73. uchar Read_Byte(void)
  74. {
  75.          uchar i,dat=0;
  76.         DQ=1;
  77.         _nop_();
  78.         for(i=0;i<8;i++)
  79.         {
  80.                 DQ=0;
  81.                 dat>>=1;
  82.                 DQ=1;
  83.                 _nop_();
  84.                 _nop_();
  85.                 _nop_();
  86.                 _nop_();
  87.                 if(DQ)
  88.                         dat|=0x80;
  89.                 else
  90.                         dat|=0x00;
  91.                 delayus(80);
  92.                 DQ=1;
  93.         }
  94.     return(dat);
  95. }
  96. void read_bytes(uchar j)
  97. {
  98.         uchar i;
  99.         for(i=0;i<j;i++)
  100.         {
  101.                 *p=Read_Byte();
  102.                 p++;
  103.         }
  104. }
  105. uchar Temp_CRC(uchar j)
  106. {
  107.         uchar i,crc=0;
  108.         for(i=0;i<j;i++)
  109.                 crc=CrcTable[crc^temp_buff[i]];
  110.         return (crc);
  111. }
  112. void ReadID(void)
  113. {
  114.         dsreset();
  115.         Write_Byte(0x33);
  116.         read_bytes(8);
  117. }
  118. uint Read_Temp()
  119. {
  120.         uint temp;
  121.         read_bytes(9);
  122.         if(Temp_CRC(9)==0)
  123.         {
  124.                 if(flag==1)
  125.                 {
  126.                         temp=(~temp)+1;
  127.                         temp=temp*0.625+0.5;
  128.                 }
  129.                 else
  130.                         temp=temp*0.625+0.5;
  131.         }
  132.         return temp;
  133. }
  134. void Config18b20()                //重新配置报警限定值和分辨率
  135. {
  136.         dsreset();
  137.         Write_Byte(0xcc);
  138.         Write_Byte(0x4e);
  139.         Write_Byte(0x19);
  140.         Write_Byte(0x1a);
  141.         Write_Byte(0x7f);
  142.         dsreset();
  143.         Write_Byte(0xcc);
  144.         Write_Byte(0x48);
  145.         dsreset();
  146.         Write_Byte(0xcc);
  147.         Write_Byte(0xb8);
  148. }
  149. uint Temp_value()
  150. {
  151.         uint temp;
  152.         p=id_buff;
  153.         ReadID();
  154.         Config18b20();
  155.         dsreset();
  156.         Write_Byte(0xcc);
  157.         Write_Byte(0x44);
  158.         dsreset();
  159.         Write_Byte(0xcc);
  160.         Write_Byte(0xbe);
  161.         temp=Read_Temp();
  162.         return temp;
  163. }
  164. //**************************************液晶驱动*****************************************************
  165. bit Busy()
  166. {
  167.         bit busy;
  168.         _RD=0;
  169.         _WR=1;
  170.         _EN=1;
  171.         delayus(5);
  172.         busy=(bit)(P0&0x80);
  173.         _EN=0;
  174.         return busy;
  175. }
  176. void Wcmd(uchar com)                        //写命令
  177. {
  178.         while(Busy());                                //判忙
  179.         _RD=0;
  180.         _WR=0;                                                //RD和WR为0时,在EN下降沿执行写指令码,在EN下降沿之前,要将指令送入P0
  181.         _EN=0;
  182.         delayus(5);
  183.         P0=com;
  184.         delayus(5);
  185.         _EN=1;
  186.         delayus(5);
  187.         _EN=0;
  188. }
  189. void Wdat(uchar dat)                        //写数据命令
  190. {
  191.         while(Busy());                                //判忙
  192.         _RD=1;
  193.         _WR=0;                                                //RD为1,WR为0时,在EN下降沿执行写数据,在EN下降沿之前,要将数据送入P0
  194.         _EN=0;
  195.         delayus(5);
  196.         P0=dat;
  197.         delayus(5);
  198.         _EN=1;
  199.         delayus(5);
  200.         _EN=0;
  201. }
  202. void Lcd_Init()                                //液晶初始化
  203. {
  204.         Wcmd(0x38);
  205.         Wcmd(0x0c);
  206.         Wcmd(0x06);
  207.         Wcmd(0x01);        
  208. }

  209. void display0(uchar row,uchar line,uchar signal)                        //row为行位参数,line为列为参数
  210. {
  211.         static uchar a=0;

  212.         if(row==1)
  213.                 a=0x80;
  214.         if(row==2)
  215.                 a=0xc0;
  216.         a=a+line-1;
  217.         Wcmd(a);
  218.         Wdat(signal);
  219. }
  220. void display1(uint temp,uchar hum)
  221. {
  222.         uchar g1,g2,g3,g4,j0,j1,j2;
  223.         g1=temp/1000;
  224.         g2=temp%1000/100;
  225.         g3=temp%100/10;
  226.         g4=temp%10;

  227.         j0=hum/100;
  228.         j1=hum%100/10;
  229.         j2=hum%10;

  230.         display0(1,2,'T');
  231.         display0(1,3,'E');
  232.         display0(1,4,'M');
  233.         display0(1,5,'P');
  234.         display0(1,6,':');
  235.         if(flag==0)
  236.                 display0(1,7,table[g1]);                                //不显示负
  237.         else
  238.                 display0(1,7,'-');                                                //显示负
  239.         display0(1,8,table[g2]);
  240.         display0(1,9,table[g3]);
  241.         display0(1,10,'.');
  242.         display0(1,11,table[g4]);
  243.         display0(1,12,0xdf);
  244.         display0(1,13,0x43);
  245. }
  246. main()
  247. {
  248.         Lcd_Init();
  249.         display0(1,1,0x20);
  250.         while(1)
  251.         {
  252.                 display1(Temp_value(),100);
  253.                 delayms(500);
  254.         }
  255. }
复制代码

回复

使用道具 举报

ID:584814 发表于 2021-5-11 14:41 | 显示全部楼层
楼主真的懂 CRC 是搞么子的
回复

使用道具 举报

ID:814785 发表于 2021-5-11 16:28 | 显示全部楼层
man1234567 发表于 2021-5-11 14:41
楼主真的懂 CRC 是搞么子的

好像是CRC校验没通过,拔掉DS18B20,显示的还是A62.5
回复

使用道具 举报

ID:592807 发表于 2021-5-12 08:34 | 显示全部楼层
man1234567 发表于 2021-5-11 14:41
楼主真的懂 CRC 是搞么子的

你可以理解成你要发送的数据是A,然后有个公式是 Y = A*K,然后实际发送的数据就是AY,单片机接受数据后会将验证Y/A的值是否等于K,如果数据在传输过程中出了错。任何一个数据出错都会导致验证失败
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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