找回密码
 立即注册
查看: 50|回复: 4

读取多路18b20

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2026-04-29 09:54:19

9

主题

23

回帖

189

积分

注册会员

积分
189
发表于 4 天前 来自手机 | 显示全部楼层 |阅读模式
请问那位有读取多路18b20 id程序,自己查资料弄了,读出不出来,也不知那不对


sbit DQ = P7^3;                   //DS18B20的数据口
u8 MinusFlag;       //负数标志,0:正数,1:负数


unsigned char DS18B20_ID[MaxSensorNum][8];        // 存检测到的传感器DS18B20_ID的数组,前面的维数代表单根线传感器数量上限
unsigned char DS18B20_SensorNum;                        // 检测到的传感器数量(从1开始,例如显示1代表1个,8代表8个)

/**************************************
复位DS18B20,并检测设备是否存在
**************************************/
void DS18B20_Reset()
{
   
        DQ = 0;                     //送出低电平复位信号
        delay_us(480);              //延时至少480us

        DQ = 1;                     //释放数据线

        delay_us(15);

}

/**************************************
从DS18B20读1字节数据
**************************************/
u8 DS18B20_ReadByte()
{
    u8 i;
    u8 dat = 0;

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

    return dat;
}

/**************************************
向DS18B20写1字节数据
**************************************/
void DS18B20_WriteByte(u8 dat)
{

        u8 j;
        u8 testb;
        for (j = 1; j <= 8; j++)
        {
                testb = dat & 0x01;
                dat = dat >> 1;
                if (testb)
                {
                        DQ=0;// 写1
                        delay_us(10);
                        DQ=1;
                        delay_us(50);
                }
                else
                {
                        DQ=0;// 写0
                        delay_us(60);
                        DQ=1;// 释放总线
                        delay_us(2);
                }
        }
}

// 检测从机给主机返回的应答脉冲。从机接收到主机的复位信号后,会在15~60us后给主机发一个应答脉冲
u8 DS18B20_Answer_Check(void)
{
        u8 delay=0;

        // 等待应答脉冲(一个60~240us的低电平信号 )的到来
        // 如果100us内,没有应答脉冲,退出函数,注意:从机接收到主机的复位信号后,会在15~60us后给主机发一个存在脉冲
        while (DQ&&delay <100)
        {
                delay++;
                delay_us(1);
        }
        // 经过100us后如果没有应答脉冲;退出函数
        if (delay>=100)//Hu200
                return 1;
        else
                delay=0;
        // 有应答脉冲且存在时间不超过240us
        while (!DQ&&delay<240)
        {
                delay++;
                delay_us(1);
        }
        if (delay>=240)
                return 1;
        return 0;
}

u8 DS18B20_INit()
{
   DS18B20_Reset();
        return DS18B20_Answer_Check();
}
/*void ds18b20_rom()
{
        int j;
         DS18B20_Reset();                //设备复位
    DS18B20_WriteByte(0x33);        //发送读序列号命令        
        
        for(j=0;j<8;j++)
        FAC_DATA_Table.ds18b20_rom_buf[0][j]=DS18B20_ReadByte();
}*/

// 从DS18B20读取2个位
u8 DS18B20_Read_2Bit(void)//读二位 子程序
{
        u8 i;
        u8 dat = 0;
        for (i = 2; i > 0; i--)
        {
                dat = dat << 1;
                DQ=0;
                delay_us(2);
                DQ=1;
                delay_us(12);
                if (DQ)        dat |= 0x01;
                delay_us(50);
        }
        return dat;
}

// 写1位到DS18B20
void DS18B20_Write_Bit(u8 dat)
{
        DQ=0;
        delay_us(1);
        if(dat & 0x01)DQ=1;
        else DQ=0;
        delay_us(60);
        DQ=1;
        delay_us(1);
}
// 自动搜索ROM
u8 DS18B20_Search_Rom()
{
        u8 k, l, chongtuwei, m, n, num;
        u8 zhan[5];
        u8 ss[64];
        u8 tempp;
        l = 0;
        num = 0;
        do
        {
                DS18B20_Reset(); //注意:复位的延时不够
               
                delay_us(480); //480、720
                DS18B20_WriteByte(0xf0);
                for (m = 0; m < 8; m++)
                {
                        u8 s = 0;
                        for (n = 0; n < 8; n++)
                        {
                                k = DS18B20_Read_2Bit();//读两位数据

                                k = k & 0x03;
                                s >>= 1;
                                if (k == 0x01)//01读到的数据为0 写0 此位为0的器件响应
                                {
                                        DS18B20_Write_Bit(0);
                                        ss[(m * 8 + n)] = 0;
                                }
                                else if (k == 0x02)//读到的数据为1 写1 此位为1的器件响应
                                {
                                        s = s | 0x80;
                                        DS18B20_Write_Bit(1);
                                        ss[(m * 8 + n)] = 1;
                                }
                                else if (k == 0x00)//读到的数据为00 有冲突位 判断冲突位
                                {
                                        //如果冲突位大于栈顶写0 小于栈顶写以前数据 等于栈顶写1
                                        chongtuwei = m * 8 + n + 1;
                                        if (chongtuwei > zhan[l])
                                        {
                                                DS18B20_Write_Bit(0);
                                                ss[(m * 8 + n)] = 0;
                                                zhan[++l] = chongtuwei;
                                        }
                                        else if (chongtuwei < zhan[l])
                                        {
                                                s = s | ((ss[(m * 8 + n)] & 0x01) << 7);
                                                DS18B20_Write_Bit(ss[(m * 8 + n)]);
                                        }
                                        else if (chongtuwei == zhan[l])
                                        {
                                                s = s | 0x80;
                                                DS18B20_Write_Bit(1);
                                                ss[(m * 8 + n)] = 1;
                                                l = l - 1;
                                        }
                                }
                                else
                                {
                                        return 5;//没有搜索到
                                }
                        }

                        tempp = s;
                        DS18B20_ID[num][m] = tempp; // 保存搜索到的ID
                }
                num = num + 1;// 保存搜索到的个数
        } while (zhan[l] != 0 && (num < MaxSensorNum));
        DS18B20_SensorNum=num;
        return num;
}
//========================================================================
// 函数: u16 ReadTemperature()
// 描述: 读取温度函数。
// 参数: none..
// 返回: 温度值.
// 版本: VER1.0
// 日期: 2020-7-30
// 备注:
//========================================================================
float ReadTemperature(u8 chi)
{   u8 i;
    u16 TempH, TempL, Temperature;
    DS18B20_Reset();                //设备复位
        DS18B20_Answer_Check();
    DS18B20_WriteByte(0xcc);        //跳过ROM命令
    DS18B20_WriteByte(0x44);        //开始转换命令
    //while (!DQ);                    //等待转换完成

    DS18B20_Reset();                //设备复位
        DS18B20_Answer_Check();
        
    //DS18B20_WriteByte(0xCC);        //跳过ROM命令
        DS18B20_WriteByte(0x55);        //pi
        for(i=0;i<8;i++)
        DS18B20_WriteByte(FAC_DATA_Table.ds18b20_rom_buf[chi]);        //读暂存存储器命令
        
    DS18B20_WriteByte(0xBE);        //读暂存存储器命令
        
    TempL = DS18B20_ReadByte();     //读温度低字节
    TempH = DS18B20_ReadByte();     //读温度高字节
        
    if(TempH & 0xf8)    //判断是否位负数
    {
        MinusFlag = 1;  //设置负数标志
        Temperature = (TempH<<8) | TempL;
        Temperature = ~Temperature + 1;
        Temperature *= 0.625 / 100.0f * (float)FAC_DATA_Table.Adjust_s.Temp;       //0.0625 * 10,保留1位小数点
    }
    else
    {
        MinusFlag = 0;  //清除负数标志
        Temperature = (((TempH<<8) | TempL) * 0.625); //0.0625 * 10,保留1位小数点
    }
        

    return Temperature;
}



void        main(void)
{   
        u8 i,j;
        IO_INIT();
  
        EG1163S_OFF=0;
        OFFON=0;
        IRON = 0;//T12控制
        //P5n_push_pull(0x04);        //P5.2 设置为推挽输出
        I2C_INIT();
       
        ADC_config();
        DMA_ADC_Config();
        EA = 1;     //打开总中断
       
        LCM_Config();        //LCM初始化
        DMA_Config();        //LCM_DMA初始化, 使用DMA方式显示下面的字符串.
        ST7735_init();

    LCD_Display_Dir(2);                                 //屏幕方向
        display();
        UartInit();
       
        PID_nitialization();
        PWMA_config();
        PWMB_config();
       
        BEEP=0;
        UpdatePwm_CC(min2);
        MCP4725_Write_VCC(0);
        user_menu_init();
        while(DS18B20_INit())
        {
          printf("DS18B20 cheak failed!\r\n");
        }
       
           printf("DS18B20 read!\r\n");

         DS18B20_Search_Rom();
                printf("DS18B20_SensorNum:%d\r\n",DS18B20_SensorNum);
          for(i=0;i<DS18B20_SensorNum;i++)
                {
                          for(j=0;j<8;j++)
                      printf("0x%02x,",DS18B20_ID[j]);   //串口打印
                        printf("\r\n");
                }   
               
        // RSTFLAG |= 0x04;   //设置看门狗复位需要检测P3.2的状态,否则看门狗复位后进入USB下载模式
        while (1)
        {
           if( EG1163S_OFF==1)
                CV_DAC=PID_Compute((float)min1,(float)OUT_VCC*100);
                else  
                {
                     CV_DAC=0;
                         MCP4725_Write_VCC(0);

                }
                //UpdatePwm_CV(min1);
                MCP4725_Write_VCC(CV_DAC);
               
            UpdatePwm_CC(min2);
                UpdatePwm_PID(1500);
        }
}
这个程序,挂载了3个18b20,有时候能正确读出来1个id,有时候一个都不行,要么就是读出来的id是错误的,自己用0x33一个一个读出id后,可以正确读出各路的温度,就一次型读取多路id不行,求大佬帮忙看看,多谢了
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2026-04-29 09:54:19

9

主题

23

回帖

189

积分

注册会员

积分
189
发表于 4 天前 来自手机 | 显示全部楼层
读取多路,始终串口打印发现0个18b20
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2026-05-01 05:53:11
已绑定手机

3

主题

94

回帖

505

积分

高级会员

积分
505
发表于 4 天前 | 显示全部楼层
c2016*** 发表于 2026-4-27 11:11
读取多路,始终串口打印发现0个18b20

STC8H自动读取3个18b20序列号.rar (25.04 KB, 下载次数: 4) STC8H万年历自动匹配18b20序列号多点测温示例程序.rar (49.73 KB, 下载次数: 3)
回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:8
  • 最近打卡:2026-04-29 09:54:19

9

主题

23

回帖

189

积分

注册会员

积分
189
发表于 前天 09:54 来自手机 | 显示全部楼层
wulin 发表于 2026-4-27 17:12

还是读不出来,要么读出来全是0x00或者不是28开头的数据,用0x33一个一个可以读取出来,单路读取后的id,可以读出正确的温度
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:60
  • 最近打卡:2026-05-01 05:53:11
已绑定手机

3

主题

94

回帖

505

积分

高级会员

积分
505
发表于 前天 15:40 | 显示全部楼层
c2016*** 发表于 2026-4-29 09:54
还是读不出来,要么读出来全是0x00或者不是28开头的数据,用0x33一个一个可以读取出来,单路读取后的id, ...

这个程序中的自动搜索总线上多个DS18B20序列号代码是实际用于某医用检测仪器的。单总线5路温度检测。有可能是你的硬件不匹配,也有可能是你修改软件出错。
回复

使用道具 举报 送花

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

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-5-1 10:31 , Processed in 0.115566 second(s), 71 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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