Как получить идентификатор устройства DSTH01 I2C Communication?
Я пытаюсь получить влажность и температуру, используя 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++);
}
2 ответа
ОБНОВЛЕНИЕ Ранее я удалил этот ответ, потому что я думал, что он неисправен и бесполезен, но, возможно, здесь есть что-то для OP...
Как вы можете получать отрицательные значения от 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
Спасибо вам, ребята, за вашу ценную поддержку и предложение. Я оставил метод ударов битом. Пробовал аппаратную функцию. Наконец я получил результаты. Это фрагмент кода:-
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();