I'm trying to integrate a Sensirion SHT20 thermometer/hygrometer to the STM32. It uses a standard I2C interface, but with a wrinkle: after I send it a command to give me the temp (or humidity), I have to insert a delay before I attempt to read the reply. From the SHT20 datasheet (sorry this is kind of long):
I've verified that I'm talking with the device, by reading its user register (this doesn't require a delay). Regarding a temp read, here's what I've tried with no success:There are two different operation modes to communicate with the sensor: Hold Master mode or No Hold Master mode. In the first case the SCL line is blocked (controlled by sensor) during measurement process while in the latter case the SCL line remains open for other communication while the sensor is processing the measurement. No hold master mode allows for processing other I2C communication tasks on a bus while the sensor is measuring. A communication sequence of the two modes is displayed in Figure 15 and Figure 16, respectively.
In the hold master mode, the SHT2x pulls down the SCL line while measuring to force the master into a wait state. By releasing the SCL line the sensor indicates that internal processing is terminated and that transmission may be continued.
In no hold master mode, the MCU has to poll for the termination of the internal processing of the sensor. This is done by sending a Start condition followed by the I2C header (1000’0001) as shown in Figure 16. If the internal processing is finished, the sensor acknowledges the poll of the MCU and data can be read by the MCU. If the measurement processing is not finished the sensor answers no ACK bit and the Start condition must be issued once more.
When using the no hold master mode it is recommended to include a wait period of 20 μs after the reception of the sensor’s ACK bit (bit 18 in Figure 16) and before the Stop condition.
Code: Select all
int Thermometer::thermRead(uint8_t cmd, uint8_t *data, uint16_t len)
{
int rc;
m_i2c_cmd = i2c_cmd_link_create();
//ESP_LOGI(TAG, "i2cReadReg(): m_i2c_cmd is %x.", (unsigned) m_i2c_cmd);
ESP_ERROR_CHECK(i2c_master_start(m_i2c_cmd));
ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, SHT20_ADDR_WRITE, true));
ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, cmd, true));
ESP_ERROR_CHECK(i2c_master_start(m_i2c_cmd));
ESP_ERROR_CHECK(i2c_master_write_byte(m_i2c_cmd, SHT20_ADDR_READ, true));
// ESP_ERROR_CHECK(i2c_master_read(m_i2c_cmd, (uint8_t *) data, len, I2C_MASTER_LAST_NACK));
ESP_ERROR_CHECK(i2c_master_read(m_i2c_cmd, (uint8_t *) data, 1, I2C_MASTER_ACK));
ESP_ERROR_CHECK(i2c_master_read(m_i2c_cmd, (uint8_t *) data, 1, I2C_MASTER_ACK));
ESP_ERROR_CHECK(i2c_master_read(m_i2c_cmd, (uint8_t *) data, 1, I2C_MASTER_NACK));
ESP_ERROR_CHECK(i2c_master_stop(m_i2c_cmd));
rc = (i2c_master_cmd_begin(I2C_PORT_NBR, m_i2c_cmd, I2C_WAITTIME_TICKS));
Can anyone see a way to do this using the I2C library, or does it look like I'm going to have to bit-bang this one?
Thanks...