/********************************************************************************* * Copyright: (C) 2024 LingYun IoT System Studio * All rights reserved. * * Filename: sht20_fops.c * Description: This file is temperature and relative humidity sensor SHT20 code * * Version: 1.0.0(2024/05/08) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "2024/05/08 12:13:26" * * Pin connection: * * SHT20 Module IGKBoard * VCC <-----> 3.3V * SDA <-----> #Pin3(I2C1_SDA) * SCL <-----> #Pin5(I2C1_SCL) * GND <-----> GND * * /run/media/mmcblk1p1/config.txt: * * # Eanble I2C overlay * dtoverlay_i2c=1 ** ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int sht20_checksum(uint8_t *data, int len, int8_t checksum); static inline void msleep(unsigned long ms); static inline void dump_buf(const char *prompt, uint8_t *buf, int size); int main(int argc, char **argv) { int fd, rv; float temp, rh; char *i2c_dev = NULL; uint8_t buf[4]; if( argc != 2) { printf("This program used to do I2C test by SHT20 sensor.\n"); printf("Usage: %s /dev/i2c-x\n", argv[0]); return 0; } i2c_dev = argv[1]; /*+--------------------------------+ *| open /dev/i2c-x device | *+--------------------------------+*/ if( (fd=open(i2c_dev, O_RDWR)) < 0) { printf("i2c device open failed: %s\n", strerror(errno)); return -1; } /*+--------------------------------+ *| set I2C mode and slave address | *+--------------------------------+*/ ioctl(fd, I2C_TENBIT, 0); /* Not 10-bit but 7-bit mode */ ioctl(fd, I2C_SLAVE, 0x40); /* set SHT2x slava address 0x40 */ /*+--------------------------------+ *| software reset SHT20 sensor | *+--------------------------------+*/ buf[0] = 0xFE; write(fd, buf, 1); msleep(50); /*+--------------------------------+ *| trigger temperature measure | *+--------------------------------+*/ buf[0] = 0xF3; write(fd, buf, 1); msleep(85); /* datasheet: typ=66, max=85 */ memset(buf, 0, sizeof(buf)); read(fd, buf, 3); dump_buf("Temperature sample data: ", buf, 3); if( !sht20_checksum(buf, 2, buf[2]) ) { printf("Temperature sample data CRC checksum failure.\n"); goto cleanup; } temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85; /*+--------------------------------+ *| trigger humidity measure | *+--------------------------------+*/ buf[0] = 0xF5; write(fd, buf, 1); msleep(29); /* datasheet: typ=22, max=29 */ memset(buf, 0, sizeof(buf)); read(fd, buf, 3); dump_buf("Relative humidity sample data: ", buf, 3); if( !sht20_checksum(buf, 2, buf[2]) ) { printf("Relative humidity sample data CRC checksum failure.\n"); goto cleanup; } rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6; /*+--------------------------------+ *| print the measure result | *+--------------------------------+*/ printf("Temperature=%lf 'C relative humidity=%lf%%\n", temp, rh); cleanup: close(fd); return 0; } int sht20_checksum(uint8_t *data, int len, int8_t checksum) { int8_t crc = 0; int8_t bit; int8_t byteCtr; //calculates 8-Bit checksum with given polynomial: x^8 + x^5 + x^4 + 1 for (byteCtr = 0; byteCtr < len; ++byteCtr) { crc ^= (data[byteCtr]); for ( bit = 8; bit > 0; --bit) { /* x^8 + x^5 + x^4 + 1 = 0001 0011 0001 = 0x131 */ if (crc & 0x80) crc = (crc << 1) ^ 0x131; else crc = (crc << 1); } } if (crc != checksum) return 0; else return 1; } static inline void msleep(unsigned long ms) { struct timespec cSleep; unsigned long ulTmp; cSleep.tv_sec = ms / 1000; if (cSleep.tv_sec == 0) { ulTmp = ms * 10000; cSleep.tv_nsec = ulTmp * 100; } else { cSleep.tv_nsec = 0; } nanosleep(&cSleep, 0); return ; } static inline void dump_buf(const char *prompt, uint8_t *buf, int size) { int i; if( !buf ) { return ; } if( prompt ) { printf("%-32s ", prompt); } for(i=0; i