找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于单片机DS18B20的一些问题想请教大家

[复制链接]
ID:968143 发表于 2021-10-5 00:08 | 显示全部楼层 |阅读模式
想做一温度报警器,烧录到51单片机开发板上可以正常显示,但是到Proteus里其他正常,但温度却无法正常显示,所以想问一下大家

单片机程序代码如下
  1. #include <REGX52.H>
  2. #include "LCD1602.h"
  3. #include "AT24C02.h"
  4. #include "Key.h"
  5. #include "DS18B20.h"
  6. #include "Delay.h"

  7. float T,TShow;
  8. char TLow,THigh;
  9. unsigned char KeyNum;

  10. void main()
  11. {
  12.         DS18B20_ConvertT();
  13.         Delay(1000);
  14.         THigh=AT24C02_ReadByte(0);
  15.         TLow=AT24C02_ReadByte(1);
  16.         LCD_Init();
  17.         LCD_ShowString(1,1,"T:");
  18.         LCD_ShowString(2,1,"TH:");
  19.         LCD_ShowString(2,9,"TL:");
  20.         LCD_ShowSignedNum(2,4,THigh,3);
  21.         LCD_ShowSignedNum(2,12,TLow,3);
  22.         while(1)
  23.         {
  24.                 KeyNum=Key();
  25.                
  26.                 /*温度读取及显示*/
  27.                 DS18B20_ConvertT();
  28.                 T=DS18B20_ReadT();
  29.                 if(T<0)
  30.                 {
  31.                         LCD_ShowChar(1,3,'-');
  32.                         TShow=-T;
  33.                 }
  34.                 else
  35.                 {
  36.                         LCD_ShowChar(1,3,'+');
  37.                         TShow=T;
  38.                 }
  39.                 LCD_ShowNum(1,4,TShow,3);
  40.                 LCD_ShowChar(1,7,'.');
  41.                 LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);
  42.                
  43.                 /*阈值判断及显示*/
  44.                 if(KeyNum)
  45.                 {               
  46.                         if(KeyNum==1)
  47.                         {
  48.                                 THigh++;
  49.                                 if(THigh>125){THigh=125;}
  50.                         }
  51.                         if(KeyNum==2)
  52.                         {
  53.                                 THigh--;
  54.                                 if(THigh<TLow){THigh++;}
  55.                         }
  56.                         if(KeyNum==3)
  57.                         {
  58.                                 TLow++;
  59.                                 if(TLow>THigh){TLow--;}
  60.                         }
  61.                         if(KeyNum==4)
  62.                         {
  63.                                 TLow--;
  64.                                 if(TLow<-55){TLow=-55;}

  65.                         }
  66.                         LCD_ShowSignedNum(2,4,THigh,3);
  67.                         LCD_ShowSignedNum(2,12,TLow,3);
  68.                         AT24C02_WriteByte(0,THigh);
  69.                         Delay(5);
  70.                         AT24C02_WriteByte(1,TLow);
  71.                         Delay(5);
  72.                 }
  73.                 if(T>THigh)
  74.                 {
  75.                         LCD_ShowString(1,13,"OV:H");
  76.                 }
  77.                 else if(T<TLow)
  78.                 {
  79.                         LCD_ShowString(1,13,"OV:L");
  80.                 }
  81.                 else
  82.                 {
  83.                         LCD_ShowString(1,13,"    ");
  84.                 }
  85.         }
  86. }
  87. #define AT24C02_ADDRESS                0xA0


  88. void AT24C02_WriteByte(unsigned char WordAddress,Data)
  89. {
  90.         I2C_Start();
  91.         I2C_SendByte(AT24C02_ADDRESS);
  92.         I2C_ReceiveAck();
  93.         I2C_SendByte(WordAddress);
  94.         I2C_ReceiveAck();
  95.         I2C_SendByte(Data);
  96.         I2C_ReceiveAck();
  97.         I2C_Stop();
  98. }


  99. unsigned char AT24C02_ReadByte(unsigned char WordAddress)
  100. {
  101.         unsigned char Data;
  102.         I2C_Start();
  103.         I2C_SendByte(AT24C02_ADDRESS);
  104.         I2C_ReceiveAck();
  105.         I2C_SendByte(WordAddress);
  106.         I2C_ReceiveAck();
  107.         I2C_Start();
  108.         I2C_SendByte(AT24C02_ADDRESS|0x01);
  109.         I2C_ReceiveAck();
  110.         Data=I2C_ReceiveByte();
  111.         I2C_SendAck(1);
  112.         I2C_Stop();
  113.         return Data;
  114. }

  115. void Delay(unsigned int xms)
  116. {
  117.         unsigned char i, j;
  118.         while(xms)
  119.         {
  120.                         i = 2;
  121.         j = 239;
  122.         do
  123.         {
  124.                 while (--j);
  125.         } while (--i);
  126.                 xms--;
  127.         }
  128. }
  129. #define DS18B20_SKIP_ROM                        0xCC
  130. #define DS18B20_CONVERT_T                        0x44
  131. #define DS18B20_READ_SCRATCHPAD        0xBE

  132. /**
  133.   * @brief  DS18B20开始温度变换
  134.   * @param  无
  135.   * @retval 无
  136.   */
  137. void DS18B20_ConvertT()
  138. {
  139.         OneWire_Init();
  140.         OneWire_SendByte(DS18B20_SKIP_ROM);
  141.         OneWire_SendByte(DS18B20_CONVERT_T);
  142. }

  143. /**
  144.   * @brief  DS18B20读取温度
  145.   * @param  无
  146.   * @retval 温度数值
  147.   */
  148. float DS18B20_ReadT()
  149. {
  150.         unsigned char TLSB,TMSB;
  151.         int Temp;
  152.         float T;
  153.         OneWire_Init();
  154.         OneWire_SendByte(DS18B20_SKIP_ROM);
  155.         OneWire_SendByte(DS18B20_READ_SCRATCHPAD);
  156.         TLSB=OneWire_ReceiveByte();        
  157.         TMSB=OneWire_ReceiveByte();
  158.         Temp=(TMSB<<8)|TLSB;
  159.         T=Temp/16.0;
  160.         return T;
  161. }
  162. sbit I2C_SCL=P2^1;
  163. sbit I2C_SDA=P2^0;

  164. void I2C_Start(void)
  165. {
  166.         I2C_SDA=1;
  167.         I2C_SCL=1;
  168.         I2C_SDA=0;
  169.         I2C_SCL=0;
  170. }

  171. void I2C_Stop(void)
  172. {
  173.         I2C_SDA=0;
  174.         I2C_SCL=1;
  175.         I2C_SDA=1;
  176. }

  177. void I2C_SendByte(unsigned char Byte)
  178. {
  179.         unsigned char i;
  180.         for(i=0;i<8;i++)
  181.         {
  182.                 I2C_SDA=Byte&(0x80>>i);
  183.                 I2C_SCL=1;
  184.                 I2C_SCL=0;
  185.         }
  186. }

  187. unsigned char I2C_ReceiveByte(void)
  188. {
  189.         unsigned char i,Byte=0x00;
  190.         I2C_SDA=1;
  191.         for(i=0;i<8;i++)
  192.         {
  193.                 I2C_SCL=1;
  194.                 if(I2C_SDA){Byte|=(0x80>>i);}
  195.                 I2C_SCL=0;
  196.         }
  197.         return Byte;
  198. }

  199. void I2C_SendAck(unsigned char AckBit)
  200. {
  201.         I2C_SDA=AckBit;
  202.         I2C_SCL=1;
  203.         I2C_SCL=0;
  204. }

  205. unsigned char I2C_ReceiveAck(void)
  206. {
  207.         unsigned char AckBit;
  208.         I2C_SDA=1;
  209.         I2C_SCL=1;
  210.         AckBit=I2C_SDA;
  211.         I2C_SCL=0;
  212.         return AckBit;
  213. }
复制代码
仿真电路如下
1.png
回复

使用道具 举报

ID:968143 发表于 2021-10-5 00:10 | 显示全部楼层
屏幕截图 2021-10-05 000952.png
回复

使用道具 举报

ID:161164 发表于 2021-10-5 07:45 | 显示全部楼层
代码不全
请把头文档的内容也贴上来
盲猜LCD1602的Read/Write有checkBusy
把它去掉
回复

使用道具 举报

ID:968143 发表于 2021-10-5 11:31 | 显示全部楼层
感谢回复
这是我LCD1602和独立按键的代码,还有就是程序烧录到51单片机能显示具体温度,但仿真只能显示-0.06,怀疑是电路连接错误或是DS18B20的初始化的时延不正确。
  1. #include <REGX52.H>

  2. //引脚配置:
  3. sbit LCD_RS=P2^6;
  4. sbit LCD_RW=P2^5;
  5. sbit LCD_EN=P2^7;
  6. #define LCD_DataPort P0

  7. //函数定义:
  8. /**
  9.   * @brief  LCD1602延时函数,12MHz调用可延时1ms
  10.   * @param  无
  11.   * @retval 无
  12.   */
  13. void LCD_Delay()
  14. {
  15.         unsigned char i, j;

  16.         i = 2;
  17.         j = 239;
  18.         do
  19.         {
  20.                 while (--j);
  21.         } while (--i);
  22. }

  23. /**
  24.   * @brief  LCD1602写命令
  25.   * @param  Command 要写入的命令
  26.   * @retval 无
  27.   */
  28. void LCD_WriteCommand(unsigned char Command)
  29. {
  30.         LCD_RS=0;
  31.         LCD_RW=0;
  32.         LCD_DataPort=Command;
  33.         LCD_EN=1;
  34.         LCD_Delay();
  35.         LCD_EN=0;
  36.         LCD_Delay();
  37. }

  38. /**
  39.   * @brief  LCD1602写数据
  40.   * @param  Data 要写入的数据
  41.   * @retval 无
  42.   */
  43. void LCD_WriteData(unsigned char Data)
  44. {
  45.         LCD_RS=1;
  46.         LCD_RW=0;
  47.         LCD_DataPort=Data;
  48.         LCD_EN=1;
  49.         LCD_Delay();
  50.         LCD_EN=0;
  51.         LCD_Delay();
  52. }

  53. /**
  54.   * @brief  LCD1602设置光标位置
  55.   * @param  Line 行位置,范围:1~2
  56.   * @param  Column 列位置,范围:1~16
  57.   * @retval 无
  58.   */
  59. void LCD_SetCursor(unsigned char Line,unsigned char Column)
  60. {
  61.         if(Line==1)
  62.         {
  63.                 LCD_WriteCommand(0x80|(Column-1));
  64.         }
  65.         else if(Line==2)
  66.         {
  67.                 LCD_WriteCommand(0x80|(Column-1+0x40));
  68.         }
  69. }

  70. /**
  71.   * @brief  LCD1602初始化函数
  72.   * @param  无
  73.   * @retval 无
  74.   */
  75. void LCD_Init()
  76. {
  77.         LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
  78.         LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
  79.         LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
  80.         LCD_WriteCommand(0x01);//光标复位,清屏
  81. }

  82. /**
  83.   * @brief  在LCD1602指定位置上显示一个字符
  84.   * @param  Line 行位置,范围:1~2
  85.   * @param  Column 列位置,范围:1~16
  86.   * @param  Char 要显示的字符
  87.   * @retval 无
  88.   */
  89. void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
  90. {
  91.         LCD_SetCursor(Line,Column);
  92.         LCD_WriteData(Char);
  93. }

  94. /**
  95.   * @brief  在LCD1602指定位置开始显示所给字符串
  96.   * @param  Line 起始行位置,范围:1~2
  97.   * @param  Column 起始列位置,范围:1~16
  98.   * @param  String 要显示的字符串
  99.   * @retval 无
  100.   */
  101. void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
  102. {
  103.         unsigned char i;
  104.         LCD_SetCursor(Line,Column);
  105.         for(i=0;String[i]!='\0';i++)
  106.         {
  107.                 LCD_WriteData(String[i]);
  108.         }
  109. }

  110. /**
  111.   * @brief  返回值=X的Y次方
  112.   */
  113. int LCD_Pow(int X,int Y)
  114. {
  115.         unsigned char i;
  116.         int Result=1;
  117.         for(i=0;i<Y;i++)
  118.         {
  119.                 Result*=X;
  120.         }
  121.         return Result;
  122. }

  123. /**
  124.   * @brief  在LCD1602指定位置开始显示所给数字
  125.   * @param  Line 起始行位置,范围:1~2
  126.   * @param  Column 起始列位置,范围:1~16
  127.   * @param  Number 要显示的数字,范围:0~65535
  128.   * @param  Length 要显示数字的长度,范围:1~5
  129.   * @retval 无
  130.   */
  131. void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
  132. {
  133.         unsigned char i;
  134.         LCD_SetCursor(Line,Column);
  135.         for(i=Length;i>0;i--)
  136.         {
  137.                 LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
  138.         }
  139. }

  140. /**
  141.   * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  142.   * @param  Line 起始行位置,范围:1~2
  143.   * @param  Column 起始列位置,范围:1~16
  144.   * @param  Number 要显示的数字,范围:-32768~32767
  145.   * @param  Length 要显示数字的长度,范围:1~5
  146.   * @retval 无
  147.   */
  148. void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
  149. {
  150.         unsigned char i;
  151.         unsigned int Number1;
  152.         LCD_SetCursor(Line,Column);
  153.         if(Number>=0)
  154.         {
  155.                 LCD_WriteData('+');
  156.                 Number1=Number;
  157.         }
  158.         else
  159.         {
  160.                 LCD_WriteData('-');
  161.                 Number1=-Number;
  162.         }
  163.         for(i=Length;i>0;i--)
  164.         {
  165.                 LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
  166.         }
  167. }

  168. /**
  169.   * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  170.   * @param  Line 起始行位置,范围:1~2
  171.   * @param  Column 起始列位置,范围:1~16
  172.   * @param  Number 要显示的数字,范围:0~0xFFFF
  173.   * @param  Length 要显示数字的长度,范围:1~4
  174.   * @retval 无
  175.   */
  176. void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
  177. {
  178.         unsigned char i,SingleNumber;
  179.         LCD_SetCursor(Line,Column);
  180.         for(i=Length;i>0;i--)
  181.         {
  182.                 SingleNumber=Number/LCD_Pow(16,i-1)%16;
  183.                 if(SingleNumber<10)
  184.                 {
  185.                         LCD_WriteData(SingleNumber+'0');
  186.                 }
  187.                 else
  188.                 {
  189.                         LCD_WriteData(SingleNumber-10+'A');
  190.                 }
  191.         }
  192. }

  193. /**
  194.   * @brief  在LCD1602指定位置开始以二进制显示所给数字
  195.   * @param  Line 起始行位置,范围:1~2
  196.   * @param  Column 起始列位置,范围:1~16
  197.   * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  198.   * @param  Length 要显示数字的长度,范围:1~16
  199.   * @retval 无
  200.   */
  201. void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
  202. {
  203.         unsigned char i;
  204.         LCD_SetCursor(Line,Column);
  205.         for(i=Length;i>0;i--)
  206.         {
  207.                 LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
  208.         }
  209. }

  210. #include <REGX52.H>
  211. #include "Delay.h"
  212. /**
  213.    *@brief        获取独立按键键码
  214.    *@param        无
  215.    *@retval 按下按键的键码,无按键按下时返回值为0
  216.    */
  217. unsigned char Key()
  218. {
  219.         unsigned char KeyNumber=0;
  220.         
  221.         if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}
  222.         if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}
  223.         if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}
  224.         if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}

  225.         return KeyNumber;
  226. }
复制代码

1.png
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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