From 80686e6bc4cb17e9d856647084725203fa63ebe6 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 19 Aug 2024 16:47:42 +0800
Subject: [PATCH] Add LCD API examples

---
 hal/modules/sht20.c |  516 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 516 insertions(+), 0 deletions(-)

diff --git a/hal/modules/sht20.c b/hal/modules/sht20.c
new file mode 100644
index 0000000..5aaa82d
--- /dev/null
+++ b/hal/modules/sht20.c
@@ -0,0 +1,516 @@
+/*********************************************************************************
+ *      Copyright:  (C) 2023 LingYun IoT System Studio
+ *                  All rights reserved.
+ *
+ *       Filename:  sht20.c
+ *    Description:  This file is temperature and relative humidity sensor SHT20 code
+ *
+ *        Version:  1.0.0(10/08/23)
+ *         Author:  Guo Wenxue <guowenxue@gmail.com>
+ *      ChangeLog:  1, Release initial version on "10/08/23 17:52:00"
+ *
+ * Pin connection:
+ *                  SHT20                 Raspberry Pi 40Pin
+ *                   VCC      <----->      #Pin1(3.3V)
+ *                   SDA      <----->      #Pin3(SDA, BCM GPIO2)
+ *                   SCL      <----->      #Pin5(SCL, BCM GPIO3)
+ *                   GND      <----->      GND
+ *
+ * /boot/config.txt:
+ *                  dtoverlay=i2c1,pins_2_3
+ *
+ ********************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <getopt.h>
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+/* 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);
+void print_buf(const char *prompt, uint8_t *buf, int size);
+void dump_buf(const char *prompt, char *buf, size_t len);
+
+static inline void banner(const char *progname)
+{
+    printf("%s program Version v1.0.0\n", progname);
+    printf("Copyright (C) 2023 Avnet.\n");
+}
+
+static void program_usage(const char *progname)
+{
+
+    printf("Usage: %s [OPTION]...\n", progname);
+    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");
+
+    printf("\n");
+    banner(progname);
+    return;
+}
+
+int main(int argc, char **argv)
+{
+    char           *dev="/dev/i2c-1";
+    char           *progname=NULL;
+    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}
+    };
+
+    progname = basename(argv[0]);
+
+    /* Parser the command line parameters */
+    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 */
+                banner(progname);
+                return EXIT_SUCCESS;
+
+            case 'h':  /*  Get help information */
+                program_usage(progname);
+                return 0;
+
+            default:
+                break;
+        }
+    }
+
+    if( i2c_init(&i2c, mode, dev, SHT2X_CHIPADDR) < 0 )
+    {
+        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 SHT2x */
+    buf[0] = SOFTRESET;
+    if( i2c_write(i2c, buf, 1) < 0 )
+    {
+        return -2;
+    }
+
+    msleep(50);
+
+    return 0;
+}
+
+int sht2x_get_temp_humidity(i2c_t *i2c, float *temp, float *rh)
+{
+    uint8_t           buf[4];
+
+    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(i2c, buf, 3);
+    print_buf("Temperature sample data: ", buf, 3);
+    *temp = 175.72 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 46.85;
+
+    /* 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(i2c, buf, 3);
+    print_buf("Relative humidity sample data: ", buf, 3);
+    *rh = 125 * (((((int) buf[0]) << 8) + buf[1]) / 65536.0) - 6;
+
+    return 0;
+}
+
+int sht2x_get_serialnumber(i2c_t *i2c, uint8_t *serialnumber, int size)
+{
+    uint8_t           buf[4]={0x0};
+
+    if( !i2c || i2c->fd<0 || !serialnumber || size!=8 )
+    {
+        printf("%s line [%d] %s() get invalid input arguments\n", __FILE__, __LINE__, __func__ );
+        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;
+}
+
+/*+----------------------+
+ *|   I2C API functions  |
+ *+----------------------+*/
+
+int i2c_init(i2c_t *i2c, int mode, char *i2cdev, int addr)
+{
+    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)
+    {
+        printf("%s() invalid input arguments!\n", __func__);
+        return -1;
+    }
+
+    /* 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;
+    }
+
+    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(tr.msgs[0].buf, data, len);
+
+
+    if( ioctl(i2c->fd, I2C_RDWR, &tr)<0 )
+    {
+        printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        rv = -4;
+        goto cleanup;
+    }
+
+cleanup:
+    if( tr.msgs[0].buf )
+        free(tr.msgs[0].buf);
+
+    if( tr.msgs )
+        free(tr.msgs);
+
+    return rv;
+}
+
+int i2c_read(i2c_t *i2c, uint8_t *buf, int size)
+{
+    struct i2c_rdwr_ioctl_data      tr;
+    int                             rv = 0;
+
+    if( !buf || size<= 0)
+    {
+        printf("%s() invalid input arguments!\n", __func__);
+        return -1;
+    }
+
+    /* 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;
+    }
+
+    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(i2c->fd, I2C_RDWR, &tr)<0 )
+    {
+        printf("%s() ioctl failure: %s\n", __func__, strerror(errno));
+        rv = -4;
+    }
+
+    free( tr.msgs );
+    return rv;
+}
+
+/*+----------------------+
+ *|    Misc functions    |
+ *+----------------------+*/
+
+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);
+}
+
+void print_buf(const char *prompt, uint8_t *buf, int size)
+{
+    int          i;
+
+    if( !buf )
+    {
+        return ;
+    }
+
+    if( prompt )
+    {
+        printf("%s ", prompt);
+    }
+
+    for(i=0; i<size; i++)
+    {
+        printf("%02x ", buf[i]);
+    }
+    printf("\n");
+
+    return ;
+}
+
+void dump_buf(const char *prompt, char *buf, size_t len)
+{
+    char        line[256];
+    size_t      i, j;
+    int         offset;
+
+    if( prompt )
+    {
+        printf("%s\n", prompt);
+    }
+
+    for(i = 0; i < len; i += 16)
+    {
+        offset = snprintf(line, sizeof(line), "%08zx: ", i);
+
+        /* Print hex representation */
+        for (j = 0; j < 16; j++)
+        {
+            if (i + j < len)
+                offset += snprintf(line + offset, sizeof(line) - offset, "%02x ", buf[i + j]);
+            else
+                offset += snprintf(line + offset, sizeof(line) - offset, "   ");
+        }
+
+        offset += snprintf(line + offset, sizeof(line) - offset, " ");
+
+        /* Print ASCII representation */
+        for (j = 0; j < 16; j++)
+        {
+            if (i + j < len)
+            {
+                unsigned char c = buf[i + j];
+                offset += snprintf(line + offset, sizeof(line) - offset, "%c", (c >= 32 && c <= 126) ? c : '.');
+            }
+            else
+            {
+                offset += snprintf(line + offset, sizeof(line) - offset, " ");
+            }
+        }
+
+        /* Print the line */
+        printf("%s\n", line);
+    }
+}
+

--
Gitblit v1.9.1