/* * sht30_driver.c * * Created on: 30. apr. 2025 * Author: Christian L. V. Madsen (OZ1CM) */ #include "sht30_driver.h" #define REV16_A(X) (((X) << 8) | ((X)>>8)) #define REV8_A(X) (((X) << 4) | ((X)>>4)) static int isStructOk(SHT30_Struct_Type *inst){ if(inst == NULL)return 0; if(inst->i2c_transfer_inst == NULL)return 0; if(inst->i2c_transfer_evt == NULL)return 0; return 1; } uint8_t crc8_i2c_u16(uint16_t input) { uint8_t crc = 0xFF; uint8_t poly = 0x31; // Process MSB first (big endian) for (int i = 1; i >= 0; i--) { uint8_t byte = (input >> (8 * i)) & 0xFF; crc ^= byte; for (uint8_t j = 0; j < 8; j++) { if (crc & 0x80) crc = (crc << 1) ^ poly; else crc <<= 1; } } return crc; // Final XOR is 0x00, so this is the final CRC } static int readRegister(SHT30_Struct_Type *inst, uint8_t *data_addr, uint8_t *data, uint32_t len){ // Write what kind of addr we would like to read from: int ret = inst->i2c_transfer_evt(inst->i2c_transfer_inst,data_addr,2, SHT30_I2C_SET); // Read data: ret += inst->i2c_transfer_evt(inst->i2c_transfer_inst,data,len, SHT30_I2C_GET); return ret; } static int writeRegister(SHT30_Struct_Type *inst, uint16_t data_addr, uint8_t *data, uint32_t len){ // Write what kind of addr we would like to read from: inst->i2c_transfer_evt(inst->i2c_transfer_inst,(uint8_t *)&data_addr,2, SHT30_I2C_SET); // Write data: inst->i2c_transfer_evt(inst->i2c_transfer_inst,data,len, SHT30_I2C_SET); return 0; } int sht30_writeCmd(SHT30_Struct_Type *inst, uint16_t command){ if(!isStructOk(inst))return 1; int ret; uint8_t buffer[2] = {0}; buffer[0] = (command >> 8) & 0xff; buffer[1] = (command & 0xff); ret = inst->i2c_transfer_evt(inst->i2c_transfer_inst,buffer,sizeof(buffer), SHT30_I2C_SET); return ret; } static int SHT30_resetConnection(SHT30_Struct_Type *inst){ if(!isStructOk(inst))return 1; for(int i = 0; i< 3; i++){ int ret = 0; ret = sht30_writeCmd(inst,0x30A2); // Soft reset device ret = sht30_writeCmd(inst,0x272A); // Measurement Command for Periodic Data Acquisition Mode if(ret == 0){ return 0; } } return 1; } void SHT30_calcRawData(SHT30_Struct_Type *p){ p->Message.RawTemp = REV16_A(p->Message.RawTemp); p->Message.RawHumidity = REV16_A(p->Message.RawHumidity); if(crc8_i2c_u16(p->Message.RawTemp) != p->Message.CRC_Temp) return; if(crc8_i2c_u16(p->Message.RawHumidity) != p->Message.CRC_Humidity) return; // Calc Temperature p->Temperature_mC = p->Message.RawTemp * 17500; p->Temperature_mC = p->Temperature_mC >> 16; p->Temperature_mC -= 4500; // Calc Humidity p->Humidity = p->Message.RawHumidity * 100; p->Humidity = p->Humidity >> 16; } int sht30_ReadData(SHT30_Struct_Type *inst){ int ret; uint8_t reg[2] = {0xe0,0x00}; ret = readRegister(inst, reg, (void*)&inst->Message, sizeof(SHT30_Message_Type)); if(ret != 0){ SHT30_resetConnection(inst); return 1; }else{ SHT30_calcRawData(inst); return 0; } } int sht30_init(SHT30_Struct_Type *inst, void *i2c_transfer_inst, setGet_I2C_Event_fpt i2c_transfer_evt){ if(inst == NULL)return -1; if(i2c_transfer_inst == NULL)return -1; if(i2c_transfer_evt == NULL)return -1; inst->i2c_transfer_inst = i2c_transfer_inst; inst->i2c_transfer_evt = i2c_transfer_evt; SHT30_resetConnection(inst); return 0; }