3933 views|5 replies

931

Posts

3

Resources
The OP
 

SHT31 evaluation + try to read sensor I2C bus data [Copy link]

 

I originally planned to modify the example and add the function of serial port outputting temperature and humidity data, but I don't have the J-LINK download tool for the time being. At the same time, I saw that some forum friends tried to download and burn but failed. So I thought it would be better to directly intercept the data on the I2C bus. In this way, I don't need to make any changes to the original evaluation board, and I can just use my expansion board. So I used a ready-made STM32L412 board for the experiment. The following figure shows the experimental setup:

The I2C data on the evaluation board was obtained through a logic analyzer. The evaluation board reads and writes the sensor once per second:

The actual operation is to write the command first, then wait for nearly 1 second before reading it out, so the timing diagram captured from the logic analyzer is read first and written later:

The read operation is to send the address code 139 first, and then read out 6 bytes of data continuously:

From the data sheet, we know that the first 3 bytes are temperature data, that is, 16-bit temperature data plus 1-byte checksum, and the last 3 bytes are humidity data, also 16-bit humidity data plus 1-byte checksum:

The command written is a 16-bit command, the address code is 138:

Based on these data, I wrote a piece of code to read out these 6 bytes of data. The following is the code for reading the I2C bus:

Read a byte:

/******************************************************
*Program name: Read_I2C
*Function: Read data on the I2C bus
*Input parameter: None
*Return parameter: Read data (1 byte)
******************************************************/
uint8_t Read_I2C(void)
{
uint8_t dat,i;
//Start reading one byte of data
for(i=0;i<8;i++){
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 0);
dat <<= 1;
if(HAL_GPIO_ReadPin(SI2C_SDA_GPIO_Port,SI2C_SDA_Pin) == 1) dat |= 0x01;
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 1);
}
return dat;
}

Here is the code to read all the data:

/******************************************************
*Program name: Intercept_I2C
*Function: intercept read data on I2C bus
*Input parameter: None
*Return parameter:
******************************************************/
void Intercept_I2C(void)
{
uint8_t i,d[7];
uint32_t temp=0,hum=0;
uint32_t d_t,d_h;
//Wait for I2C start signalwhile
(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin)==1){
while(HAL_GPIO_ReadPin(SI2C_SDA_GPIO_Port,SI2C_SDA_Pin)==1);
}

// while(Read_I2C() != 139) //Read address appears on the I2C bus
for(i = 0; i < 7; i++)
d = Read_I2C();
/*
temp = Read_I2C(); //Get the upper eight bits
temp <<= 8;
temp |= (uint16_t )Read_I2C();
hum = Read_I2C(); //Check byte (discarded)
hum = Read_I2C();
hum <<= 8;
hum |= (uint16_t )Read_I2C();
*/
d_t = d[1];
d_t <<= 8;
d_t |= d[2];
// temp = (d_t * 175 / 65535) - 45;
temp = d_t *1000 / 267 - 4500;
d_h = d[4];
d_h <<= 8;
d_h |= d[5];
hum = d_h * 10000 / 65535;
LCD_write_value(12,3,5,0,1,temp);
LCD_write_value(12,4,5,0,1,hum);
LCD_write_value(50,3,5,0,1,d_t);
LCD_write_value(50,4,5,0,1,d _h);

LCD_write_value(0,0,3,0,1,d[0]);
// LCD_write_value(24,0,3,0,1,d[0]);
LCD_write_value(0,1,3,0,1,d[1]);
LCD_write_value(24,1,3,0,1,d[2]);
LCD_write_value(50,1,3,0,1,d[3]);
LCD_write_value(0,2,3,0,1,d[4]);
LCD_write_value(24,2,3,0,1,d[5]);
LCD_write_value(50,2,3,0,1,d[6]);
HAL_Delay(2);
}

After repeated tests, these data were basically read out, but they seemed not quite correct, especially the calculation process was incorrect, and the calculated temperature and humidity data were very different from the actual display. In the figure below, the first line is the read address code, the second and third lines are the temperature and humidity data and the check code, the blue circles are the read temperature and humidity data, and the red circles are the calculated temperature and humidity values, which are inconsistent with the actual display, especially the humidity data jumps and fluctuates, and is unstable.

According to the data sheet, the calculation formulas for temperature and humidity are as follows:

However, the data calculated by the code I wrote according to this formula is different from the manual calculation. I don’t know where the code is wrong. Here is the code:

d_t = d[1];
d_t <<= 8;
d_t |= d[2];
// temp = (d_t * 175 / 65535) - 45;
temp = d_t *1000 / 267 - 4500;
d_h = d[4];
d_h <<= 8;
d_h |= d[5];
hum = d_h * 10000 / 65535; //Round to two decimal places

I changed the variable type from 16-bit unsigned to 32-bit unsigned, but the result was still wrong.

I couldn't get the correct temperature and humidity values by manual calculation. I don't know where the problem lies.

When reading and writing I2C bus data, I ignored the ACK after each byte. Could this be the reason for the incorrect data acquisition? According to the timing diagram, 1 ACK is 3 microseconds, and the time to the start of the next byte is 5.125 microseconds, a total of 8.125 microseconds. I don't know how long it takes from the read byte function to the next re-entry, but this should not affect the synchronization, because reading the next byte is based on the SCL clock, unless the time to return to the next re-entry is less than 3 microseconds.


This content is originally created by EEWORLD forum user hujj . If you want to reprint or use it for commercial purposes, you must obtain the author's consent and indicate the source

I2C_test_5.jpg (414.21 KB, downloads: 0)

I2C_test_5.jpg

I2C_test_6.jpg (372.14 KB, downloads: 0)

I2C_test_6.jpg

I2C_test_7.jpg (376.38 KB, downloads: 0)

I2C_test_7.jpg

Latest reply

It may still be a timing problem, and the captured data is wrong   Details Published on 2020-1-20 21:35
 
 

1w

Posts

25

Resources
2
 

Is it caused by data overflow?

Comments

It seems not. The data type I use is 32-bit unsigned. For 16-bit data, multiplying it by 175 and then dividing it by 65535 should not overflow.   Details Published on 2020-1-20 16:59
 
 
 

931

Posts

3

Resources
3
 
dcexpert posted on 2020-1-20 16:42 Is it caused by data overflow?

It seems not. The data type I use is 32-bit unsigned. For 16-bit data, multiplying it by 175 and then dividing it by 65535 should not overflow.

 
 
 

1w

Posts

25

Resources
4
 

It may still be a timing problem, and the captured data is wrong

Comments

However, the address data read out is correct and there is no error.  Details Published on 2020-1-20 22:30
 
 
 

931

Posts

3

Resources
5
 
dcexpert posted on 2020-1-20 21:35 It may still be a timing problem, and the captured data is wrong

However, the address data read out is correct and there is no error.

 
 
 

931

Posts

3

Resources
6
 

After careful investigation, I found that the reason why I failed to obtain the correct data was because I ignored the ACK. I added the code of waiting for ACK when reading the I2C data, and the data obtained was correct. The code is as follows:

/******************************************************
*Program name: Read_I2C
*Function: Read data on the I2C bus
*Input parameter: None
*Return parameter: Read data (1 byte)
******************************************************/
uint8_t Read_I2C(void)
{
uint8_t dat,i;
//Start reading one byte of data
for(i=0;i<8;i++){
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 0);
dat <<= 1;
if(HAL_GPIO_ReadPin(SI2C_SDA_GPIO_Port,SI2C_SDA_Pin) == 1) dat |= 0x01;
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 1);
}
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 0);
while(HAL_GPIO_ReadPin(SI2C_SCL_GPIO_Port,SI2C_SCL_Pin) == 1); //Waiting for ACK
return dat;
}

The following are the temperature and humidity data obtained by the STM32L412 development board:

Sometimes there will be a small error, which should be due to the incomplete synchronization of the two refreshes:

So far, the test is successful. The data was captured using the STM32L412KB development board, and the display screen is LCD5110.

 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list