[经验分享] 单片机DS18B20多路温度采集

[复制链接]
 楼主| aspoke 发表于 2024-2-17 23:53 | 显示全部楼层 |阅读模式
  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.   * [url=home.php?mod=space&uid=247401]@brief[/url]  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=0;
  34.         LCD_Delay();
  35.         LCD_EN=1;
  36.         LCD_Delay();
  37.         LCD_EN=0;
  38. }

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

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

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

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

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

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

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

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

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

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

  213. void LCD_DispalyT(float T)
  214. {
  215.         float TShow;
  216.         LCD_Init();
  217.         LCD_ShowString(1,1,"T:");
  218.         if(T<0)                                //如果温度小于0
  219.         {
  220.                 LCD_ShowChar(1,3,'-');        //显示负号
  221.                 TShow=-T;                //将温度变为正数
  222.         }
  223.         else                                //如果温度大于等于0
  224.         {
  225.                 LCD_ShowChar(1,3,'+');        //显示正号
  226.                 TShow=T;
  227.         }
  228.         LCD_ShowNum(1,4,TShow,3);                //显示温度整数部分
  229.         LCD_ShowChar(1,7,'.');                //显示小数点
  230.         LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);//显示温度小数部分
  231.        
  232. }


benjaminka 发表于 2024-3-4 16:27 | 显示全部楼层
每个DS18B20都需要一个独立的电源供电,并且需要与单片机共用一个地线。
jkl21 发表于 2024-3-4 16:39 | 显示全部楼层
DS18B20传感器在完成一次温度转换后,需要等待一段时间(通常为750ms)才能进行下一次转换。在进行多路温度采集时,要考虑到转换时间的影响。
abotomson 发表于 2024-3-5 08:55 | 显示全部楼层
安装DS18B20时,要考虑环境因素对温度传感器的影响,如湿度和温度等,这些都可能影响温度测量的准确性。
minzisc 发表于 2024-3-5 09:48 | 显示全部楼层
由于DS18B20使用的是单总线协议,因此在同一总线上连接的DS18B20数量过多时,可能会引起信号反射和竞争问题。适当的设计总线拓扑结构和时序控制是保证数据准确传输的关键。
wilhelmina2 发表于 2024-3-5 13:01 | 显示全部楼层
进行温度转换时,DS18B20需要一定的时间(典型值750ms),在发出温度转换命令后,必须等待这段时间后再读取数据。
yeates333 发表于 2024-3-5 13:11 | 显示全部楼层
DS18B20的工作电压范围是3V到5.5V,通常使用3.3V或5V电源。电源稳定,以避免因电源波动导致的读数错误。
mmbs 发表于 2024-3-5 16:01 | 显示全部楼层
单片机向DS18B20发送命令时,需要严格按照DS18B20的时序要求来发送。错误的时序可能会导致DS18B20无法正确接收命令。
51xlf 发表于 2024-3-9 16:50 | 显示全部楼层
在进行多路温度采集时,需要使用总线拓扑结构连接多个DS18B20传感器。注意总线上的每个传感器都有一个唯一的64位序列号,可以通过读取ROM指令来识别和定位特定的传感器。
geraldbetty 发表于 2024-3-9 19:15 | 显示全部楼层
DS18B20传感器使用1-Wire总线进行通信,通信线的长度会影响信号质量。尽量使用较短的通信线,以减少信号干扰和传输延迟。
i1mcu 发表于 2024-3-9 20:15 | 显示全部楼层
DS18B20使用1-Wire协议进行通信,注意掌握协议规范和通信时序。在编写单片机程序时,要严格按照协议和时序要求进行操作。
pixhw 发表于 2024-3-11 14:35 | 显示全部楼层
在一次温度采集过程中,需要通过软件控制依次选通各个DS18B20进行通信,避免多传感器同时响应导致的数据冲突。
juliestephen 发表于 2024-3-11 17:11 | 显示全部楼层
DS18B20的GND引脚必须与单片机的GND引脚正确连接,以确保电位一致,避免因电位不一致造成的通信问题。
plsbackup 发表于 2024-3-14 13:26 | 显示全部楼层
DS18B20采用单总线协议进行通信,需要严格按照协议规范进行读写操作,包括初始化、ROM操作(读取序列号或选择设备)、RAM操作(读取温度数据)等步骤。
wangdezhi 发表于 2024-3-14 13:40 | 显示全部楼层
编写程序逐一唤醒和读取每个DS18B20的温度数据,可以采用轮询方式或扫描方式,前者适用于传感器数量较少的情况,后者更适合大量传感器的场合。
bartonalfred 发表于 2024-3-14 13:53 | 显示全部楼层
DS18B20的温度测量精度可以通过编程设置为9位至12位。根据实际需求选择合适的精度,以平衡测量精度和传输速率。
lihuami 发表于 2024-3-14 18:43 | 显示全部楼层
DS18B20与单片机之间的通信是通过序列完成的,需要严格按照DS18B20的数据手册中的时序进行操作。特别是在转换温度和写操作时,必须精确控制时钟信号。
gygp 发表于 2024-3-14 21:20 | 显示全部楼层
DS18B20通过1-Wire协议发送原始温度数据,需要控制器进行计算才能得到实际温度值。
在软件编程时,要正确实现数据的解析和转换算法。
minzisc 发表于 2024-3-14 22:31 | 显示全部楼层
对于DS18B20,需要考虑其低功耗特性,在不需要通信时可以通过软件将单片机与DS18B20的连接断开,以节省电源。
uptown 发表于 2024-3-15 20:44 | 显示全部楼层
DS18B20的数据线(DQ)通常连接到单片机的一个IO口。确保数据线连接可靠,避免接触不良或信号传输问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

2474

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部