From 53de825c4c4d8325c02341177f62ab84897eb5ee Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sat, 25 Jul 2026 22:09:43 +0800
Subject: [PATCH] update vscode task.json and add stm32flash tools

---
 ex2.i2c-bitbang/Board/sht20.c |  226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 226 insertions(+), 0 deletions(-)

diff --git a/ex2.i2c-bitbang/Board/sht20.c b/ex2.i2c-bitbang/Board/sht20.c
new file mode 100644
index 0000000..5352041
--- /dev/null
+++ b/ex2.i2c-bitbang/Board/sht20.c
@@ -0,0 +1,226 @@
+/**********************************************************************
+ *   Copyright: (C)2024 LingYun IoT System Studio
+ *      Author: GuoWenxue<guowenxue@gmail.com>
+ *
+ * Description: SHT20 Temperature & humidity sensor driver on ISKBoard
+ *
+ *   ChangeLog:
+ *        Version    Date       Author            Description
+ *        V1.0.0  2024.08.29    GuoWenxue      Release initial version
+ *
+ ***********************************************************************/
+
+#include <stdio.h>
+#include "sht20.h"
+#include "miscdev.h" /* udelay() / mdelay() */
+
+/* SHT20 7位标准 I2C 从机地址 */
+#define SHT20_I2C_ADDR          0x40
+
+/* SHT20 控制指令 (No Hold Master) */
+#define SHT20_CMD_TRIG_T        0xF3  /* 触发温度测量 (非阻塞) */
+#define SHT20_CMD_TRIG_RH       0xF5  /* 触发湿度测量 (非阻塞) */
+#define SHT20_CMD_SOFT_RESET    0xFE  /* 软件复位 */
+
+/* I2C 设备 SHT20 */
+static     i2c_dev_t sht20;
+
+/* 前置静态辅助函数声明 */
+static uint8_t sht20_check_crc(uint8_t *data, uint8_t nbytes, uint8_t checksum);
+i2c_status_t sht20_read_value(i2c_dev_t *sht20, uint8_t cmd, float *value);
+
+/**
+ * @brief  SHT20 初始化并软复位芯片
+ * @param  bus: 绑定的 I2C 物理总线指针
+ * @retval 0: 成功; -1: 失败
+ */
+int sht20_init(i2c_bus_t *bus)
+{
+    uint8_t cmd = SHT20_CMD_SOFT_RESET;
+    int rv = 0;
+
+    if (!bus)
+    {
+        return -1;
+    }
+
+    mdelay(20);
+
+    /* 绑定设备及其设备号到 I2C 总线上 */
+    i2c_bind_dev(&sht20, bus, SHT20_I2C_ADDR);
+
+    /* 将I2C总线加锁让设备独占总线 */
+    i2c_lock_dev(&sht20);
+
+    /* 向 SHT20 发送软件复位指令,并等待复位完成 */
+    i2c_write_no_reg(sht20.bus, sht20.dev_addr, &cmd, 1);
+    mdelay(20);
+
+    /* 释放设备的 I2C 总线锁 */
+    i2c_free_dev(&sht20);
+    return rv;
+}
+
+/**
+ * @brief  应用层温湿度采样接口函数 (带总线锁)
+ * @param  temperature: 存放输出温度结果的指针
+ * @param  humidity:    存放输出湿度结果的指针
+ * @retval 0: 采样成功且CRC通过; -1: 采样或校验失败
+ */
+int sht20_sample_TrH(float *temperature, float *humidity)
+{
+    int rv = -1;
+
+    if( !temperature || !humidity )
+    {
+        return -1;
+    }
+
+    /* 将I2C总线加锁让设备独占总线 */
+    i2c_lock_dev(&sht20);
+
+    /* 2. 采集温度 */
+    if (sht20_read_value(&sht20, SHT20_CMD_TRIG_T, temperature) != I2C_OK)
+    {
+        goto cleanup;
+    }
+
+    /* 3. 采集湿度 */
+    if (sht20_read_value(&sht20, SHT20_CMD_TRIG_RH, humidity) != I2C_OK)
+    {
+        goto cleanup;
+    }
+
+    rv = 0;
+
+cleanup:
+    /* 4. 释放总线并解锁 */
+    i2c_free_dev(&sht20);
+    return rv;
+}
+
+/**
+ * @brief  SHT20 硬件标准 CRC-8 校验
+ * @note   多项式 P(x) = x^8 + x^5 + x^4 + 1 = 1 0011 0001 = 0x31
+ * @param  data: 待校验的数据缓冲区指针 (含 High Byte 和 Low Byte)
+ * @param  nbytes: 校验的数据长度 (固定为 2 字节)
+ * @param  checksum: SHT20 芯片硬件返回的 CRC 结果字节
+ * @retval 0: 校验通过; 其余值: 校验失败
+ */
+static uint8_t sht20_check_crc(uint8_t *data, uint8_t nbytes, uint8_t checksum)
+{
+    uint8_t crc = 0x00; /* 初始值为 0 */
+    uint8_t byte_ctr;
+    uint8_t bit;
+
+    /* 逐个字节计算 */
+    for (byte_ctr = 0; byte_ctr < nbytes; ++byte_ctr)
+    {
+        crc ^= (data[byte_ctr]);
+
+        /* 按位进行模二除法 */
+        for (bit = 8; bit > 0; --bit)
+        {
+            if (crc & 0x80)
+            {
+                crc = (uint8_t)((crc << 1) ^ 0x31);
+            }
+            else
+            {
+                crc = (uint8_t)(crc << 1);
+            }
+        }
+    }
+
+    if (crc != checksum)
+    {
+        return 1; /* 校验不匹配 */
+    }
+
+    return 0; /* 成功 */
+}
+
+/**
+ * @brief  读取温湿度的底层通用核心函数 (加入完备的 CRC-8 硬件校验)
+ */
+i2c_status_t sht20_read_value(i2c_dev_t *dev, uint8_t cmd, float *value)
+{
+    uint8_t raw_data[2];
+    uint8_t crc_byte;
+    uint8_t rx_buf[3];
+    uint16_t raw_result;
+    uint32_t poll_timeout = 2000;
+    i2c_status_t status;
+
+    if ( !value )
+    {
+        return I2C_ERROR;
+    }
+
+    /* 1. 发送触发测量命令 (无寄存器写模式) */
+    status = i2c_write_no_reg(dev->bus, dev->dev_addr, &cmd, 1);
+    if (status != I2C_OK)
+    {
+        return I2C_ERROR;
+    }
+
+    /* 根据测量指令进行预留的 ADC 硬件转换安全延时 */
+    if (cmd == SHT20_CMD_TRIG_T)
+    {
+        mdelay(65);
+    }
+    else
+    {
+        mdelay(25);
+    }
+
+    /* 2. 利用高级读 API 的内部寻址应答机制等待芯片转换完成 */
+    while (poll_timeout--)
+    {
+        /* SHT20 在进行 ADC 转换时,它会对读模式寻址返回 NACK。
+         * i2c_read_no_reg() 发现地址无应答,会自动发 Stop 并返回错误。
+         * 我们直接利用这一机制作为非阻塞就绪判断!
+         */
+        status = i2c_read_no_reg(dev->bus, dev->dev_addr, rx_buf, 3);
+        if (status == I2C_OK)
+        {
+            /* 读取成功,3 字节(高、低、CRC)*/
+            break;
+        }
+
+        udelay(100);
+    }
+
+    if (poll_timeout == 0)
+    {
+        return I2C_ERROR;
+    }
+
+    /* 3. 分离出读回的 High Byte, Low Byte 以及 CRC 校验码 */
+    raw_data[0] = rx_buf[0];
+    raw_data[1] = rx_buf[1];
+    crc_byte    = rx_buf[2];
+
+    /* 4. 执行 CRC-8 校验 */
+    if (sht20_check_crc(raw_data, 2, crc_byte) != 0)
+    {
+        printf("SHT20 CRC Check Failed!\r\n");
+        return I2C_ERROR;
+    }
+
+    /* 5. 清除低 2 位状态位 */
+    raw_result = (uint16_t)((raw_data[0] << 8) | raw_data[1]);
+    raw_result &= ~0x0003;
+
+    /* 6. 代入物理公式转换 */
+    if (cmd == SHT20_CMD_TRIG_T)
+    {
+        *value = -46.85f + 175.72f * ((float)raw_result / 65536.0f);
+    }
+    else
+    {
+        *value = -6.0f + 125.0f * ((float)raw_result / 65536.0f);
+    }
+
+    return I2C_OK;
+}

--
Gitblit v1.10.0