找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2882|回复: 8
收起左侧

三个DS18B20接MCU三个IO口程序问题

[复制链接]
ID:481090 发表于 2019-2-26 20:10 | 显示全部楼层 |阅读模式
用DS18B20传感器和51单片机做出多路温度监测系统,但是要用到三个DS18B20,每个DS18B20接一个51单片机管脚,不是单总线的,一个传感器我已经知道怎么写了,三个的用最笨的办法复制三次,但是显示不行,只能显示一个温度,三个都插上的时候,而且温度也都不会变化,这是什么问题导致的呢,是不是不能用这种方法,如果不行,还有别的什么方法呢,给个大概的思路或者给一个实例。。。谢谢各位大佬了。
#include "DS18B20.h"
   
uchar TPH1;                           //存放温度值的高字节
uchar TPL1;                           //存放温度值的低字节

uchar TPH2;                           //存放温度值的高字节
uchar TPL2;                           //存放温度值的低字节

uchar TPH3;                           //存放温度值的高字节
uchar TPL3;                           //存放温度值的低字节

/**************************************
延时X微秒(STC12C5A60S2@12M)
不同的工作环境,需要调整此函数
此延时函数是使用1T的指令周期进行计算,与传统的12T的MCU不同
**************************************/
void DelayXus(uchar n)
{
    while (n--)
    {
        _nop_();
        _nop_();
    }
}
/**************************************
第一个 复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset1()
{
    CY = 1;
    while (CY)
    {
        DQ1 = 0;                     //送出低电平复位信号
        DelayXus(240);              //延时至少480us
        DelayXus(240);
        DQ1 = 1;                     //释放数据线
        DelayXus(60);               //等待60us
        CY = DQ1;                    //检测存在脉冲
        DelayXus(240);              //等待设备释放数据线
        DelayXus(180);
    }
}
/**************************************
从DS18B20读1字节数据
**************************************/
uchar DS18B20_ReadByte1()
{
    uchar i;
    uchar dat = 0;

    for (i=0; i<8; i++)             //8位计数器
    {
        dat >>= 1;
        DQ1 = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        DQ1= 1;                     //准备接收
        DelayXus(1);                //接收延时
        if (DQ1) dat |= 0x80;        //读取数据
        DelayXus(60);               //等待时间片结束
    }

    return dat;
}
/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte1(uchar dat)
{
    char i;

    for (i=0; i<8; i++)             //8位计数器
    {
        DQ1 = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        dat >>= 1;                  //送出数据
        DQ1 = CY;
        DelayXus(60);               //等待时间片结束
        DQ1 = 1;                     //恢复数据线
        DelayXus(1);                //恢复延时
    }
}
/**************************************
读取温度值
**************************************/
void read_wendu1()
{   
     DS18B20_Reset1();                //设备复位
  DS18B20_WriteByte1(0xCC);        //跳过ROM命令
  DS18B20_WriteByte1(0x44);        //开始转换命令
  while (!DQ1);                    //等待转换完成
    DS18B20_Reset1();                //设备复位
  DS18B20_WriteByte1(0xCC);        //跳过ROM命令                                               
  DS18B20_WriteByte1(0xBE);        //读暂存存储器命令   
   
    TPL1 = DS18B20_ReadByte1();       //读温度低字节
  TPH1 = DS18B20_ReadByte1();       //读温度高字节
}


/**************************************
第二个 复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset2()
{
    CY = 1;
    while (CY)
    {
        DQ2 = 0;                     //送出低电平复位信号
        DelayXus(240);              //延时至少480us
        DelayXus(240);
        DQ2 = 1;                     //释放数据线
        DelayXus(60);               //等待60us
        CY = DQ2;                    //检测存在脉冲
        DelayXus(240);              //等待设备释放数据线
        DelayXus(180);
    }
}
/**************************************
从DS18B20读1字节数据
**************************************/
uchar DS18B20_ReadByte2()
{
    uchar i;
    uchar dat = 0;

    for (i=0; i<8; i++)             //8位计数器
    {
        dat >>= 1;
        DQ2 = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        DQ2= 1;                     //准备接收
        DelayXus(1);                //接收延时
        if (DQ2) dat |= 0x80;        //读取数据
        DelayXus(60);               //等待时间片结束
    }

    return dat;
}
/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte2(uchar dat)
{
    char i;

    for (i=0; i<8; i++)             //8位计数器
    {
        DQ2 = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        dat >>= 1;                  //送出数据
        DQ2 = CY;
        DelayXus(60);               //等待时间片结束
        DQ2 = 1;                     //恢复数据线
        DelayXus(1);                //恢复延时
    }
}
/**************************************
读取温度值
**************************************/
void read_wendu2()
{   
     DS18B20_Reset2();                //设备复位
  DS18B20_WriteByte2(0xCC);        //跳过ROM命令
  DS18B20_WriteByte2(0x44);        //开始转换命令
  while (!DQ2);                    //等待转换完成
    DS18B20_Reset2();                //设备复位
  DS18B20_WriteByte2(0xCC);        //跳过ROM命令                                               
  DS18B20_WriteByte2(0xBE);        //读暂存存储器命令   
   
    TPL2 = DS18B20_ReadByte2();       //读温度低字节
  TPH2= DS18B20_ReadByte2();       //读温度高字节
}






/**************************************
第三个 复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset3()
{
    CY = 1;
    while (CY)
    {
        DQ3 = 0;                     //送出低电平复位信号
        DelayXus(240);              //延时至少480us
        DelayXus(240);
        DQ3 = 1;                     //释放数据线
        DelayXus(60);               //等待60us
        CY = DQ3;                    //检测存在脉冲
        DelayXus(240);              //等待设备释放数据线
        DelayXus(180);
    }
}
/**************************************
从DS18B20读1字节数据
**************************************/
uchar DS18B20_ReadByte3()
{
    uchar i;
    uchar dat = 0;

    for (i=0; i<8; i++)             //8位计数器
    {
        dat >>= 1;
        DQ3 = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        DQ3= 1;                     //准备接收
        DelayXus(1);                //接收延时
        if (DQ3) dat |= 0x80;        //读取数据
        DelayXus(60);               //等待时间片结束
    }

    return dat;
}
/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte3(uchar dat)
{
    char i;

    for (i=0; i<8; i++)             //8位计数器
    {
        DQ3 = 0;                     //开始时间片
        DelayXus(1);                //延时等待
        dat >>= 1;                  //送出数据
        DQ3 = CY;
        DelayXus(60);               //等待时间片结束
        DQ3 = 1;                     //恢复数据线
        DelayXus(1);                //恢复延时
    }
}
/**************************************
读取温度值
**************************************/
void read_wendu3()
{   
     DS18B20_Reset3();                //设备复位
  DS18B20_WriteByte3(0xCC);        //跳过ROM命令
  DS18B20_WriteByte3(0x44);        //开始转换命令
  while (!DQ3);                    //等待转换完成
    DS18B20_Reset3();                //设备复位
  DS18B20_WriteByte3(0xCC);        //跳过ROM命令                                               
  DS18B20_WriteByte3(0xBE);        //读暂存存储器命令   
   
    TPL3 = DS18B20_ReadByte3();       //读温度低字节
  TPH3 = DS18B20_ReadByte3();       //读温度高字节
}


回复

使用道具 举报

ID:481090 发表于 2019-2-26 20:31 | 显示全部楼层
void T_Display1() {                 EA=0;                 read_wendu1();//读取温度           EA=1;                 wendu1=((TPH1&0x07)*16+TPL1*0.0625)*100;//转换实际温度                 LcdSetCursor(6,0);                 LcdWriteDat(0x30+wendu1/1000%10);                 LcdSetCursor(7,0);                 LcdWriteDat(0x30+wendu1/100%10);                  }  void T_Display2() {  EA=0;         read_wendu2();//读取温度           EA=1;                 wendu2=((TPH2&0x07)*16+TPL2*0.0625)*100;//转换实际温度                 LcdSetCursor(10,0);   LcdWriteDat(0x30+wendu2/1000%10);         LcdSetCursor(11,0);         LcdWriteDat(0x30+wendu2/100%10);}  void T_Display3() {   EA=0;                 read_wendu3();//读取温度           EA=1;                 wendu3=((TPH3&0x07)*16+TPL3*0.0625)*100;//转换实际温度         LcdSetCursor(14,0);                 LcdWriteDat(0x30+wendu3/1000%10);         LcdSetCursor(15,0);                 LcdWriteDat(0x30+wendu3/100%10);}这是三个显示的
回复

使用道具 举报

ID:403593 发表于 2019-2-27 10:58 | 显示全部楼层
三个DS18b20共用一个IO口就行,没必要用三个口,网上有多点测温的例子,找来看一看就知道怎么回事了
回复

使用道具 举报

ID:481433 发表于 2019-2-27 11:31 | 显示全部楼层
一份参考代码,供参考。

给客户使用HC32L110 IAP.rar

1.59 MB, 下载次数: 47

回复

使用道具 举报

ID:481090 发表于 2019-2-27 14:15 | 显示全部楼层
已经解决,谢谢各位了
回复

使用道具 举报

ID:491242 发表于 2019-3-20 09:12 | 显示全部楼层
能发一发你已经做好的程序吗
回复

使用道具 举报

ID:737981 发表于 2020-5-22 14:32 | 显示全部楼层
Su夜已深 发表于 2019-2-27 14:15
已经解决,谢谢各位了

你好,怎么解决的,你还是坚持三个I/o口吗
回复

使用道具 举报

ID:282850 发表于 2020-5-22 17:13 | 显示全部楼层
支持你3个IO口的,多年前我用1线2个DS18,距离上不去,改用了2个IO,程序也是重复模块的。现在的4个测温也是用4IO口,不过程序只用了一份。
回复

使用道具 举报

ID:45879 发表于 2020-6-29 13:04 | 显示全部楼层
f556 发表于 2020-5-22 17:13
支持你3个IO口的,多年前我用1线2个DS18,距离上不去,改用了2个IO,程序也是重复模块的。现在的4个测温也是 ...

方便说一些思路吗 谢了 正在看这方面的
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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