static const char *TAG = "i2c-temp";
static unsigned char sht30_buf[6]={0}; 
static float g_temp=0.0, g_rh=0.0;

/**
 * I2C主机初始化
 */
static esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = IO_SENSOR_SDA;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = IO_SENSOR_SCL;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
    conf.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);
}

/* 
 * 初始化sht30
 * _________________________________________________________________
 * | start | slave_addr + wr_bit + ack | write 1 byte + ack  | stop |
 * --------|---------------------------|---------------------|------|
 */
int sht30_init(void)
{
    int ret;
    //配置SHT30的寄存器
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();                  // 新建操作I2C句柄
    i2c_master_start(cmd);                                         // 启动I2C
    i2c_master_write_byte(cmd, SHT30_WRITE_ADDR << 1 | WRITE_BIT, ACK_CHECK_EN);  // 发地址+写+检查ack
    i2c_master_write_byte(cmd, CMD_FETCH_DATA_H, ACK_CHECK_EN);                   // 发数据高8位+检查ack
    i2c_master_write_byte(cmd, CMD_FETCH_DATA_L, ACK_CHECK_EN);                   // 发数据低8位+检查ack
    i2c_master_stop(cmd);                                                         // 停止I2C
    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_RATE_MS);      //I2C发送
    i2c_cmd_link_delete(cmd);                                                     //删除I2C句柄
    return ret;

}

/*
* sht30校验算法
* @param[in]   pdata                  :需要校验的数据
* @param[in]   nbrOfBytes              :需要校验的数据长度
* @retval      int                  :校验值
*/
unsigned char SHT3X_CalcCrc(unsigned char *data, unsigned char nbrOfBytes)
{
    unsigned char bit;                   // bit mask
    unsigned char crc = 0xFF;            // calculated checksum
    unsigned char byteCtr;               // byte counter
    unsigned int POLYNOMIAL =  0x131;    // P(x) = x^8 + x^5 + x^4 + 1 = 100110001

    // calculates 8-Bit checksum with given polynomial
    for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++) {
        crc ^= (data[byteCtr]);
        for(bit = 8; bit > 0; --bit) {
            if(crc & 0x80) {
                crc = (crc << 1) ^ POLYNOMIAL;
            }  else {
                crc = (crc << 1);
            }
        }
    }
    return crc;
}

/*
* sht30数据校验
* @param[in]   pdata                  :需要校验的数据
* @param[in]   nbrOfBytes              :需要校验的数据长度
* @param[in]   checksum              :校验的结果
* @retval      int                  :0成功,其他失败
*/
unsigned char SHT3X_CheckCrc(unsigned char *pdata, unsigned char nbrOfBytes, unsigned char checksum)
{
    unsigned char crc;
    crc = SHT3X_CalcCrc(pdata, nbrOfBytes);// calculates 8-Bit checksum
    if(crc != checksum) 
    {   
        return 1;           
    }
    ESP_LOGI(TAG, "error crc:,%d", crc);
    return 0;              
}


/**
 * 获取sht30温湿度
 * ______________________________________________________________________________________
 * | start | slave_addr + rd_bit + ack | read 1 byte + ack  | read 1 byte + nack | stop |
 * --------|---------------------------|--------------------|--------------------|------|
 */
int sht30_get_value(void)
{
    ESP_LOGI(TAG, "begin sht30 get value");
    int ret;
    //配置SHT30的寄存器
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();                                    //新建操作I2C句柄
    i2c_master_start(cmd);                                                           //启动I2C
    i2c_master_write_byte(cmd, SHT30_WRITE_ADDR << 1 | READ_BIT, ACK_CHECK_EN);      //发地址+读+检查ack
    i2c_master_read_byte(cmd, &sht30_buf[0], ACK_VAL);                               //读取数据+回复ack
    i2c_master_read_byte(cmd, &sht30_buf[1], ACK_VAL);                               //读取数据+回复ack
    i2c_master_read_byte(cmd, &sht30_buf[2], ACK_VAL);                               //读取数据+回复ack
    i2c_master_read_byte(cmd, &sht30_buf[3], ACK_VAL);                               //读取数据+回复ack
    i2c_master_read_byte(cmd, &sht30_buf[4], ACK_VAL);                               //读取数据+回复ack
    i2c_master_read_byte(cmd, &sht30_buf[5], NACK_VAL);                              //读取数据+不回复ack
    i2c_master_stop(cmd);                                                            //停止I2C
    ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_RATE_MS);         //I2C发送
    if(ret!=ESP_OK)
    {
        return ret;
    }
    i2c_cmd_link_delete(cmd);                                                       //删除I2C句柄
    //校验读出来的数据,算法参考sht30 datasheet
    if( (!SHT3X_CheckCrc(sht30_buf,2,sht30_buf[2])) && (!SHT3X_CheckCrc(sht30_buf+3,2,sht30_buf[5])) )
    {
        ret = ESP_OK;//成功
    }
    else
    {
        ret = 1;
    }
    ESP_LOGI(TAG, "ret:%d",ret);
    return ret;
}

static void i2c_temp_task(void *arg)
{
    ESP_LOGI(TAG, "begin temp task");
    while (1) {       
        //获取温湿度
        if(sht30_get_value()==ESP_OK)   
        {
            //算法参考sht30 datasheet
            g_temp    =( ( (  (sht30_buf[0]*256) +sht30_buf[1]) *175   )/65535.0  -45  );
            g_rh  =  ( ( (sht30_buf[3]*256) + (sht30_buf[4]) )*100/65535.0) ;
            ESP_LOGI("SHT30", "temp:%4.2f ℃ 
", g_temp); // ℃打印出来是乱码,所以用C
            ESP_LOGI("SHT30", "hum:%4.2f %%RH 
", g_rh);
        }
        vTaskDelay(6000/portTICK_RATE_MS);
    }
    vTaskDelete(NULL);
}

void i2c_temp_start(void)
{
    ESP_LOGI(TAG, "start get temperature and humidity");
    ESP_ERROR_CHECK(i2c_master_init());
    sht30_init(); 
    vTaskDelay(500/portTICK_RATE_MS);  
    xTaskCreate(i2c_temp_task, "i2c_temp_task", 1024 * 2, (void *)0, 10, NULL);
}