From f7889e2ceddbc3e15ea4b5377d831f4432169f76 Mon Sep 17 00:00:00 2001
From: Guo Wenxue <guowenxue@gmail.com>
Date: Sat, 04 Jan 2025 16:26:42 +0800
Subject: [PATCH] Update iotd program configure file
---
modules/sht20.c | 406 ++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 295 insertions(+), 111 deletions(-)
diff --git a/modules/sht20.c b/modules/sht20.c
index d84877f..f549369 100644
--- a/modules/sht20.c
+++ b/modules/sht20.c
@@ -10,7 +10,7 @@
* ChangeLog: 1, Release initial version on "10/08/23 17:52:00"
*
* Pin connection:
- * STH20 Module Raspberry Pi Board
+ * SHT20 Raspberry Pi 40Pin
* VCC <-----> #Pin1(3.3V)
* SDA <-----> #Pin3(SDA, BCM GPIO2)
* SCL <-----> #Pin5(SCL, BCM GPIO3)
@@ -39,11 +39,41 @@
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
-int i2c_write(int fd, uint8_t slave_addr, uint8_t *data, int len);
-int i2c_read(int fd, uint8_t slave_addr, uint8_t *buf, int size);
-int sht20_checksum(uint8_t *data, int len, int8_t checksum);
+/* SHT2X 7-bit I2C slave address */
+#define SHT2X_CHIPADDR 0x40
+
+/* SHT2X trigger command */
+#define SOFTRESET 0xFE
+#define TRIGGER_TEMPERATURE_NO_HOLD 0xF3
+#define TRIGGER_HUMIDITY_NO_HOLD 0xF5
+
+/* Linux /dev/i2c-x device program API mode */
+enum
+{
+ MODE_IOCTL, /* I2C device API use ioctl() */
+ MODE_RDWR, /* I2C device API use read()/write() */
+};
+
+typedef struct i2c_s
+{
+ char *dev; /* I2C master device, /dev/i2c-N */
+ int addr; /* 7-bits slave address */
+ int fd; /* File description */
+ int mode; /* I2C device API use read/write or ioctl mode */
+} i2c_t;
+
+int sht2x_softreset(i2c_t *i2c);
+int sht2x_get_serialnumber(i2c_t *i2c, uint8_t *serialnumber, int size);
+int sht2x_get_temp_humidity(i2c_t *i2c, float *temp, float *rh);
+
+int i2c_init(i2c_t *i2c, int mode, char *i2cdev, int addr);
+int i2c_write(i2c_t *i2c, uint8_t *data, int len);
+int i2c_read(i2c_t *i2c, uint8_t *buf, int size);
+void i2c_term(i2c_t *i2c);
+
static inline void msleep(unsigned long ms);
-static inline void dump_buf(const char *prompt, uint8_t *buf, int size);
+void print_buf(const char *prompt, uint8_t *buf, int size);
+void dump_buf(const char *prompt, char *buffer, size_t length);
static inline void banner(const char *progname)
{
@@ -58,6 +88,7 @@
printf(" %s is SHT20 temperature and humidity sensor program. \n", progname);
printf(" -d[device ] Specify I2C device, such as /dev/i2c-1\n");
+ printf(" -m[mode ] Specify API mode, 0 for ioctl and 1 for read()/write()\n");
printf(" -h[help ] Display this help information\n");
printf(" -v[version ] Display the program version\n");
@@ -68,14 +99,17 @@
int main(int argc, char **argv)
{
- int fd, rv;
- float temp, rh;
- char *dev = "/dev/i2c-1";
+ char *dev="/dev/i2c-1";
char *progname=NULL;
- uint8_t buf[4];
+ int mode = MODE_IOCTL;
+ int rv;
+ float temp, rh;
+ uint8_t serialnumber[8];
+ i2c_t i2c;
struct option long_options[] = {
{"device", required_argument, NULL, 'd'},
+ {"mode", required_argument, NULL, 'm'},
{"version", no_argument, NULL, 'v'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
@@ -84,12 +118,16 @@
progname = basename(argv[0]);
/* Parser the command line parameters */
- while ((rv = getopt_long(argc, argv, "d:vh", long_options, NULL)) != -1)
+ while ((rv = getopt_long(argc, argv, "d:m:vh", long_options, NULL)) != -1)
{
switch (rv)
{
case 'd': /* Set I2C device path: /dev/i2c-1 */
dev = optarg;
+ break;
+
+ case 'm': /* Set I2C API mode: 0,1 */
+ mode = atoi(optarg) ? MODE_RDWR : MODE_IOCTL;
break;
case 'v': /* Get software version */
@@ -105,108 +143,190 @@
}
}
-
- /*+--------------------------------+
- *| open /dev/i2c-x device |
- *+--------------------------------+*/
- if( (fd=open(dev, O_RDWR)) < 0)
+ if( i2c_init(&i2c, mode, dev, SHT2X_CHIPADDR) < 0 )
{
- printf("i2c device '%s' open failed: %s\n", dev, strerror(errno));
+ printf("I2C master device initial failed.\n");
+ return 1;
+ }
+
+ if( sht2x_softreset(&i2c) < 0 )
+ {
+ printf("SHT2x initialize failure, maybe device not present!\n");
+ return 1;
+ }
+
+ if( sht2x_get_serialnumber(&i2c, serialnumber, 8) < 0)
+ {
+ printf("SHT2x get serial number failure\n");
+ return 3;
+ }
+
+ if( sht2x_get_temp_humidity(&i2c, &temp, &rh) < 0 )
+ {
+ printf("SHT2x get get temperature and relative humidity failure\n");
+ return 3;
+ }
+
+ printf("Temperature=%lf ℃ relative humidity=%lf.\n", temp, rh);
+
+ i2c_term(&i2c);
+
+ return 0;
+}
+
+int sht2x_softreset(i2c_t *i2c)
+{
+ uint8_t buf[1];
+
+ if( !i2c || i2c->fd<0 )
+ {
+ printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
return -1;
}
- /*+--------------------------------+
- *| software reset SHT20 sensor |
- *+--------------------------------+*/
-
- buf[0] = 0xFE;
- i2c_write(fd, 0x40, buf, 1);
+ /* software reset SHT2x */
+ buf[0] = SOFTRESET;
+ if( i2c_write(i2c, buf, 1) < 0 )
+ {
+ return -2;
+ }
msleep(50);
+ return 0;
+}
- /*+--------------------------------+
- *| trigger temperature measure |
- *+--------------------------------+*/
+int sht2x_get_temp_humidity(i2c_t *i2c, float *temp, float *rh)
+{
+ uint8_t buf[4];
- buf[0] = 0xF3;
- i2c_write(fd, 0x40, buf, 1);
+ if( !i2c || !temp || !rh || i2c->fd<0 )
+ {
+ printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+ return -1;
+ }
+
+ /* send trigger temperature measure command and read the data */
+ memset(buf, 0, sizeof(buf));
+ buf[0]=TRIGGER_TEMPERATURE_NO_HOLD;
+ i2c_write(i2c, buf, 1);
msleep(85); /* datasheet: typ=66, max=85 */
memset(buf, 0, sizeof(buf));
- i2c_read(fd, 0x40, buf, 3);
- dump_buf("Temperature sample data: ", buf, 3);
+ i2c_read(i2c, buf, 3);
+ print_buf("Temperature sample data: ", buf, 3);
+ *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
- 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;
- i2c_write(fd, 0x40, buf, 1);
+ /* send trigger humidity measure command and read the data */
+ memset(buf, 0, sizeof(buf));
+ buf[0] = TRIGGER_HUMIDITY_NO_HOLD;
+ i2c_write(i2c, buf, 1);
msleep(29); /* datasheet: typ=22, max=29 */
-
memset(buf, 0, sizeof(buf));
- i2c_read(fd, 0x40, 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;
- }
+ i2c_read(i2c, buf, 3);
+ print_buf("Relative humidity sample data: ", buf, 3);
+ *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
- 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)
+int sht2x_get_serialnumber(i2c_t *i2c, uint8_t *serialnumber, int size)
{
- int8_t crc = 0;
- int8_t bit;
- int8_t byteCtr;
+ uint8_t buf[4]={0x0};
- //calculates 8-Bit checksum with given polynomial: x^8 + x^5 + x^4 + 1
- for (byteCtr = 0; byteCtr < len; ++byteCtr)
+ if( !i2c || i2c->fd<0 || !serialnumber || size!=8 )
{
- 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);
- }
+ printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+ return -1;
}
- if (crc != checksum)
- return 0;
- else
- return 1;
+ /* Read SerialNumber from Location 1 */
+ memset(buf, 0, sizeof(buf));
+ buf[0] = 0xfa; /* command for readout on-chip memory */
+ buf[1] = 0x0f; /* on-chip memory address */
+ i2c_write(i2c, buf, 2);
+
+ memset(buf, 0, sizeof(buf));
+ i2c_read(i2c, buf, 4);
+
+ if( !buf[0] && !buf[1] && !buf[2] && !buf[3] )
+ {
+ printf("ERROR: SHT2X device not detected!\n");
+ return -2;
+ }
+
+ serialnumber[5]=buf[0]; /* Read SNB_3 */
+ serialnumber[4]=buf[1]; /* Read SNB_2 */
+ serialnumber[3]=buf[2]; /* Read SNB_1 */
+ serialnumber[2]=buf[3]; /* Read SNB_0 */
+
+ /* Read SerialNumber from Location 2 */
+ memset(buf, 0, sizeof(buf) );
+ buf[0]=0xfc; /* command for readout on-chip memory */
+ buf[1]=0xc9; /* on-chip memory address */
+ i2c_write(i2c, buf, 2);
+
+ memset(buf, 0, sizeof(buf) );
+ i2c_read(i2c, buf, 4);
+
+ serialnumber[1]=buf[0]; /* Read SNC_1 */
+ serialnumber[0]=buf[1]; /* Read SNC_0 */
+ serialnumber[7]=buf[2]; /* Read SNA_1 */
+ serialnumber[6]=buf[3]; /* Read SNA_0 */
+
+ print_buf("SHT2x Serial number: ", serialnumber, 8);
+
+ return 0;
}
-int i2c_write(int fd, uint8_t slave_addr, uint8_t *data, int len)
+/*+----------------------+
+ *| I2C API functions |
+ *+----------------------+*/
+
+int i2c_init(i2c_t *i2c, int mode, char *i2cdev, int addr)
{
- struct i2c_rdwr_ioctl_data i2cdata;
- int rv = 0;
+ if( !i2c || !i2cdev || !addr )
+ return -1;
+
+ memset(i2c, 0, sizeof(*i2c));
+ i2c->addr = addr;
+ i2c->dev = i2cdev;
+ i2c->mode = mode;
+
+ if( (i2c->fd=open(i2cdev, O_RDWR)) < 0)
+ {
+ printf("open i2c device %s failed: %s\n", i2cdev, strerror(errno));
+ return -1;
+ }
+
+ if( MODE_RDWR == i2c->mode )
+ {
+ /* set I2C mode and SHT2x slave address */
+ ioctl(i2c->fd, I2C_TENBIT, 0); /* Not 10-bit but 7-bit mode */
+ ioctl(i2c->fd, I2C_SLAVE, i2c->addr); /* set SHT2x slave address */
+ }
+
+ return 0;
+}
+
+void i2c_term(i2c_t *i2c)
+{
+ if( !i2c )
+ return;
+
+ if( i2c->fd > 0)
+ close(i2c->fd);
+
+ return ;
+}
+
+int i2c_write(i2c_t *i2c, uint8_t *data, int len)
+{
+ struct i2c_rdwr_ioctl_data tr;
+ int rv = 0;
if( !data || len<= 0)
{
@@ -214,28 +334,36 @@
return -1;
}
- i2cdata.nmsgs = 1;
- i2cdata.msgs = malloc( sizeof(struct i2c_msg)*i2cdata.nmsgs );
- if ( !i2cdata.msgs )
+ /* I2C device program API: read()/write() */
+ if( MODE_RDWR == i2c->mode )
+ {
+ write(i2c->fd, data, len);
+ return 0;
+ }
+
+ /* I2C device program API: ioctl() */
+ tr.nmsgs = 1;
+ tr.msgs = malloc( sizeof(struct i2c_msg)*tr.nmsgs );
+ if ( !tr.msgs )
{
printf("%s() msgs malloc failed!\n", __func__);
return -2;
}
- i2cdata.msgs[0].addr = slave_addr;
- i2cdata.msgs[0].flags = 0; //write
- i2cdata.msgs[0].len = len;
- i2cdata.msgs[0].buf = malloc(len);
- if( !i2cdata.msgs[0].buf )
+ tr.msgs[0].addr = i2c->addr;
+ tr.msgs[0].flags = 0; //write
+ tr.msgs[0].len = len;
+ tr.msgs[0].buf = malloc(len);
+ if( !tr.msgs[0].buf )
{
printf("%s() msgs malloc failed!\n", __func__);
rv = -3;
goto cleanup;
}
- memcpy(i2cdata.msgs[0].buf, data, len);
+ memcpy(tr.msgs[0].buf, data, len);
- if( ioctl(fd, I2C_RDWR, &i2cdata)<0 )
+ if( ioctl(i2c->fd, I2C_RDWR, &tr)<0 )
{
printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
rv = -4;
@@ -243,19 +371,19 @@
}
cleanup:
- if( i2cdata.msgs[0].buf )
- free(i2cdata.msgs[0].buf);
+ if( tr.msgs[0].buf )
+ free(tr.msgs[0].buf);
- if( i2cdata.msgs )
- free(i2cdata.msgs);
+ if( tr.msgs )
+ free(tr.msgs);
return rv;
}
-int i2c_read(int fd, uint8_t slave_addr, uint8_t *buf, int size)
+int i2c_read(i2c_t *i2c, uint8_t *buf, int size)
{
- struct i2c_rdwr_ioctl_data i2cdata;
- int rv = 0;
+ struct i2c_rdwr_ioctl_data tr;
+ int rv = 0;
if( !buf || size<= 0)
{
@@ -263,29 +391,41 @@
return -1;
}
- i2cdata.nmsgs = 1;
- i2cdata.msgs = malloc( sizeof(struct i2c_msg)*i2cdata.nmsgs );
- if ( !i2cdata.msgs )
+ /* I2C device program API: read()/write() */
+ if( MODE_RDWR == i2c->mode )
+ {
+ read(i2c->fd, buf, size);
+ return 0;
+ }
+
+ /* I2C device program API: ioctl() */
+ tr.nmsgs = 1;
+ tr.msgs = malloc( sizeof(struct i2c_msg)*tr.nmsgs );
+ if ( !tr.msgs )
{
printf("%s() msgs malloc failed!\n", __func__);
return -2;
}
- i2cdata.msgs[0].addr = slave_addr;
- i2cdata.msgs[0].flags = I2C_M_RD; //read
- i2cdata.msgs[0].len = size;
- i2cdata.msgs[0].buf = buf;
+ tr.msgs[0].addr = i2c->addr;
+ tr.msgs[0].flags = I2C_M_RD; //read
+ tr.msgs[0].len = size;
+ tr.msgs[0].buf = buf;
memset(buf, 0, size);
- if( ioctl(fd, I2C_RDWR, &i2cdata)<0 )
+ if( ioctl(i2c->fd, I2C_RDWR, &tr)<0 )
{
printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
rv = -4;
}
- free( i2cdata.msgs );
+ free( tr.msgs );
return rv;
}
+
+/*+----------------------+
+ *| Misc functions |
+ *+----------------------+*/
static inline void msleep(unsigned long ms)
{
@@ -304,10 +444,9 @@
}
nanosleep(&cSleep, 0);
- return ;
}
-static inline void dump_buf(const char *prompt, uint8_t *buf, int size)
+void print_buf(const char *prompt, uint8_t *buf, int size)
{
int i;
@@ -318,7 +457,7 @@
if( prompt )
{
- printf("%-32s ", prompt);
+ printf("%s ", prompt);
}
for(i=0; i<size; i++)
@@ -329,3 +468,48 @@
return ;
}
+
+void dump_buf(const char *prompt, char *buffer, size_t length)
+{
+ size_t i, j;
+
+ if (prompt)
+ {
+ printf("%s\n", prompt);
+ }
+
+ for (i = 0; i < length; i += 16)
+ {
+ printf("%08zx: ", i);
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i + j < length)
+ {
+ printf("%02x ", buffer[i + j]);
+ }
+ else
+ {
+ printf(" ");
+ }
+ }
+
+ printf(" ");
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i + j < length)
+ {
+ unsigned char c = buffer[i + j];
+ printf("%c", (c >= 32 && c <= 126) ? c : '.');
+ }
+ else
+ {
+ printf(" ");
+ }
+ }
+
+ printf("\n");
+ }
+}
+
--
Gitblit v1.9.1