H_JEN 发表于 2016-5-2 17:21:44

基于STM32的DS18B20的问题

本人现在在做基于STM32的DS18B20的测温,但是一直不成功。就拿初始化来说,按照时序图是先给低电平480us或以上,再给15us的高电平,然后就放开总线,18B20就开始复位。我的初始化程序时要看18B20有没有复位完成。但是我用示波器来看的时候前面给的开始信号是正确的,但是后面读18B20的复位输出的时候,18B20一直处于高电平.......为什么呢?
char ds18b20_Reset(void)
{
      uint8_t count = 0,i = 0;      

      GPIO_Out_Config();

      DQ_L;
      Delay_us(480);

      DQ_H;
      Delay_us(15);

      GPIO_In_Config();//IPU模式能读数,但是一直为1,18b20可能坏了      
      Delay_us(10);

      while(count < 100)
      {
                i = DQ_Read;
                if(i == 1)
                {
                NOP();
                count++;
                }
                else
                        break;
      }

      if(count >= 100)
                return 0;
      else
                count = 0;
      while(count <240)
      {
                i = DQ_Read;
                if(i ==0)
                {
                NOP();
                count++;
                }
                break;
      }
      if(count >= 240)
                return 0;
      else
                return 1;
}以上是初始化的,GPIO的输出模式是PP推挽,GPIO的输入模式是IPU上拉输入;
求大神指点一二啊

单片机是STM32F103ZET的,现在经过修改后,能读出数据,但是高八位要么全0,要么全1;低八位总是全0。而且18b20复位完成后,不发送任何指令,直接读数据口,读出来的有时是1,有时是0。根据时序图,复位完成后,数据口应该是一直高电平才对。
完整的程序如下:
#include "stm32_18b20.h"

void ds18b20_Config(void)
{
      unsigned char Init_Flag;

      Init_Flag = ds18b20_Reset();
      if(Init_Flag)
                printf("\r\n 1 \r\n");//复位成功
      else
      {
                printf("\r\n -1 \r\n");//复位失败
                while(1);
      }               
}

void ds18b20_WriteCmd(uint8_t cmd)
{
      uint8_t i, ch;      

      GPIO_Out_Config();

      for(i = 0; i < 8; i++)
      {
                ch = cmd;
                ch = ch & 0x01;
                cmd = cmd >> 1;
               
                DQ_L;
                Delay_us(15);//起始15us低电平

                if(ch)//写入1                              
                {                                       
                        DQ_H;
                        NOP();NOP();NOP();NOP();NOP();
                        DQ_L;                        
                        Delay_us(65);      
                }                                       
                else//写入0                              
                {                                       
                        DQ_L;
                        Delay_us(65);
                        DQ_H;
                        NOP();NOP();NOP();NOP();NOP();               
                }                              
      }
}

uint8_t ds18b20_ReadData(void)
{
      uint8_t i,s = 0, dat = 0, data = 0;

      ds18b20_Config();      

      for(i = 0; i < 8; i++)
      {
                data = data >> 1;

                DQ_L;
                NOP();
                DQ_H;
                Delay_us(12);//放开总线
                s = DQ_Read;
                if(s)
                        dat = 1;
                else
                        dat = 0;
                Delay_us(45);
                s = 0;
                data = data | (dat << 7);               
      }
      return data;      
}

char ds18b20_Reset(void)
{
      uint8_t count = 0,i = 0;      

      GPIO_Out_Config();

      DQ_L;
      Delay_us(480);//复位信号

      DQ_H;
      Delay_us(15);//释放总线

      while(count < 100)
      {
                i = DQ_Read;
                if(i == 1)
                {
                Delay_us(1);
                count++;
                }
                else
                        break;
      }

      if(count >= 100)
                return 0;
      else
                count = 0;
      while(count <240)
      {
                i = DQ_Read;
                if(i ==0)
                {
                Delay_us(1);
                count++;
                }
                break;
      }
      
      if(count >= 240)
                return 0;
      else
                {
                        Delay_us(750);
                        i = DQ_Read;
                        printf("\r\n i = %d\r\n ",i);
                        return 1;
                }               
}

void ds18b20_TransCmd(void)
{
      ds18b20_Config();

      ds18b20_WriteCmd(0xcc);//1100 1100
      ds18b20_WriteCmd(0x44);//0100 0100
}

void ds18b20_ReadCmd(void)
{
      ds18b20_Config();

      ds18b20_WriteCmd(0xcc);//1100 1100
      ds18b20_WriteCmd(0xbe);//1011 1110
}

float ds18b20_GetTemp(void)
{
      uint8_t tempH = 0, tempL = 0, temp = 0;
      float tem = 0;

      ds18b20_TransCmd();
      Delay_ms(1000);
      
      ds18b20_ReadCmd();

      tempL = ds18b20_ReadData();
      tempH = ds18b20_ReadData();

//      printf("\r\n 0x%d \r\n", tempH);
//      printf("\r\n 0x%d \r\n", tempL);
      
      temp = (tempH << 8) + tempL;
      tem =temp * 0.0625;
      printf("\r\n tem %f \r\n", tem);

      return tem;
}

void NOP(void)
{
      uint8_t i = 1;
      i--;
}
用示波器看过延时程序的实现是正确的。复位函数里的复位信号给的也是正确的。
电路图里左边是电源线,中间是数据线,右边是地线

aszrf 发表于 2016-5-4 13:23:37

:):(:D:D:'(:P

dsjsjf 发表于 2016-5-4 13:25:54

设置成开漏输出,外接上拉电阻,使用时不需要切换输入输出,试试

a6552918 发表于 2016-5-4 13:26:10

应该配置为输入浮空。

jinglixixi 发表于 2016-5-4 13:27:41

DS18B20数据端是否加了上拉电阻。

zhoupxa 发表于 2016-5-4 13:32:37

GPIO应设置为漏极开路

huaiqiao 发表于 2016-5-4 13:37:57

其实这种Onewire的,要注意时序问题

power568 发表于 2016-5-4 13:41:29

确定总线时间和手册给出的时间是否严格匹配,最好留有余量。。。

wolfgang2015 发表于 2016-5-4 13:44:23

检查电路,DQ是否做了上拉

风子 发表于 2016-5-4 14:42:16

帮顶      
页: [1] 2 3 4 5 6
查看完整版本: 基于STM32的DS18B20的问题