Как получить идентификатор устройства связи DSTH01 I2C?

Я пытаюсь получить влажность и температуру с помощью DSTH01. Но я не могу получить правильное значение. Я получаю влажность как -24 и температуру как -50. Я не знаю, где я пропал. Пожалуйста, помогите мне решить мою проблему. Первоначально, если я получу идентификатор устройства, это поможет решить мою проблему. Я использую PIC18f2520 с кристаллом 10 МГц.

Я сделал следующее подключение:

 PIN1-GND
 PIN2-Pull Up to 3.3 V with 10k- Microcontroller  PIN_C3
 PIN3 - Pull Up to 3.3 V with 10k-Microcontroller  PIN_C4
 PIN4 - Microcontroller  PIN_A2
 PIN5 - 3.3 V 

Вот мой исходный код:

 #define DSTH01_SCK  PIN_C3
 #define DSTH01_SDA  PIN_C4
 #define DSTH01_CSB  PIN_A2

 #define SDA_H output_high(DSTH01_SDA)
 #define SDA_L output_low(DSTH01_SDA)
 #define SCK_H output_high(DSTH01_SCK)
 #define SCK_L output_low(DSTH01_SCK)
 #define CS_H  output_high(DSTH01_CSB)
 #define CS_L  output_low(DSTH01_CSB)

 #define SlaveAddress      0x40
 #define RegisterAddress0  0x00
 #define RegisterAddress1  0x01
 #define RegisterAddress2  0x02
 #define RegisterAddress3  0x03
 #define RegisterAddress11 0x11

 void small_delay(void);
 void I2C_START(void);
 void I2C_STOP(void);
 void I2C_WRITE(unsigned int8 Data);
 int8 I2C_READ(void);
 void I2C_ACK(unsigned int8 a);
 int8 I2C_SEND(unsigned int8 SlaveAdd,unsigned int8 RegisterAdd,unsigned  int8 *s);
 int8 I2C_RECEIVE(unsigned int8 SlaveAdd,unsigned int8 RegisterAdd,unsigned int8 *s);
 void Temperature_READ(unsigned int8 *s);
 void RelativeHumidity_READ(unsigned int8 *s);
 int1 Check_SDA(void);

 unsigned int8 Ack;
 unsigned int8 id;
 unsigned int8 RelativeHumidity =0;
 unsigned int8 Temperature =0;
 unsigned int8 Start1=0x01;
 unsigned int8 Start2=0x11;

 void main(void)
 {    
     set_tris_c(0x80);
     delay_ms(100);delay_ms(100);  
     output_low(PIN_C3);
     output_high(PIN_C4);
     output_low(PIN_A2);
     enable_interrupts(int_rda);
     enable_interrupts(global);   
     delay_ms(100);delay_ms(100);
     delay_ms(100);delay_ms(100);
     delay_ms(100);delay_ms(100);  

     CS_L;
     I2C_RECEIVE(SlaveAddress,RegisterAddress11,&id);
     while (1)
     {
            RelativeHumidity_READ(&RelativeHumidity);
            Temperature_READ(&Temperature);
            delay_ms(100);delay_ms(100);
            delay_ms(100);delay_ms(100);
            delay_ms(100);delay_ms(100);
            printf("\r\nRelativeHumidity:%d",RelativeHumidity);
            printf("\tTemperature:%d",Temperature);
      }  
  }

void I2C_START()
{
   SDA_H;small_delay();
   SCK_H;small_delay();
   SDA_L;small_delay();
   SCK_L;small_delay();
 }
void I2C_STOP()
{
   SDA_L;small_delay();
   SCK_H;small_delay();
   SDA_H;small_delay();
}  
 void I2C_WRITE(unsigned  int8 Data)
{
   unsigned  int8 i;
   for(i=0;i<8;i++)
   {
      if(Data&0x80)
         {SDA_H;small_delay();}
      else
         SDA_L;small_delay();
         SCK_H;small_delay();
         SCK_L;small_delay();
         Data<<=1;
   }
   SDA_H;small_delay();
   SCK_H;small_delay();
   //if(SDA==1)
   if(Check_SDA()==1)
      Ack=0;
   else
      Ack=1;
      SCK_L;small_delay();
}  
unsigned  int8 I2C_READ()
{
   unsigned  int8 Data=0;
   unsigned  int8 i;
   SDA_H;
   for(i=0;i<8;i++)
   {
      SCK_L;small_delay();
      SCK_H;small_delay();
      Data<<=1;
      //if(SDA==1)
     if(Check_SDA()==1)
      Data=Data+1; 
   }
   SCK_L;small_delay();
   return Data;
}
void I2C_ACK(unsigned  int8 a)
{
   if(a==0)
      {SDA_L;small_delay();}
   else
      SDA_H;small_delay();
      SCK_H;small_delay();
   SCK_L;small_delay();
}
unsigned int8 I2C_SEND(unsigned  int8 SlaveAdd,unsigned  int8 RegisterAdd,unsigned  int8 *s)
{
   SlaveAdd=SlaveAdd<<1;
   I2C_START();
   I2C_WRITE(SlaveAdd);
   if(Ack==0)
      return 0;
   I2C_WRITE(RegisterAdd);
      if(Ack==0)
         return 0;
      I2C_WRITE(*s);
         if(Ack==0)
         return 0;
         I2C_STOP();
   return 1;
}
unsigned  int8 I2C_RECEIVE(unsigned  int8 SlaveAdd,unsigned  int8 RegisterAdd,unsigned  int8 *s)
{
   SlaveAdd = SlaveAdd<<1;
   I2C_START();
   I2C_WRITE(SlaveAdd);
   if(Ack==0)
   return 0;
   I2C_WRITE(RegisterAdd);
   if(Ack==0)
   return 0;
   I2C_START();

   I2C_WRITE(SlaveAdd+1);
   if(Ack==0)
      return 0;
      *s=I2C_READ();
      I2C_ACK(1);
      I2C_STOP();
   return 1;
}
void RelativeHumidity_READ(unsigned  int8 *s)
{
   unsigned  int8 Status=1;
   unsigned  int8 RelativeHumidityH;
   unsigned  int8 RelativeHumidityL;
   unsigned  int16 RelHum;
   I2C_SEND(SlaveAddress,RegisterAddress3,&Start1);
   while(Status==1)
   {
      I2C_RECEIVE(SlaveAddress,RegisterAddress0,&Status);
   }
   I2C_RECEIVE(SlaveAddress,RegisterAddress1,&RelativeHumidityH);
   I2C_RECEIVE(SlaveAddress,RegisterAddress2,&RelativeHumidityL);
   RelHum=RelativeHumidityH;
   RelHum=RelHum<<8;
   RelHum+=RelativeHumidityL;
   RelHum=RelHum>>4;
   *s=RelHum/16-24;
}
void Temperature_READ(unsigned  int8 *s)
{
   unsigned  int8 Status=1;
   unsigned  int8 TemperatureH;
   unsigned  int8 TemperatureL;
   unsigned  int16 Temp;
   I2C_SEND(SlaveAddress,RegisterAddress3,&Start2);
   while(Status==1)
   {
      I2C_RECEIVE(SlaveAddress,RegisterAddress0,&Status);
   }
   I2C_RECEIVE(SlaveAddress,RegisterAddress1,&TemperatureH);
   I2C_RECEIVE(SlaveAddress,RegisterAddress2,&TemperatureL);
   Temp=TemperatureH;
   Temp<<=8;
   Temp+=TemperatureL;
   Temp>>=2;
   *s=Temp/32-50;
}
int1 Check_SDA(void)
{
   int1 a;
   set_tris_c(0x90);//10010000,RX,0,0,SDA,0,0,0,0
   small_delay();
   if(input(DSTH01_SDA)){a =1; }
   else{a = 0;}
   set_tris_c(0x80);//10000000
   small_delay();
   return a;
}
void small_delay(void)
{
   char a;
   for(a = 0;a < 10;a++);
}

person RFK    schedule 25.04.2015    source источник
comment
Как вы можете получать отрицательные значения из unsigned переменных?   -  person Weather Vane    schedule 25.04.2015
comment
Используйте printf %u для печати unsigned ints   -  person TheCodeArtist    schedule 09.05.2015
comment
Кто-нибудь может сказать мне, почему я получаю -Ve Marks? Есть ли проблемы с моим вопросом? Здесь идентификатор таблицы данных www.dorji.com/docs/data/DSTH01.pdf .. Пожалуйста, ответьте.   -  person RFK    schedule 09.05.2015
comment
@RFK Первоначально я опубликовал ответ после прочтения того же листа данных, но удалил его из-за неопределенности. Я нашел по крайней мере одну ошибку в таблице данных (таблица 8, которая вместо температуры повторяет таблицу 6 для влажности). Я заметил там какой-то код, который вы, возможно, скопировали, возможно, он тоже неисправен. Я предложил вам попробовать прочитать значения и отобразить их (в шестнадцатеричном или двоичном формате) без каких-либо сдвигов или корректировок, чтобы увидеть, какую корреляцию вы получаете между различными входными данными и полученными данными. Будьте методичны в этом.   -  person Weather Vane    schedule 09.05.2015
comment
@RFK Я восстановил более ранний ответ, в котором я подумал, что вы, возможно, дублируете сдвиг данных, необходимый для деления. Если это отвлекающий маневр, извините, скажите мне, и я удалю его снова.   -  person Weather Vane    schedule 09.05.2015
comment
@Weather Vane спасибо за ответ. Вам не нужно удалять его. Да, вы правы ... в таблице данных есть некоторые ошибки. Пожалуйста, посмотрите мой ответ, который я уже опубликовал. Если хотите, пожалуйста, дайте несколько мерков + ve, вот и все.   -  person RFK    schedule 13.05.2015
comment
@RFK, пожалуйста, примите мой ответ, если он был правильным и помог вам.   -  person Weather Vane    schedule 13.05.2015


Ответы (2)


ОБНОВЛЕНИЕ Ранее я удалил этот ответ, потому что считал его ошибочным и бесполезным, но, возможно, здесь есть что-то для ОП...

Как вы можете получать отрицательные значения из unsigned переменных?

Глядя на лист данных DSTH01, относительная влажность % рассчитывается как (RH/16)-24 и это говорит о том, что в вашем коде есть ненужная строка

RelHum=RelHum>>4;               // remove this line
*s=RelHum/16-24;

Далее в таблице данных говорится, что температура рассчитывается с помощью (TEMP/32)-50, и это говорит о том, что в вашем коде есть еще одна ненужная строка.

Temp>>=2;                       // remove this line
*s=Temp/32-50;

при условии, что вы правильно прочитали данные I2C.

В таблице данных есть ошибка в таблице 6, которая показывает, что влажность равна 11 битам. У него также есть ошибка в таблице 8, которая вместо отображения температуры повторяет ту же таблицу, что и для влажности, таблица 6.

Я думаю, вы делаете дополнительные деления, потому что в таблице данных указано, что результаты 12-битные и 14-битные соответственно, но вывод состоит в том, что данные выровнены по левому краю, поэтому требуются деления (на самом деле сдвиги), но только однажды! Я предлагаю вам выполнить преобразования, как указано в таблице данных: используйте DATAh и DATAl, и они дополняются нулями справа. Так что код может быть лучше, как

RelHum = (RelHum >> 4) - 24;    // div 16
*s = (unsigned int8)RelHum;     // now cast to 8-bit

а также

Temp = (Temp >> 5) - 50;        // div 32
*s = (unsigned int8)Temp;       // now cast to 8-bit
person Weather Vane    schedule 25.04.2015

Спасибо, ребята, за вашу ценную поддержку и предложение. Я оставил битовый метод. Пробовал аппаратную функцию. Наконец я получил результаты. Это фрагмент кода: -

i2c_start();
i2c_write(0x80); // Device address
i2c_write(0x11); // Data to device
i2c_start(); // Restart
i2c_write(0x81); // to change data direction
data=i2c_read(0); // Now read from slave
printf("\n\rID:%02X",data);
i2c_stop(); 
person RFK    schedule 13.05.2015