/* i2c - Simple example
Simple I2C example that shows how to initialize I2C
as well as reading and writing from and to registers for a sensor connected over I2C.
The sensor used in this example is a SHT3X inertial measurement unit.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/i2c.h"
#define SHT31_DEFAULT_ADDR 0x44 /**< SHT31 Default Address */
#define SHT31_MEAS_HIGHREP_STRETCH \
0x2C06 /**< Measurement High Repeatability with Clock Stretch Enabled */
#define SHT31_MEAS_MEDREP_STRETCH \
0x2C0D /**< Measurement Medium Repeatability with Clock Stretch Enabled */
#define SHT31_MEAS_LOWREP_STRETCH \
0x2C10 /**< Measurement Low Repeatability with Clock Stretch Enabled*/
#define SHT31_MEAS_HIGHREP \
0x2400 /**< Measurement High Repeatability with Clock Stretch Disabled */
#define SHT31_MEAS_MEDREP \
0x240B /**< Measurement Medium Repeatability with Clock Stretch Disabled */
#define SHT31_MEAS_LOWREP \
0x2416 /**< Measurement Low Repeatability with Clock Stretch Disabled */
#define SHT31_READSTATUS 0xF32D /**< Read Out of Status Register */
#define SHT31_CLEARSTATUS 0x3041 /**< Clear Status */
#define SHT31_SOFTRESET 0x30A2 /**< Soft Reset */
#define SHT31_HEATEREN 0x306D /**< Heater Enable */
#define SHT31_HEATERDIS 0x3066 /**< Heater Disable */
#define SHT31_REG_HEATER_BIT 0x0d /**< Status Register Heater Bit */
#define portTICK_RATE_MS 1
#define I2C_MASTER_SDA_IO 19 //CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
#define I2C_MASTER_SCL_IO 18 //CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 10000 /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 150
#define SHT3X_SENSOR_ADDR 0x44 /*!< Slave address of the SHT3X sensor */
/**
* @brief Read a sequence of bytes from a SHT3X sensor registers
*/
static esp_err_t SHT3X_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{
/*esp_err_t i2c_master_write_read_device(i2c_port_t i2c_num, uint8_t device_address,
const uint8_t* write_buffer, size_t write_size,
uint8_t* read_buffer, size_t read_size,
TickType_t ticks_to_wait)
*/
return i2c_master_write_read_device(I2C_MASTER_NUM, SHT3X_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
}
/**
* @brief Write N byte to a SHT3X sensor register
*/
static esp_err_t SHT3X_register_write(uint8_t reg_addr, uint8_t *data,int len)
{
int ret = 0;
uint8_t *wr_dat = (uint8_t*) malloc(len+1);
if(wr_dat==NULL)
return -1;
wr_dat[0] = reg_addr;
for(int i=0;i<len;i++)
{
wr_dat[i+1] = data[i];
}
ret = i2c_master_write_to_device(I2C_MASTER_NUM, SHT3X_SENSOR_ADDR, wr_dat, len+1, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
free(wr_dat);
return ret;
}
static esp_err_t SHT3X_write(uint8_t *data,int len)
{
int ret = 0;
ret = i2c_master_write_to_device(I2C_MASTER_NUM, SHT3X_SENSOR_ADDR, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
return ret;
}
/**
* @brief i2c master initialization
*/
static esp_err_t i2c_master_init(void)
{
int i2c_master_port = I2C_MASTER_NUM;
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
void delay(int ms)
{
vTaskDelay(ms);
}
/**
* Performs a CRC8 calculation on the supplied values.
*
* @param data Pointer to the data to use when calculating the CRC8.
* @param len The number of bytes in 'data'.
*
* @return The computed CRC8 value.
*/
static uint8_t crc8(const uint8_t *data, int len) {
/*
*
* CRC-8 formula from page 14 of SHT spec pdf
*
* Test data 0xBE, 0xEF should yield 0x92
*
* Initialization data 0xFF
* Polynomial 0x31 (x8 + x5 +x4 +1)
* Final XOR 0x00
*/
const uint8_t POLYNOMIAL=(0x31);
uint8_t crc=(0xFF);
for (int j = len; j; --j) {
crc ^= *data++;
for (int i = 8; i; --i) {
crc = (crc & 0x80) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
}
}
return crc;
}
bool writeCommand(uint16_t command) {
uint8_t cmd[2];
cmd[0] = command >> 8;
cmd[1] = command & 0xFF;
return SHT3X_write(cmd, 2);
}
bool readTempHum(float *tempOut,float *humOut)
{
uint8_t readbuffer[6]={0};
writeCommand(SHT31_MEAS_HIGHREP);
delay(20);
i2c_master_read_from_device(I2C_MASTER_NUM, SHT3X_SENSOR_ADDR,readbuffer, sizeof(readbuffer),I2C_MASTER_TIMEOUT_MS / portTICK_RATE_MS);
if (readbuffer[2] != crc8(readbuffer, 2) ||
readbuffer[5] != crc8(readbuffer + 3, 2))
return false;
int32_t stemp = (int32_t)(((uint32_t)readbuffer[0] << 8) | readbuffer[1]);
// simplified (65536 instead of 65535) integer version of:
// temp = (stemp * 175.0f) / 65535.0f - 45.0f;
stemp = ((4375 * stemp) >> 14) - 4500;
*tempOut = (float)stemp / 100.0f;
uint32_t shum = ((uint32_t)readbuffer[3] << 8) | readbuffer[4];
// simplified (65536 instead of 65535) integer version of:
// humidity = (shum * 100.0f) / 65535.0f;
shum = (625 * shum) >> 12;
*humOut = (float)shum / 100.0f;
return true;
}
void sht3x_app_main(void)
{
ESP_ERROR_CHECK(i2c_master_init());
printf("I2C initialized successfully,BUILD:[%s %s]",__DATE__,__TIME__);
int cnt = 0;
bool ret = true;
float temp = 0.0;
float humidity = 0.0;
float tempAll = 0;
float humAll = 0;
while(true)
{
int count = 100;
tempAll = 0;
humAll = 0;
for (size_t i = 0; i < count; i++)
{
temp = 0;
humidity = 0;
ret = readTempHum(&temp,&humidity);
if(!ret)
{
printf("=====Read Error=====\n");
break;
}
tempAll+=temp;
humAll+=humidity;
}
temp = tempAll/count;
humidity = humAll/count;
cnt++;
printf("[%d] temp=%.2f,hum=%.2f \n",cnt,temp,humidity);
vTaskDelay(100);
}
}
[ESP32] IIC驱动温度湿度传感器SHT3x
于 2022-12-07 21:00:56 首次发布