简介:stm8+SHTC3.zip 是一份以 STM8 微控制器驱动 SHTC3 温湿度传感器的完整工程资源,演示了通过 I2C 接口读取温度与湿度、利用定时器触发每秒采样,并通过 UART 串口输出的实际项目流程,适合物联网、智能家居等低功耗场景的嵌入式开发者、学生以及希望入门 8 位单片机驱动的爱好者参考。压缩包共 156 个文件,以 36 个 .h 头文件、34 个 .c 源文件为核心,并附 .ewp 工程文件、.hex 烧录文件、.xcl 链接脚本及标准外设库代码;整体约 5.18MB,目录结构清晰,可直接导入 IAR 等开发环境编译运行。资源覆盖 STM8 外设初始化、SHTC3 命令读写、I2C 时序控制、定时器中断触发、串口波特率与数据帧参数配置等关键知识点,并基于 STM8L15x 标准外设库提供驱动源码,帮助读者从寄存器与库函数两个层面理解传感器采样的完整链路。已有 1709 人学习下载,对于需要快速搭建温湿度上报功能或研究 STM8 低功耗数据采集的开发者,这是一份既适合入门又便于扩展的实践参考资料。 我最近整理了一套基于 STM8 读取 SHTC3 温湿度传感器的工程,打包成了 stm8+SHTC3.zip 这种常见的项目压缩包。如果你正打算做低成本温湿度采集,这个组合是相当经典的方案:STM8 便宜、外设简单、上手快,SHTC3 是数字传感器,出厂校准、I2C 接口,温湿度精度都够用。zip 包本身不是什么复杂玩意儿,但里面藏着的工程结构、驱动代码、编译配置,才是真正的价值所在。这篇文章我就从“拿到 zip 包之后该怎么办”讲起,把环境搭建、驱动理解、代码移植到实测调试的完整链路捋一遍,给正在做嵌入式传感器项目的朋友一个能直接抄作业的参考。
很多刚入门的同学拿到 zip 后习惯双击打开,看看里面有什么文件,然后想直接改代码,结果发现工程文件打不开、路径引出一堆错误。这个坑我踩过,所以先提醒一句:任何从压缩包里来的工程,第一步永远是解压到本地,而不是在压缩包里操作。后面的所有步骤,都会基于你已经在本地建好了一个可读写的工程目录。
1. 项目概述与整体设计思路
1.1 STM8与SHTC3组合为什么值得做
先说硬件选型。STM8 是意法半导体推出的 8 位 MCU,主频最高做到 16MHz 或 24MHz,Flash 从 8KB 到 128KB 不等,价格却是 8 位机里最亲民的那一档。很多小家电、电动工具、传感器节点用的就是它。SHTC3 是 Sensirion 出的数字温湿度传感器,I2C 接口,温度精度典型 ±0.2°C,湿度精度典型 ±2%RH,功耗还特别低,测量模式下电流只有几百微安,待机更是微安级别。这两个东西放在一起,一套温湿度采集节点的物料成本可以压到十块以内,非常适合批量部署。
但价格低不代表容易做。SHTC3 虽然是数字接口,不用校准模拟电路,但它的 I2C 时序、测量命令、数据校验都有讲究。很多人在移植驱动时卡在“读出来的数据是 0”、“数据一直不变”、“温湿度乱跳”这些问题上,本质是没搞清楚传感器内部的寄存器机制和通信时序。用 STM8 做 I2C 主机时,有两种方式:硬件 I2C 外设和 GPIO 模拟 I2C。硬件 I2C 理论上快,但 STM8 的硬件 I2C 外设对时序要求严格,用不好反而容易死锁;GPIO 模拟 I2C 则更灵活,只要延时控制得当,稳定性和可移植性都很好。这个项目 zip 包里的驱动,我推荐用模拟 I2C。
1.2 ZIP包里的工程结构
打开 stm8+SHTC3.zip 后,你大概率看到的是一堆文件,我按实际工程经验给你梳理一个比较合理的目录:
stm8+SHTC3/ ├── drivers/ │ ├── shtc3.c │ ├── shtc3.h │ ├── soft_i2c.c │ └── soft_i2c.h ├── user/ │ ├── main.c │ ├── stm8s_it.c │ └── stm8s_conf.h ├── lib/ │ └── STM8S_StdPeriph_Driver/ ├── project/ │ ├── stm8_shtc3.eww │ ├── stm8_shtc3.ewp │ └── settings/ ├── docs/ │ └── SHTC3_Datasheet.pdf └── README.mddrivers 目录下是传感器驱动和模拟 I2C 代码,user 目录放主函数和中断文件,lib 是标准外设库,project 目录是 IDE 工程文件,docs 是数据手册。这个结构看起来清晰,但实际从网上下到的 zip 包往往没有这么规整,比如没有 README、缺少 lib 文件,甚至传感器驱动是 .c 和 .h 都混在一起。遇到这种情况,我的建议是先建一个干净的本地目录,再手动把源码、头文件、工程文件分门别类放好,避免后面编译时头文件找不到、源文件路径不对。
1.3 方案选型背后的考量
为什么推荐 STM8 而不直接用 STM32?因为你的项目如果只是读个温湿度、控制个继电器、上报个开关量,那 STM32 的性能根本用不满,价格和功耗反而上去了。STM8 的 8 位架构在这个场景下够用,而且开发工具成熟、资料多,社区老工程师积累了大量的代码可以直接参考。当初我为什么选 SHTC3 而不是 DHT11、SHT30?DHT11 是单总线协议,时序要求极严格,还要自己校准,精度也差;SHT30 精度更高,但价格也高。SHTC3 刚好卡在中间:数字 I2C 接口比 DHT11 省心,价格比 SHT30 便宜很多,精度能满足常规环境监测需求。这些选型思路,会直接体现在工程的驱动代码风格和注释里。
2. 开发环境搭建与工具链准备
2.1 选择合适的STM8开发环境
STM8 的开发环境选择,我试过 IAR for STM8、SDCC + VSCode、STVD 这几套工具链。如果你是从 zip 工程包入手,最稳妥的是 IAR for STM8,因为很多现成工程都是用它创建的,.ewp 工程文件双击就能打开。IAR 对 STM8 的支持做得比较完善,编译优化、调试器集成都不错,唯一的缺点是商用要授权,但评估版限制代码大小后用于学习也够。SDCC 则是完全免费的开源编译器,配合 VSCode 和 stm8flash,用命令行烧录,适合喜欢折腾的人。但 SDCC 和老工程之间的兼容性有时会出问题,比如头文件语法差异、位操作写法不同,从 zip 里拷来的代码可能需要小改才能编译通过。
我的建议是:别在环境选择上纠结太久。你手头这个 stm8+SHTC3.zip,如果里面是 IAR 工程,就装 IAR;如果没有工程文件,只有 .c 和 .h,那用 SDCC 或 IAR 新建空工程再添加文件也可以。环境本身不会限制你写出好的传感器驱动,反而是“不断试错”的环境切换会消耗大量时间。
2.2 烧录器与下载配置
STM8 的烧录方式主要有两种:ST-Link 和第三方编程器。ST-Link V2 是最常见的选择,便宜、稳定,IAR 和 STVD 都支持。第三方编程器比如网上卖的脱机烧录器,适合量产,但学习调试阶段没必要上手。配置下载器时有几个关键点:
- 在 IAR 工程里,Project -> Options -> Debugger 选择 ST-Link。
- Debugger -> ST-Link 界面里,Connection 选 SWIM,这是 STM8 专用的调试协议。
- 芯片型号必须选对,比如 STM8S003F3P6、STM8S103F3P6、STM8L051F3P6,选错会导致 Flash 大小和寄存器映射不匹配。
这类问题非常典型,很多人代码写完了,一烧录就报错“SWIM error”,十有八九是芯片型号选错或者连接线过长。SWIM 引脚对时序敏感,线长了干扰也大,我一般控制在 20 厘米以内。
2.3 解压和导入zip工程包的注意事项
解压路径是第一个大坑。不要解压到带中文、带空格的目录里,比如“桌面\新建文件夹(stm8)”这种,IAR 对路径中的中文支持不太好,编译时会报“cannot open source file”之类的错。我用 7-Zip 解压后,习惯把工程放在纯英文路径,比如D:\work\stm8_shtc3。
解压完成以后,先看一眼根目录有没有 .ewp 或 .eww 文件。如果有,直接双击 .eww 打开 workspace;如果没有,就用 IAR 新建一个项目,再把源码文件和头文件路径手动加进去。从 zip 里拷出来的文件,最好右键检查一下属性,Windows 偶尔会把这些文件标记为“从其他位置解压”而影响读写权限,如果出现“Access denied”,右键属性勾选解除锁定即可。这些操作听起来很简单,但确实是新手最容易卡住的地方。
3. SHTC3驱动原理与关键实现
3.1 SHTC3传感器工作机制
SHTC3 使用 I2C 接口,7 位设备地址是 0x70,8 位写地址是 0xE0,读地址是 0xE1。上电后传感器默认处于睡眠模式,必须先发送唤醒命令 0x3517,然后才能开始测量。这一点特别容易忽略,因为很多 SHT3x 系列的传感器上电就能测量,而 SHTC3 必须在命令序列里加唤醒。工程 zip 包里如果读不出来数据,第一反应先检查有没有发唤醒命令。
它支持两种测量模式:带时钟延展(Clock Stretching)和不带时钟延展。时钟延展的意思是:传感器在测量期间会拉低 SCL,告诉主机“我还没准备好,你先等着”。这种模式对主机程序的流程更简单,不用精确计算延时。命令 0x7CA2 就是温湿度都测、高精度、带时钟延展的典型命令。测量完成后,传感器一次性返回 6 个字节:温度高字节、温度低字节、温度 CRC8 校验、湿度高字节、湿度低字节、湿度 CRC8 校验。计算公式如下:
温度:T = -45 + 175 * (rawTemp / 65535) 相对湿度:RH = 100 * (rawHumidity / 65535)
这里的 rawTemp 是 16 位无符号整数,也就是把温度高字节左移 8 位再或上温度低字节。SHTC3 出厂前已经做过多点校准,所有校准系数都存在芯片内部,主机不需要额外查表。
3.2 I2C时序与模拟实现
I2C 协议本身不复杂,核心就是起始条件、停止条件、数据传输、应答/非应答。用 STM8 的 GPIO 模拟 I2C,比调用硬件 I2C 外设更直观。我写的软件 I2C 一般包含这几个函数:
- SoftI2C_Init:配置 GPIO 为开漏输出,拉高 SCL/SDA。
- SoftI2C_Start:SCL 高电平期间,SDA 拉低。
- SoftI2C_Stop:SCL 高电平期间,SDA 拉高。
- SoftI2C_WriteByte:依次发送 8 位数据,每发一位切换 SCL。
- SoftI2C_ReadByte:依次读取 8 位数据。
- SoftI2C_WaitAck / SoftI2C_Ack / SoftI2C_NAck:处理应答。
每个函数的延时都建议用软件延时函数,不要用没有延时的循环空转,因为不同编译器的优化级别会影响空循环的实际周期数。我最开始吃过的亏就是把for(i=0;i<100;i++);的延时当成准确的,结果换一个优化等级,I2C 时序就乱了。后来写了一个基于 NOP 指令的延时,并把优化级别固定下来,问题才算解决。
3.3 核心驱动代码思路
核心读取流程大概是这样的:
- 发送唤醒命令:Start -> 写 0xE0 -> 写 0x35 -> 写 0x17 -> Stop,等待 1ms。
- 发送测量命令:Start -> 写 0xE0 -> 写 0x7C -> 写 0xA2 -> Stop。
- 等待测量完成,这里可以用延时或等待传感器拉低 SCL。
- 重新发送起始条件,发送读地址 0xE1,依次读取 6 个字节。
- 发送 NACK 和 Stop。
- 将 6 字节拆成温度和湿度 raw 值,校验 CRC,最后换算成实际温湿度。
CRC8 校验是 SHTC3 很关键的一环。多项式是 0x31,初值是 0xFF。我之前偷懒跳过校验,结果在传感器老化或线路干扰时读回一些毛刺数据,温度跳了十几度。后来老老实实把 CRC8 加上,等于给数据加了一道安全锁。CRC 实现网上很多,核心是一个 8 位循环查表或逐位运算,代码量很小。
以下是简化版的读取流程伪代码,基于软件 I2C:
bool SHTC3_ReadTempHumidity(float *temp, float *hum) { uint8_t buf[6]; uint16_t rawT, rawH; SoftI2C_Start(); SoftI2C_WriteByte(0xE0); // 写地址 SoftI2C_WriteByte(0x7C); // 测量命令高字节 SoftI2C_WriteByte(0xA2); // 测量命令低字节 SoftI2C_Stop(); delay_ms(5); // 等待测量完成 SoftI2C_Start(); SoftI2C_WriteByte(0xE1); // 读地址 for (i = 0; i < 6; i++) { buf[i] = SoftI2C_ReadByte(); if (i < 5) SoftI2C_Ack(); else SoftI2C_NAck(); } SoftI2C_Stop(); if (CheckCRC8(buf[0], buf[1], buf[2]) == 0) return false; if (CheckCRC8(buf[3], buf[4], buf[5]) == 0) return false; rawT = (buf[0] << 8) | buf[1]; rawH = (buf[3] << 8) | buf[4]; *temp = -45.0f + 175.0f * (float)rawT / 65535.0f; *hum = 100.0f * (float)rawH / 65535.0f; return true; }要注意的是,读取时如果读地址后面没有正确回 ACK/NACK,传感器可能会卡在总线状态,导致后续通信失败。我一般在 Stop 之后还会加一个小延时,给总线释放留时间。
4. 工程移植与实测调试
4.1 硬件连接与上拉电阻
SHTC3 的供电范围是 1.62V 到 3.6V,一般直接接 3.3V。SCL 和 SDA 是开漏输出,必须接上拉电阻到 VDD,推荐 4.7kΩ。STM8 的 GPIO 如果内部有上拉,可以用内部上拉省两个电阻,但内部上拉的阻值通常在 30kΩ 到 50kΩ,I2C 速度一快就可能导致信号上升沿太缓。我做了个测试:1MHz I2C 时,用内部上拉通信不稳定;改 4.7kΩ 外部上拉后,波形干净很多。所以如果板子空间允许,还是老老实实焊两个电阻。
具体接法上,STM8S003 的 PB4/PB5、PD2/PD3 都可以复用为 I2C,但模拟 I2C 的话任意普通 GPIO 都能用。我习惯把 SCL 接到 PD2,SDA 接到 PD3,原因仅仅是引脚位置好布线。代码里初始化时把它俩都配置为开漏输出,初始输出高电平。
4.2 代码层级配置与编译
把 zip 里的源码加入工程之后,有三件事必须做:
- 在 IAR 的 Options -> C/C++ Compiler -> Preprocessor 里添加源文件目录为 include 路径。
- 在 Options -> General Options -> Target 里选择 MCU 型号。
- 检查 stm8s_conf.h 里的外设模块宏开关,确保没有把用不到的模块全部打开导致编译变慢。
有一次我从 zip 里导入工程,编译报了一堆错,仔细一看是 include 路径里有一个不存在的文件夹。这种问题特别隐蔽,因为报错的语句本身并没有错,纯粹是搜索不到头文件。解决办法很粗暴:把所有头文件集中放在工程根目录下的inc文件夹里,然后在 include 路径里加上这个inc,比让 IDE 自己去一堆目录里翻更省心。
编译通过后,用 ST-Link 下载,打开 IAR 的 Live Watch 窗口,添加temp和hum变量,单步跑一下就能看到实时数值变化。如果硬件连接正确、驱动没有 bug,一两秒内就能看到温度从 25 跳到 26 这种合理波动。
4.3 实测数据与波动处理
我拿手上的 STM8S003F3P6 + SHTC3 模块实测,放在室内稳定环境下,连续读取 100 次,温度读数大约在 25.1°C 到 25.4°C 之间波动,湿度在 46%RH 到 48%RH 之间波动。这个波动幅度对 SHTC3 来说是正常的,毕竟传感器本身有噪声,环境气流、板子发热也会影响读数。如果你的项目要求显示稳定值,可以在软件里做滑动平均,比如取最近 5 次采样值求平均值。但要注意,平均窗口别太大,否则响应速度就慢了,空气质量监测这种需要快速变化的场景就不合适。
我还试过在传感器旁边放一杯热水,湿度读数会在几秒内明显上升,温度也会跟着变。这说明驱动读取链路是通的。碰到读数纹丝不动的情况,优先怀疑传感器没唤醒,其次是 I2C 通信失败,最后才是数据换算错误。这三个问题按顺序排查,通常很快能解决。
5. 常见问题与排查技巧实录
5.1 I2C总线上拉没接,主机读不到数据
现象:读回来的数据一直是 0xFF 或者 0x00,I2C 通信像没反应一样。 原因:SCL/SDA 没有上拉,总线始终为低,主机没法启动通信。 排查:用示波器或逻辑分析仪看 SCL/SDA 波形,如果波形是一条平线,大概率没上拉。 解决:接 4.7kΩ 上拉电阻,或者启用 STM8 内部上拉。这里必须提醒一下,SHTC3 模块有些自带了上拉电阻,如果你再外接一个,就等于两个上拉并联,信号能工作但功耗稍增;模块没上拉的话,必须外部补上。
5.2 测量值一直为0或固定值
现象:温度湿度读出来始终是同一个值,比如 0.0 或 100.0。 原因:传感器没被唤醒,或者测量命令没有正确执行。 解决:在进入测量前先发送唤醒命令 0x3517,并延时 1ms。我发现不少 zip 工程注释里写了唤醒,但实际代码因为条件编译被屏蔽掉了,所以得手工检查一下驱动文件里到底有没有执行。
5.3 编译报错“cannot open source file”
现象:编译时报找不到某个头文件。 原因:include 路径没配好,或者源文件没加入工程。 解决:回到 Project -> Options -> C/C++ Compiler -> Preprocessor,把.h文件所在的目录全加进去;同时确认.c文件在 workspace 的文件树里。还有一种情况是路径里含有中文或空格,导致 IAR 解析失败,把工程挪到纯英文路径再试。
5.4 数据跳变特别严重
现象:读数一会儿 25°C 一会儿 35°C,湿度更夸张。 原因:电源纹波大、传感器附近有强干扰、测量间隔太短导致传感器还没稳定。 解决:
- 在传感器 VDD 和 GND 之间加 100nF 去耦电容。
- 把 I2C 线尽量短,远离继电器、电机等干扰源。
- 延长两次测量之间的间隔,SHTC3 测量本身只要几毫秒,但频繁读取会引入噪声,我一般间隔 500ms 以上。
这里放一个常见问题速查表,方便对照:
| 现象 | 直接原因 | 优先排查方向 |
|---|---|---|
| 读不到数据 | I2C 总线异常 | 上拉电阻、接线、地址 |
| 数据为 0 | 未唤醒传感器 | 唤醒命令、等待时间 |
| 温湿度完全不变 | 测量命令没生效 | 命令字节、条件编译 |
| 数据跳变巨大 | 电源、干扰、时序 | 去耦电容、走线、间隔 |
| 编译找不到头文件 | include 路径错误 | 工程选项、纯英文路径 |
5.5 一个容易忽略的小坑:读取之后的总线释放
我在调试时经常碰到的还有一个问题:读取完 6 个字节后,没有发 NACK 就发 Stop,结果下一次通信时传感器一直把 SDA 拉低,整个 I2C 总线卡死。解决办法是,在读取最后一个字节后,主机要发送 NACK 信号告知传感器“不要再发了”,然后立刻产生 Stop 条件。很多 zip 包里为了省事,读取时统一回 ACK,最后一字节也回 ACK,这个细节当时花了我整整一个下午才定位。所以读官方例程的时候,别只看代码能不能跑,要理解每一段时序背后的硬件逻辑。
6. 写在最后
从 stm8+SHTC3.zip 这个压缩包出发,我们其实走过了一条完整的嵌入式开发链路:解压工程、配环境、看原理、写驱动、调时序、排故障。这套流程不光是针对 SHTC3,换成其他 I2C 传感器,比如 SHT30、BMP280,套路几乎一模一样。只是在 SHTC3 上,唤醒命令、CRC8、ACK/NACK 这些细节更值得琢磨,踩过一次坑之后,你会对 I2C 通信有更深的体感。
我个人经验是,拿到任何 zip 工程包,别急着烧录,先把 README 和主函数从头到尾看一遍,搞清楚作者用的是硬件 I2C 还是软件 I2C、唤醒命令放在哪里、校验有没有开,再动手测试。这样至少能少走三个小时的弯路。希望这篇分享能让你手上的 STM8+SHTC3 工程一次跑通。
本文还有配套的精品资源,点击获取