打印
[经验分享]

单片机DS18B20多路温度采集

[复制链接]
4413|43
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aspoke|  楼主 | 2024-2-17 23:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <REGX52.H>

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


//函数定义:
/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()
{
        unsigned char i, j;

        i = 2;
        j = 239;
        do
        {
                while (--j);
        } while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
        LCD_RS=0;
        LCD_RW=0;
        LCD_DataPort=Command;
        LCD_EN=0;
        LCD_Delay();
        LCD_EN=1;
        LCD_Delay();
        LCD_EN=0;
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
        LCD_RS=1;
        LCD_RW=0;
        LCD_EN=0;
        LCD_DataPort=Data;
        LCD_EN=1;
        LCD_Delay();
        LCD_EN=0;
        LCD_Delay();
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
        if(Line==1)
        {
                LCD_WriteCommand(0x80|(Column-1));
        }
        else if(Line==2)
        {
                LCD_WriteCommand(0x80|(Column-1+0x40));
        }
}

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

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
        LCD_SetCursor(Line,Column);
        LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
        unsigned char i;
        LCD_SetCursor(Line,Column);
        for(i=0;String[i]!='\0';i++)
        {
                LCD_WriteData(String[i]);
        }
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
        unsigned char i;
        int Result=1;
        for(i=0;i<Y;i++)
        {
                Result*=X;
        }
        return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
        unsigned char i;
        LCD_SetCursor(Line,Column);
        for(i=Length;i>0;i--)
        {
                LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
        }
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
        unsigned char i;
        unsigned int Number1;
        LCD_SetCursor(Line,Column);
        if(Number>=0)
        {
                LCD_WriteData('+');
                Number1=Number;
        }
        else
        {
                LCD_WriteData('-');
                Number1=-Number;
        }
        for(i=Length;i>0;i--)
        {
                LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
        }
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
        unsigned char i,SingleNumber;
        LCD_SetCursor(Line,Column);
        for(i=Length;i>0;i--)
        {
                SingleNumber=Number/LCD_Pow(16,i-1)%16;
                if(SingleNumber<10)
                {
                        LCD_WriteData(SingleNumber+'0');
                }
                else
                {
                        LCD_WriteData(SingleNumber-10+'A');
                }
        }
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
        unsigned char i;
        LCD_SetCursor(Line,Column);
        for(i=Length;i>0;i--)
        {
                LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
        }
}

void LCD_DispalyT(float T)
{
        float TShow;
        LCD_Init();
        LCD_ShowString(1,1,"T:");
        if(T<0)                                //如果温度小于0
        {
                LCD_ShowChar(1,3,'-');        //显示负号
                TShow=-T;                //将温度变为正数
        }
        else                                //如果温度大于等于0
        {
                LCD_ShowChar(1,3,'+');        //显示正号
                TShow=T;
        }
        LCD_ShowNum(1,4,TShow,3);                //显示温度整数部分
        LCD_ShowChar(1,7,'.');                //显示小数点
        LCD_ShowNum(1,8,(unsigned long)(TShow*100)%100,2);//显示温度小数部分
       
}


使用特权

评论回复
沙发
benjaminka| | 2024-3-4 16:27 | 只看该作者
每个DS18B20都需要一个独立的电源供电,并且需要与单片机共用一个地线。

使用特权

评论回复
板凳
jkl21| | 2024-3-4 16:39 | 只看该作者
DS18B20传感器在完成一次温度转换后,需要等待一段时间(通常为750ms)才能进行下一次转换。在进行多路温度采集时,要考虑到转换时间的影响。

使用特权

评论回复
地板
abotomson| | 2024-3-5 08:55 | 只看该作者
安装DS18B20时,要考虑环境因素对温度传感器的影响,如湿度和温度等,这些都可能影响温度测量的准确性。

使用特权

评论回复
5
minzisc| | 2024-3-5 09:48 | 只看该作者
由于DS18B20使用的是单总线协议,因此在同一总线上连接的DS18B20数量过多时,可能会引起信号反射和竞争问题。适当的设计总线拓扑结构和时序控制是保证数据准确传输的关键。

使用特权

评论回复
6
wilhelmina2| | 2024-3-5 13:01 | 只看该作者
进行温度转换时,DS18B20需要一定的时间(典型值750ms),在发出温度转换命令后,必须等待这段时间后再读取数据。

使用特权

评论回复
7
yeates333| | 2024-3-5 13:11 | 只看该作者
DS18B20的工作电压范围是3V到5.5V,通常使用3.3V或5V电源。电源稳定,以避免因电源波动导致的读数错误。

使用特权

评论回复
8
mmbs| | 2024-3-5 16:01 | 只看该作者
单片机向DS18B20发送命令时,需要严格按照DS18B20的时序要求来发送。错误的时序可能会导致DS18B20无法正确接收命令。

使用特权

评论回复
9
51xlf| | 2024-3-9 16:50 | 只看该作者
在进行多路温度采集时,需要使用总线拓扑结构连接多个DS18B20传感器。注意总线上的每个传感器都有一个唯一的64位序列号,可以通过读取ROM指令来识别和定位特定的传感器。

使用特权

评论回复
10
geraldbetty| | 2024-3-9 19:15 | 只看该作者
DS18B20传感器使用1-Wire总线进行通信,通信线的长度会影响信号质量。尽量使用较短的通信线,以减少信号干扰和传输延迟。

使用特权

评论回复
11
i1mcu| | 2024-3-9 20:15 | 只看该作者
DS18B20使用1-Wire协议进行通信,注意掌握协议规范和通信时序。在编写单片机程序时,要严格按照协议和时序要求进行操作。

使用特权

评论回复
12
pixhw| | 2024-3-11 14:35 | 只看该作者
在一次温度采集过程中,需要通过软件控制依次选通各个DS18B20进行通信,避免多传感器同时响应导致的数据冲突。

使用特权

评论回复
13
juliestephen| | 2024-3-11 17:11 | 只看该作者
DS18B20的GND引脚必须与单片机的GND引脚正确连接,以确保电位一致,避免因电位不一致造成的通信问题。

使用特权

评论回复
14
plsbackup| | 2024-3-14 13:26 | 只看该作者
DS18B20采用单总线协议进行通信,需要严格按照协议规范进行读写操作,包括初始化、ROM操作(读取序列号或选择设备)、RAM操作(读取温度数据)等步骤。

使用特权

评论回复
15
wangdezhi| | 2024-3-14 13:40 | 只看该作者
编写程序逐一唤醒和读取每个DS18B20的温度数据,可以采用轮询方式或扫描方式,前者适用于传感器数量较少的情况,后者更适合大量传感器的场合。

使用特权

评论回复
16
bartonalfred| | 2024-3-14 13:53 | 只看该作者
DS18B20的温度测量精度可以通过编程设置为9位至12位。根据实际需求选择合适的精度,以平衡测量精度和传输速率。

使用特权

评论回复
17
lihuami| | 2024-3-14 18:43 | 只看该作者
DS18B20与单片机之间的通信是通过序列完成的,需要严格按照DS18B20的数据手册中的时序进行操作。特别是在转换温度和写操作时,必须精确控制时钟信号。

使用特权

评论回复
18
gygp| | 2024-3-14 21:20 | 只看该作者
DS18B20通过1-Wire协议发送原始温度数据,需要控制器进行计算才能得到实际温度值。
在软件编程时,要正确实现数据的解析和转换算法。

使用特权

评论回复
19
minzisc| | 2024-3-14 22:31 | 只看该作者
对于DS18B20,需要考虑其低功耗特性,在不需要通信时可以通过软件将单片机与DS18B20的连接断开,以节省电源。

使用特权

评论回复
20
uptown| | 2024-3-15 20:44 | 只看该作者
DS18B20的数据线(DQ)通常连接到单片机的一个IO口。确保数据线连接可靠,避免接触不良或信号传输问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

2474

帖子

1

粉丝