尧图精选

SHT30温湿度传感器STM32F4驱动实战:I2C读写与CRC校验

🕒 发布时间:2026/9/3 19:54:47 📁 来源:尧图网络
简介面向STM32嵌入式开发者的SHT30温湿度传感器驱动资源演示如何通过模拟IIC在STM32F407上完成温湿度读取适合需要掌握IIC时序、传感器寄存器配置的初学者和项目开发者。压缩包共3个文件包含SHT30.c/H驱动源码与温湿度.pdf说明文档整体仅858KB其中C/H文件提供可直接移植的驱动接口覆盖GPIO模拟SDA/SCL、启动/停止信号、读写地址与数据校验等关键环节PDF则详细梳理SHT30的7位地址0x44/0x45、单次/周期测量模式配置及IIC完整通信步骤便于对照理解。目前已有1595人学习下载。借助该资源可快速跑通模拟IIC通信流程省去自行阅读数据手册和反复调试时序的精力也能为后续接入其他IIC传感器提供清晰的代码范式与排错思路尤其适合在环境监测、智能家居等场景中快速落地。 解压SHT30温湿度传感器stm32f4.zip这个压缩包时我心里大概有数这又是一套STM32环境采集的常规工程。但把代码完整过了一遍后发现这个工程包做得比想象中完整从STM32F407的I2C初始化、SHT30的寄存器读写、CRC校验到串口输出、Keil5烧录配置都有不是那种只丢一个main.c的碎片工程。这个项目能解决的问题很直接用一块Cortex-M4单片机稳定读取SHT30温湿度传感器数据通过I2C总线把原始数据变成真正的温度湿度数值。整个过程不依赖现成模块库代码逻辑完全可控特别适合两类人——一是刚把STM32跑起来、想快速上手一个真实传感器的初学者二是手里有项目需求、想把SHT30低成本集成进现有固件的老手。1. 这个工程包到底做了什么1.1 SHT30环境采集里非常能打的选手SHT30是瑞士Sensirion盛思锐出的数字温湿度传感器和传统湿敏电阻方案最大的区别在于它直接输出经过校准的数字信号温度和湿度都是16bit精度不需要自己做校准和多点标定。精度方面温度典型值±0.3°C湿度典型值±2%RH做环境监测、气象站、冷链运输记录、温室大棚控制都绰绰有余。同时它的接口是I2C最高支持1MHz快速模式单次测量命令一次读回6个字节温度高字节、低字节、温度CRC、湿度高字节、低字节、湿度CRC数据干净利落很省心。我在项目里横向对比过DHT11、AM2302和SHT30。DHT11胜在便宜、程序简单但精度和一致性只能说“凑合能用”AM2302某种程度上是DHT11的升级版测量范围大一些但时序敏感、每次读取必须严格按照起始信号来稍不注意就超时。SHT30贵一点但基本不用调上电就能拿到稳定数据长期漂移也小很多。如果是做量产产品SHT30的性价比其实更高省掉了大量后期标定和测试时间。1.2 为什么主控选STM32F4而不选其他这个工程包选择STM32F4核心原因不外乎三点性能充裕、外设丰富、生态成熟。STM32F407主频168MHz跑I2C这种低速总线完全是杀鸡用牛刀但正是这种性能冗余给后期扩展留了空间比如同时挂EMMC存数据、用SPI1接磁编码器MT6701、再接一块LCD屏CPU也不会卡顿。另外STM32F4的I2C、SPI、USART、SDIO接口齐全在一颗芯片上就能完成“传感器采集数据存储对外通信”的闭环。相比用51单片机或者F1系列F4有更大的Flash和RAM工程里即便加上FatFS文件系统、Modbus协议栈资源也不会捉襟见肘。对初学者来说STM32F4还有一层优势网上资料特别多。而且工程用Keil5开发图形化界面配好烧录器之后点一下Load就能下载程序调试门槛比Linux板卡低得多。这套方案放在2025年来看依然是最稳妥的入门路线不会被各种新架构带偏。1.3 工程包的代码结构长什么样解压之后里面的文件路径大概是这样的SHT30_STM32F4/ ├── Core/ │ ├── Inc/ │ │ ├── main.h │ │ └── sht30.h │ └── Src/ │ ├── main.c │ └── sht30.c ├── Drivers/ │ ├── CMSIS/ │ └── STM32F4xx_HAL_Driver/ ├── MDK-ARM/ │ ├── Project.uvprojx │ └── ... └── Readme.txt这个结构是从STM32CubeMX生成的工程模板改过来的把SHT30驱动单独拆成sht30.c和sht30.h和主业务逻辑解耦。好处很明显以后换传感器只要替换驱动文件不用动main.c里的业务代码代码给别人看也是先看接口再看实现理解成本低很多。2. 硬件连接和电路设计里容易忽略的细节2.1 引脚定义与I2C地址的坑SHT30的接口很简单常用引脚就5个VDD、GND、SCL、SDA、ADDR。默认情况下ADDR接地器件7位地址是0x44如果ADDR接VDD地址变成0x45。我第一次调这块芯片就栽在地址上——HAL库的I2C函数要求传的是8位地址也就是说要对左移一位写地址是0x88、读地址是0x89很多人直接填0x44结果总线一直NACK查了整整半天。STM32F4这边常用的I2C1引脚是PB6SCL和PB7SDAI2C2是PB10/PB11I2C3是PA8/PC9。选哪一路不影响驱动逻辑但要注意引脚是否和其他外设冲突。这个工程用的是I2C1接法如下表SHT30引脚STM32F4引脚说明VDD3.3V供电GNDGND地SCLPB6I2C1时钟线SDAPB7I2C1数据线ADDRGND默认地址0x442.2 上拉电阻和电源去耦I2C总线是开漏结构必须在SCL和SDA上接上拉电阻。很多人第一次画板子会漏掉这一步然后发现I2C通信时好时坏。上拉电阻阻值取4.7kΩ比较保守如果总线上设备多或者线比较长可以降到2.2kΩ反过来如果I2C速率高、走线短10kΩ也能工作。SHT30手册给出的范围是1kΩ到10kΩ推荐从4.7kΩ起步。还有一个容易被忽略的点传感器供电纹波。SHT30在3.3V下工作如果电源来自DC-DC模块且纹波偏大湿度数据会出现随机跳动。最好在VDD和GND之间放一个100nF陶瓷电容空间允许再加一个10μF钽电容效果会稳很多。此外SHT30这类传感器对VDD爬坡速度也有要求上电太慢可能导致初始化失败稳定供电是前提。2.3 一块板子上挂多个I2C设备的地址规划I2C总线天然支持多设备挂载但SHT30的地址选择只有0x44和0x45两档一个I2C总线上最多挂两颗。如果项目需要测多个点位的温湿度就得用TCA9548A这类I2C多路复用器把总线扩展成8路每路再挂SHT30。这个工程虽然只验证了一颗传感器但驱动代码里用了地址宏定义换成0x45或者动态传地址都很方便。规划阶段就把地址位分配好后面联调省太多事。3. 驱动代码拆解从I2C到温湿度数据3.1 I2C底层用硬件还是软件模拟SHT30本身只要求标准I2C时序STM32F4的硬件I2C完全够用。用HAL库的话几行代码就能完成一次读取我建议新手直接上硬件I2C省心且不占CPU。不过要提醒一句STM32F4的硬件I2C偶尔会出现BUSY标志卡死的情况这时候强制拉一下SCL或者在初始化里调用__HAL_I22C_CLEAR_FLAG(hi2c1, I2C_FLAG_BUSY)就能解掉。如果习惯把I2C引脚换成任意GPIO或者想彻底避开硬件I2C的时序问题也可以自己写软件I2C。方式就是用两个普通GPIO模拟开漏输出配合延时翻转电平。这种方案移植性最强换个单片机只要改引脚定义就能跑。缺点是CPU占用高、抗干扰依赖软件延时准确性所以量产代码我更推荐硬件I2C。3.2 SHT30核心命令与读取流程SHT30的命令分单次测量和周期测量两大类。单次测量适合“需要时才测一次”的场景周期测量适合持续监控。工程里用的是单次测量命令是0x2C 0x06含义是高重复性、时钟延展模式。读取流程四步走主机向0x88地址发送测量命令0x2C 0x06等待芯片完成测量高重复性模式下约15ms主机从0x89地址读取6个字节解析温度和湿度原始值并做CRC校验核心代码#define SHT30_ADDR_W 0x88 // I2C写地址 #define SHT30_ADDR_R 0x89 // I2C读地址 #define SHT30_CMD_MS_H 0x2C // 单次测量高重复性 #define SHT30_CMD_MS_L 0x06 uint8_t sht30_read_data(float *temp, float *hum) { uint8_t buf[6]; uint8_t cmd[2] {SHT30_CMD_MS_H, SHT30_CMD_MS_L}; // 发送测量命令 if (HAL_I2C_Master_Transmit(hi2c1, SHT30_ADDR_W, cmd, 2, 100) ! HAL_OK) return 1; HAL_Delay(20); // 等待测量完成留点余量 // 读取6字节数据 if (HAL_I2C_Master_Receive(hi2c1, SHT30_ADDR_R, buf, 6, 100) ! HAL_OK) return 2; // 校验CRC if (SHT30_CRC8(buf[0], 2) ! buf[2] || SHT30_CRC8(buf[3], 2) ! buf[5]) return 3; // 转换温度、湿度 uint16_t rawT (buf[0] 8) | buf[1]; uint16_t rawH (buf[3] 8) | buf[4]; *temp -45.0f 175.0f * rawT / 65535.0f; *hum 100.0f * rawH / 65535.0f; return 0; }一个细节测量完成前绝对不要发读命令否则读出来的是上上次的旧数据。工程里用HAL_Delay(20)是简单粗暴但有效的方式如果对时序有严格要求可以改成读取前的SCL电平轮询或者用SHT30的“测量后查询”模式那个不需要延时就知道了测量状态。3.3 CRC校验到底在防什么SHT30返回的6个字节里每个16bit数据后面都跟了1个8bit CRC由芯片内部CRC-8引擎生成多项式0x31初始值0xFF。这个设计专门用来检测通信链路是否受干扰。I2C走线如果比较长或者环境里有电机、开关电源之类的干扰源数据线上会出现毛刺收到的原始值可能发生位翻转。没有CRC校验时一个反了的bit可能让温度从25°C跳到-15°C后果很严重。所以驱动里的CRC校验不是可选项而是必选项。我见过很多工程把CRC验证注释掉靠平均值滤波来兜底这种方式在实验室里没问题放到工业现场迟早翻车。CRC代码也不复杂一个循环就写完uint8_t SHT30_CRC8(uint8_t *data, uint8_t len) { uint8_t crc 0xFF; for (uint8_t i 0; i len; i) { crc ^ data[i]; for (uint8_t bit 0; bit 8; bit) { if (crc 0x80) crc (crc 1) ^ 0x31; else crc 1; } } return crc; }3.4 温湿度计算公式与精度取舍SHT30的原始数据是16bit范围0~65535换算成物理量的公式非常固定温度T -45 175 * rawT / 65535湿度RH 100 * rawH / 65535这个公式直接来自芯片手册套用就好。有一点要注意湿度公式算出来是相对湿度RH和绝对湿度、露点温度不是一回事。如果要算露点需要用Magnus公式结合温度和相对湿度近似计算。工程里只输出了温湿度但代码里留了扩展位加一个露点计算函数也就十来行。在STM32F4上用浮点运算计算温湿度毫无压力因为F4带硬件单精度浮点单元FPU。如果换成Cortex-M0这类没有FPU的芯片就要考虑把浮点换成定点数比如温度用扩大100倍的整数表示输出时再除100能显著降低CPU开销。这种对精度的取舍做嵌入式要时刻记在心里。4. Keil5烧录STM32F4工程全流程4.1 工程模板与文件组织用Keil5打开工程后左侧Project栏会看到Target下的分组Application里是main.c和sht30.cDrivers里是HAL库源码和CMSIS启动文件。工程用的是STM32F407VET6启动文件startup_stm32f407xx.s不能选错选成F103的启动文件芯片直接跑不起来。系统时钟配置这里也要留意F407默认25MHz外部晶振如果用8MHz晶振必须改PLL配置否则串口波特率会偏差到没法用。4.2 烧录前必须检查的5个设置我把这个工程里烧录踩过的坑整理成5个检查点芯片型号Options for Target - Device选择STMicroelectronics - STM32F4 Series - 对应型号。型号不匹配时Flash烧录算法和内存地址映射都会出错。宏定义C/C - Define必须写USE_HAL_DRIVER,STM32F407xx。USE_HAL_DRIVER告诉HAL库启用STM32F407xx告诉库你的具体型号缺一个编译直接报一大堆未定义错误。调试器选择Debug - Use - ST-Link Debugger或J-LINKSettings里选择SWD模式不建议用JTAG。SWD只占两根线省出来的引脚能干别的。Flash烧录算法Debug - Settings - Flash Download确认Flash Size和实际芯片一致。报“No Algorithm”就是没选对Flash要把STM32F4xx Flash添加进来。Reset and RunFlash Download里务必勾选Reset and Run这样程序烧完自动复位执行。没勾也没关系手动按复位键就行但调试效率会低不少。配置完成后Rebuild编译再点Load下载。正常情况下Build Output窗口会显示“Application running”板上的LED开始闪烁。4.3 串口打印调试技巧这个工程把温湿度数据通过USART1打印波特率115200。用printf重定向时需要重写fputc函数int fputc(int ch, FILE *f) { while (!(USART1-SR USART_FLAG_TXE)); USART1-DR (uint8_t)ch; return ch; }打开串口助手后把显示格式设为字符串模式不然看到的全是乱码。输出数据尽量不要做太多格式化字符串越长MCU和串口助手两边的配合越容易出问题。我一般输出CSV格式方便直接记录到Excel里画温湿度曲线26.32,48.51 26.31,48.49 26.31,48.50这样用串口助手的“保存到文件”功能就能低成本攒下一整天的温湿度数据后续处理也方便。5. 实测中的典型问题与排查记录5.1 传感器无应答读回全是0xFF这是调试SHT30时最常遇到的问题。现象是HAL_I2C_Master_Transmit返回值错误或者读到的6个字节全是0xFF。排查顺序一般是这样的先用万用表测VDD和GND有没有电电压是不是3.3V。遇到过开发板USB口供电不足电压掉到2.8V传感器就是不回应。再查SCL、SDA有没有接反。SHT30封装比较小手工焊接时焊反很常见。确认上拉电阻存在。用示波器看SCL/SDA如果空闲电平不是高电平多半是上拉电阻没接或没焊好。最后查代码里的地址。前面强调过HAL库要用0x88/0x89而不是0x44/0x45。5.2 温湿度数值跳变、漂移如果CRC校验已经通过但数据还是会偶尔跳一下问题多半出在电源或布线上。经验是先给传感器单独加100nF去耦电容再把I2C导线从电机、继电器等干扰源旁挪开最后在上层加一个简单滑动平均滤波比如采5次取中间值。这些招数组合下来数据基本就稳了。另外传感器在通电初期湿度值会有一个“爬坡”过程这不是芯片坏了而是内部高分子感湿膜在重新平衡环境湿度。从上电到稳定一般需要几分钟尤其是刚从干燥仓储环境拿出来时不要一上电就急着拿数据去验收。5.3 Keil5下载时连接失败Keil5点击Load后提示“Cannot access target”我把它整理成一个速查表现象可能原因处理办法连接失败ST-Link驱动没装好重装STSW-LINK009驱动连接失败SWDIO/SWCLK接线松检查杜邦线或PCB焊盘连接失败芯片读保护被使能用STM32CubeProgrammer去除读保护连接失败板子没供电确认VDD检查调试器是否给板子供了电下载后不运行Flash Download没勾Reset and Run勾上或者手动复位有一个情况要特别提醒如果之前往芯片里烧过读保护代码芯片会锁定SWD口此时Keil完全连不上。解决方法是按住板子复位键点击Download在出现烧录进度前松开复位键通常能救回来救不回来就上STM32CubeProgrammer用整片擦除恢复。5.4 问题排查速查表症状大概率原因先查什么I2C读取返回HAL_ERROR地址错/上拉缺失/接线错地址、波形读回字节全为0xFFSDA线没上拉/接线断开上拉、连线数据偶尔跳变电源纹波/布线干扰去耦电容、走线温湿度值离谱公式用错/原始数据错位CRC、公式CRC校验一直失败I2C速率太快/软件I2C时序不对降速、延时长一点温度正常湿度偏高传感器受潮或靠近热源烘干、隔离6. 后续扩展SHT30和EMMC、SPI外设的联动6.1 用SDIO把温湿度存进EMMC工程基础功能跑通后一个很自然的扩展方向是把温湿度数据存进存储介质做一个独立的环境记录仪。STM32F407的SDIO接口可以直接驱动eMMC芯片因为eMMC的接口协议和MMC/SD是兼容的通过SDIO总线就能访问内部的控制逻辑和NAND Flash。不过用eMMC不能只接四根线就完事有几个点必须处理eMMC通常需要VCC和VCCQ两路电源VCCQ电平看芯片是1.8V还是3.3V板子上要保证完整的初始化时序包括CMD0、CMD1、CMD2这些命令软件层建议直接挂FatFS文件系统让数据以文件形式保存主机端读起来方便。如果不用文件系统就得自己实现坏块管理和均衡磨损工作量成倍增加。在工程里可以每完成一次SHT30读取就把温湿度记录追加到一个文本文件里再配上RTC时间戳一个冷链运输记录仪的原型就成了。6.2 SPI1驱动MT6701磁编码器另一个相关的热词是“stm32f4配置spi1驱动mt6701”。MT6701是一款磁编码器芯片输出绝对角度机器人关节和云台上经常用它做位置反馈。它支持SPI、ABZ、PWM多种接口如果走SPI挂到STM32F4的SPI1主机接口即可SCK、MOSI、MISO、CS四根线软件上按芯片手册配好时钟极性和相位读一次就能拿到14位角度数据0到16383对应360度。这样组合下来一个系统里既有SHT30做环境监测又有MT6701做运动位置反馈再加上EMMC做数据记录本质上就是“环境感知运动感知数据存储”的完整方案。在需要长期无人值守的设备上这种组合很常见。6.3 扩展时要注意的资源冲突扩展外设之前先翻芯片数据手册确认引脚有没有打架。比如SPI1如果用了PB3、PB4、PB5而I2C1用了PB6、PB7表面看不冲突但JTAG的默认引脚正好也是PB3、PB4要把调试本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →