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