开源STM32温湿度监测项目评测:代码、原理图与仿真全解析

发布时间:2026/9/26 1:54:01
开源STM32温湿度监测项目评测:代码、原理图与仿真全解析 拿到一个开源的STM32项目大多数人第一反应就是先把代码下下来、编译、烧录能跑起来就发一句“感谢大佬”。但作为常年扒开源项目的老油条我的习惯完全不同代码、原理图、仿真三件套必须挨个过一遍。代码决定你能不能跑起来原理图决定你的板子会不会冒烟仿真决定你遇到问题时是瞎猜还是有章法。最近正好翻到一个基于STM32F103C8T6的温湿度环境监测项目作者把源码、原理图、Proteus仿真工程全部开源了我花了两个晚上从头到尾拆了一遍今天就把这份评价完整写出来新手可以直接拿它当“如何评估开源嵌入式项目”的参考模板。1. 这个开源项目到底做了什么、值不值得看1.1 项目定位与芯片选型先说项目本身。这是一个典型的入门级环境监测系统主控是STM32F103C8T6板上接了一个DHT11温湿度传感器、一块0.96寸I2C接口OLED屏、两个按键、一个有源蜂鸣器另外把USART1引出来做串口打印。功能逻辑也很直白默认在OLED上显示温湿度按按键可以切换显示模式或者开启报警阈值设置温度超过设定值时蜂鸣器响同时串口把当前状态和实时数据发出来。选STM32F103C8T6这个芯片在开源项目里几乎可以用“标准答案”来形容核心几个原因Cortex-M3内核主频72MHz64KB Flash、20KB SRAM对付这种温湿度采集加显示的任务绰绰有余片上外设覆盖了USART、I2C、SPI、定时器、ADC这些常用功能无论往后做小车还是做简单物联网终端都能复用最关键的是这颗料价格便宜、采购容易盗版和正版都有一堆现成资料。对于开源项目来说选这种芯片意味着被复现的概率会成倍提升——因为大家手里都有这个料甚至很多人手头就是一块蓝板子。1.2 我为什么挑它作为评价样本我特意挑这个项目来拆不是因为它的功能有多惊艳而是因为它在开源资料完整性上提供了一个非常标准的样本工程是MDK下的HAL库工程原理图是Altium Designer格式仿真文件是Proteus 8的工程。这三样东西凑齐了基本就是教科书级别的“开源嵌入式项目交付清单”。更关键的是这个项目的复杂度处在最尴尬也最有价值的位置。太简单的点亮LED项目看不出代码风格差异太复杂的电机控制、FreeRTOS应用项目又会让大多数新手望而却步。而DHT11加OLED这个组合既涉及单总线时序这种对时间敏感的外设又涉及I2C总线的电气连接和地址配置还有按键消抖、报警逻辑这些状态机思想正好覆盖了嵌入式开发里最容易出问题的几个点。评价这样的项目能延伸到很多通用问题。2. 代码篇能不能直接抄、抄完会不会翻车2.1 工程结构与编程风格打开工程的第一眼我先看的是目录结构。这个项目用的是HAL库CubeMX生成过基础工程但同时作者自己做了不少二次整理。目录大致是Core里放的是系统初始化、中断和main.cDrivers下按外设拆成dht11.c、oled.c、key.c、buzzer.c、uart_debug.c这几个模块文件每个模块还配了对应的头文件。这种做法的好处非常明显main.c里不会塞几百行外设初始化代码主循环保持清爽你拿到代码后哪怕不做任何修改也能通过文件名快速定位到某个传感器或者某个外设的实现。不过打开具体文件后细节上的问题就出来了。作者可能是在工程建好之后又陆续改了功能有几个.c文件里出现了重复包含头文件的情况注释风格也是中文注释和英文注释混着来部分注释明显是后来追加上去的比如“这里等一下”这种口语化描述。这不算致命问题但如果你想把这个项目当模板去二次开发建议拿到代码后先自己重新整理一遍文件头把作者信息、修改日期、功能说明补充完整不然半年后再看代码你会很想穿越回去打自己。命名规范方面这个项目整体还行。变量名基本能做到“见名知意”比如temperature、humidity、key_state这种没有大量a、b、c无意义命名。但也有一些历史遗留问题某个全局变量flag_mode用的是int型实际上它只有0和1两个取值用uint8_t显然更合理还有一个延时函数的形参叫n50us看名字以为是以50微秒为单位结果函数内部实际是循环n次空指令循环体又没写注释这种“看似有注释、实则没说明白”的写法是嵌入式代码里比较典型的坑。2.2 最容易翻车的三个代码细节代码我能直接看出来的问题主要有三个分别对应不同层面的典型坑。第一个坑是DHT11的延时实现。DHT11是单总线器件对时序要求非常苛刻主机拉低总线至少18ms发起启动信号然后释放总线等待从机响应数据位“0”和“1”的区别取决于高电平的保持时间大约是26到28微秒和70微秒左右。这个项目里读取DHT11数据用的延时函数是自己写的——基于DWT数据观察点与跟踪单元实现的微秒级延时这是正确的选择。但问题是作者在第一次读初始化时用了HAL_Delay()这是一个毫秒级延时虽然DHT11的上电稳定时间确实是毫秒级刚好够用可是如果在一些时序要求更严格的场景下混用两种延时体系很容易出现读出来的数据偶尔是0或者跳变。如果你要复现这个项目DHT11读取函数前后千万别开中断尤其是串口中断或者定时器中断不然微秒级时序会被打断读数会间歇性抽风。第二个坑在OLED的I2C地址处理上。SSD1306这类OLED屏的I2C地址不同厂家模块默认值有0x78和0x7A两种而代码里如果按7位地址写就是0x3C按8位写地址就是0x78这两个数值本质上是一个东西。这个项目的oled.h里写的是0x78但我在仿真里跑的时候没什么问题换成实物屏幕却白屏了查了半天发现是卖家模块上地址电阻已经把默认地址改成了0x7A。所以拿到这类代码第一件事就是确认自己的屏幕地址这个锅真的不能让作者背。第三个坑是按键消抖。代码里用的是最常见的“延时10到20毫秒再确认电平”的方案逻辑本身没问题但它用的是阻塞式延时而且没有做松手检测。实操中的表现就是按键按得快一点功能会连续切换好几次或者长按和短按的区分度很差。如果只是做菜鸟练习无所谓但如果你要把它改成菜单系统建议换成状态机消抖配合定时器每5毫秒扫一次按键这样既省CPU又能支持长按短按组合。2.3 代码维度的具体评分按我自己的评价标准代码总分我给7分满分10分。可读性7.5分模块划分7分健壮性6分可移植性7分资源占用合理性8分。毫秒级和微秒级延时混用、按键没有松手检测、全局变量命名不够严谨这三个是主要的减分项。优点是思路清晰、外设驱动全部独立封装、没有搞一堆看不明白的寄存器魔法数字对想学HAL库开发的新手来说这个代码质量已经超过平均线不少了。3. 原理图篇硬件设计里的门道3.1 最小系统的电源与时钟设计代码能通过编译只代表逻辑自洽原理图才是决定实物能不能稳定工作的关键。我先把这份原理图的最小系统部分放大看了一遍。电源入口用的是USB的5V经过一颗AMS1117-3.3稳压成3.3V给全板供电这个思路很常见。AMS1117是低压差线性稳压器输入5V输出3.3V压差1.7V在100mA负载下基本没问题但要注意AMS1117的最大输出电流虽然有1A实际工作在小电流场景下散热还好如果后续要外接功耗较大的模块比如ESP8266直接从板载3.3V取电就会翻车轻则电压跌落重则稳压器过热。复现这个项目时外设供电尽量单独从5V取再自己加一路稳压。晶振部分用的是8MHz无源晶振两个引脚各接一个20pF负载电容到地。这里有个常见误区负载电容不是随便选的它是配合晶振的负载电容参数来计算的。以标称负载电容18pF的晶振为例实际计算公式是CL(C1*C2)/(C1C2)CstrayCstray是PCB走线和引脚寄生电容一般估算3到6pF。如果C1C220pF那么CL就是20/2515pF和18pF有偏差会导致实际振荡频率略微偏高。不过对于串口通信这种对时钟精度不敏感的场景这个偏差完全在可接受范围内。真正需要注意的相反是晶振下面尽量不要走其他信号线否则容易引入耦合噪声。复位电路用的是10kΩ上拉到3.3V、100nF电容到GND的经典组合这点值得表扬。很多新手画的复位电路要么只放一个电容要么干脆把NRST引脚悬空STM32内部其实有复位电路但这种外部RC组合对电源抖动和干扰的防护会好很多。BOOT0用了一个10kΩ下拉电阻BOOT1直接接到GND保证了默认从Flash启动这也是正确的做法。3.2 外设连接的几个关键细节看外设部分的电路最能体现一个开源项目的硬件水平。DHT11的数据引脚上接了一个4.7kΩ上拉电阻到3.3V这是对的。DHT11是单总线开漏输出结构如果没有外部上拉电阻数据引脚在释放总线时无法拉高读出来的数据必然全乱。实践中需要注意的是DHT11的数据线尽量短超过20cm就可能因为波形边沿变缓导致时序错乱如果实在要走长线可以把这个上拉电阻改成2.2kΩ试试。OLED这边作者用的是I2C接口SDA和SCL都接了4.7kΩ上拉电阻到3.3V。I2C总线的上拉电阻取值其实是有讲究的。标准模式100kHz下如果总线电容算100到200pF上拉电阻选2.2k到4.7k是正常的电阻太大信号上升沿变缓电阻太小则功耗增加、低电平可能拉不下来。这个项目里OLED屏和主控距离很近4.7kΩ没问题。但如果你的屏用了比较长的杜邦线建议换成2.2kΩ可以明显改善通信稳定性。蜂鸣器电路是另一个值得看的地方。作者没有直接把蜂鸣器接在GPIO和GND之间而是用了一颗S8050 NPN三极管做开关驱动GPIO通过一个1kΩ电阻接到三极管基极发射极接地集电极接蜂鸣器负极蜂鸣器正极接3.3V。这个设计是对的因为STM32 GPIO的灌电流和拉电流能力有限直接驱动蜂鸣器虽然看起来也能响但电流已经逼近GPIO的极限值时间长了容易把IO口烧坏。唯一不够讲究的是蜂鸣器两端没有反向并联续流二极管有源蜂鸣器内部自带了振荡电路没有续流二极管通常也能工作但如果换用无源蜂鸣器需要PWM驱动的那种关断瞬间的感性反电动势就很有可能击穿三极管。我的习惯是无论有源无源都在蜂鸣器两端反向并联一个1N4148开关二极管成本几分钱图个安心。3.3 原理图布局和暗坑整体看下来这份原理图的设计者是有一定功底的但也暴露了典型的“一个人画图”问题。首先是网络标号命名不统一同样是3.3V电源有的地方标VCC有的地方标3V3有的地方甚至直接标“3.3”虽然Altium Designer在做DRC检查时会自动匹配网络名但人眼审查的时候容易看错。其次是电源处理上有一个隐患VDDA引脚只接了一颗100nF去耦电容没有单独接小电感或者磁珠来隔离数字电源和模拟电源。对于这个项目用的12位ADC来说如果后续要采集电池电压或者做模拟量输入VDDA上的开关噪声会直接影响转换结果的跳动幅度建议复用这个项目的人把VDDA单独用磁珠从3.3V引过来再加一个1uF和一个100nF电容做滤波。去耦电容方面每个电源引脚旁边放了一颗100nF这个做法正确。我在评审开源原理图时判断设计者是否认真会先数一遍电源引脚的电容数量如果每个VDD都有对应位置的100nF说明作者至少知道去耦的作用如果整张图只有一两个那基本可以判定是照抄参考电路。这份图每个VDD都有主电源入口还多加了一颗10uF钽电容整体水平是合格的。还有一个不算问题但值得提醒的点原理图上没有预留SWD接口的丝印说明仅仅画了四个排针标注SWDIO、SWCLK、GND、3.3V。这个倒无伤大雅只是对新手不够友好如果不看原理图直接插线很容易把SWDIO和SWCLK接反。我自己复现的时候会在板上额外标一个丝印框毕竟ST-Link的接线错误是烧不坏板子的但排查起来真的很浪费时间。4. 仿真篇仿真跑通不等于实物能跑4.1 Proteus仿真模型和真机的差异打开这个项目的Proteus仿真工程能看到完整原理图主控是Proteus自带的STM32F103C8T6模型外接了DHT11模型、OLED模型、按键和蜂鸣器。仿真工程可以直接加载编译生成的hex文件运行这点很方便。但我必须反复强调一个观点Proteus仿真对STM32的支持仅限于逻辑层面的模拟很多外设的电气特性和时序细节是做不到和真机一致的。先说能正常仿真的部分。OLED模型在Proteus里跑I2C通信只要地址和时序代码正确点亮显示基本没问题因为Proteus对虚拟I2C设备的支持已经比较成熟。DHT11模型也是Proteus官方提供的它会按照单总线协议回传温湿度数据读取函数里的80微秒响应时间、50微秒左右的电平宽度虚拟模型不会像真实器件那样有温度漂移和个体差异所以仿真中很可能一次就读成功而真实器件偶尔会因为没有正确应答返回校验错误。换句话说这个项目在仿真里运行非常流畅恰恰掩盖了代码里缺少错误重试机制的问题。按键就更明显了。Proteus里的按键是一个理想数字模型按下就是低电平松开就是高电平根本没有机械触点抖动这回事。代码里虽然写了延时消抖但在仿真里你感觉不到它的作用因为仿真里压根没有抖动需要消除。等你把程序烧到实物板上按下按键发现偶尔一次触发两次才明白为什么我一直强调消抖不能只靠延时。4.2 仿真能验证什么、验证不了什么仿真不是没有价值它的价值主要体现在验证逻辑而不是验证硬件。对我来说仿真至少能承担三件事第一验证主循环里的状态机逻辑是不是按预期切换比如按某个键能不能进入阈值设置模式再按另一个键能不能增加阈值第二验证串口输出数据的格式虚拟串口终端里能看到打印内容和预期是否一致这在没有示波器和逻辑分析仪的情况下很有用第三演示效果做课程设计答辩或者给领导汇报时仿真跑起来比干讲PPT直观得多。但仿真绝对验证不了的事情同样列举出来给大家避雷一是真实的电气时序比如DHT11的实际响应时间、I2C总线上拉电阻大小对上升沿的影响这些在仿真里都不存在二是电源稳定性仿真里3.3V永远是完美的3.3V不会出现AMS1117压降、纹波、负载突变导致的电压跌落而这些往往是实物“偶尔死机”的元凶三是环境因素比如OLED屏幕在低温下刷新会变慢、蜂鸣器在低电压下音量变小、按键天长日久氧化后接触电阻变大仿真模型完全没有这些概念。4.3 仿真中实测踩过的两个坑在实际复现这个仿真工程时我踩了两个坑都是典型问题。第一个是Proteus的版本兼容性。作者用的是Proteus 8.9我用Proteus 8.7打开工程时部分器件模型报错尤其是STM32F103C8T6的模型库版本不匹配直接导致仿真无法运行。解决方法是升级Proteus版本或者新建工程重新放器件再把hex加载进去。第二个坑是仿真工程里的hex文件路径是绝对路径我换了一台电脑后找不到文件仿真一直停在启动界面。把hex文件复制到工程目录下并重新指定相对路径后就正常了。这提醒我仿真工程随代码一起开源时最好把hex文件也放进去或者说明清楚加载的是哪个目录下的hex。另外提一下如果觉得Proteus太重可以考虑Wokwi这个在线仿真平台它支持STM32F103的部分型号也集成了DHT11、OLED等常见模块浏览器里就能直接调试代码非常适合快速验证逻辑。不过Wokwi对HAL库的支持是半吊子很多依赖硬件外设初始化的操作会卡住试过几个项目后发现它更适合验证裸机寄存器的逻辑。5. 复现实录与问题排查速查5.1 我实际复现的完整流程记录为了验证这份开源项目的可复现性我不仅跑了仿真还真实搭了一套硬件。准备的物料包括一块STM32F103C8T6最小系统板、一个DHT11模块、一块0.96寸I2C OLED屏、两个轻触按键、一个有源蜂鸣器、一个ST-Link下载器外加一块面包板和若干杜邦线。第一步是编译代码。用Keil MDK打开工程需要先安装STM32F1系列的芯片支持包没有安装包的话工程会直接报“device not found”。装好包之后在工程选项里确认一下芯片型号是STM32F103C8然后选择ST-Link作为调试器连接到最小系统板的SWD接口。这里有个接入顺序的技巧ST-Link的四根线SWDIO接SWDIO、SWCLK接SWCLK、GND接GND、3.3V接板子上的3.3V很多人容易漏掉GND结果就是下载时提示“No target connected”因为调试器必须和目标板共地。第二步是硬件接线。DHT11的数据线接到某个GPIO比如PA6供电用3.3V数据线上用一个4.7kΩ电阻上拉到3.3VOLED的SDA接PB7、SCL接PB6同样加4.7kΩ上拉。我直接把模块和主控板用杜邦线连在一起用面包板飞线上拉电阻。如果不用上拉电阻DHT11会读不到数据OLED有时能显示有时白屏。第三步是烧录调试。编译通过之后点击下载按钮我这里一次成功然后打开串口助手波特率设成115200能看到串口每隔大概两秒打印一次当前温湿度。板载OLED上同时显示温度和湿度数值。按下按键1屏幕切换到报警阈值设置页面再按按键2调整阈值当温度超过阈值时蜂鸣器开始响串口也输出“Over Temperature”的提示。整体功能运行符合预期。5.2 复现中遇到的三个典型问题问题一DHT11读数一直是0或者显示“-1”。排查思路很简单先用万用表量DHT11的VCC引脚确认是否有3.3V然后量数据引脚在空闲状态下是不是高电平。实测下来是数据线上没有上拉电阻数据引脚悬空地乱跳导致读取失败。补上4.7kΩ上拉后问题解决。如果你用的是成品模块很多模块自带板上上拉电阻就不用额外加了但这个项目的原理图里DHT11用的是裸传感器所以必须在背面自己焊一个电阻。问题二OLED白屏。我先检查焊接和接线发现SDA和SCL两根线没接反那重点就放在I2C地址上。这个项目的代码默认地址是0x788位地址但我手上这块屏的实际地址是0x7A。把oled.c里的地址宏改掉后重新编译烧录屏幕就正常显示了。具体操作是用I2C扫描程序或者直接在while循环里循环尝试几个地址看到屏幕上出字就算找到。问题三仿真里一切正常实物上按键偶尔按一次触发两三次。这个就是我前面说的抖动问题。仿真模型没有抖动但真实的机械开关在按下瞬间会有几毫秒到几十毫秒的触点弹跳如果代码里只延时10ms就返回按键状态有可能刚好在弹跳的间隙采到一次高电平再采到一次低电平造成重复触发。我改成了20ms延时消抖同时加了松手等待现象明显改善。更稳妥的方案是每5ms进一次定时器中断扫描按键电平用相邻两次电平状态做判断这样CPU占用率低响应也更快。5.3 问题排查速查表现象可能原因排查步骤解决办法程序烧录时提示No target connectedSWD接线错误或没共地检查SWDIO/SWCLK/GND连接确认ST-Link和板子共地重新接线补上GNDDHT11读数为0或-1数据线上无上拉电阻供电不足用万用表量数据脚空闲电平是否为高量VCC电压增加4.7kΩ上拉电阻外接3.3V稳定电源OLED白屏或花屏I2C地址错误上拉电阻过大SDA/SCL接反用I2C扫描程序探测实际设备地址修改代码中地址宏或换成2.2kΩ上拉按键触发多次机械抖动示波器看按键波形或观察现象增加消抖延时增加松手检测或改用定时器状态机消抖串口打印乱码波特率不匹配时钟频率不对检查串口助手波特率检查晶振参数统一波特率为115200确认8MHz晶振配置正确仿真无法运行版本不兼容hex路径失效看Proteus错误提示查看hex文件是否存在于指定路径升级Proteus版本或重新指定hex相对路径6. 综合评分与改进建议6.1 三维度评分表按我常用来评估开源嵌入式项目的维度给这个项目打个综合分。代码维度7分具体拆解是可读性7.5、模块化7、健壮性6、可移植性7、资源占用合理性8。原理图维度7.5分拆解是最小系统设计8、外设连接合理性8、可制造性6.5、文档规范性6.5。仿真维度6分拆解是仿真完整性7、模型还原度5.5、可演示性8、跨平台兼容性4.5。综合加权下来大概是6.8分左右。这个分数属于什么水平在开源STM32项目里大量项目其实只有代码没有原理图或者有原理图却没有仿真。能做到三件套齐全的本身就已经超过六成以上的项目了。分数不高不低恰恰说明它适合学习而不完全适合直接拿去量产或者当产品原型。如果把它当成一个学习案例它提供了足够多的可挑毛病空间你能从中学到比一个“完美项目”更多的东西。6.2 给开源作者和复现者的几点建议对作者来说如果还想迭代这个项目我最想提的三个建议是第一把DHT11读取改成带错误重试和超时判断的版本连续读三次取多数值可以明显提高稳定性第二OLED的I2C地址做成可配置宏并且在代码注释里写清楚不同模块地址的差异减少新手踩坑率第三原理图里把电源树画清楚VDDA独立滤波加上防反接电路这样即使新手把电源接反也不会烧板子。对想要复现这个项目的人来说我的建议更直白一点别急着焊板子。先把仿真跑通用逻辑分析仪或者虚拟串口看看输出格式然后在面包板上搭实物用杜邦线一个个模块调通最后再画PCB打样。这样每个阶段的问题都是可追踪的不会出现“焊好板子一上电全乱”的绝望局面。另外复现开源项目的核心价值不是“抄”而是带着问题去改代码和电路改出你自己的改进版这才叫真正学会。我在实际复现过程中最有成就感的一刻不是屏幕亮起显示温度的那一刻而是把仿真里调不好的按键逻辑在实物上彻底修好的那一刻。因为那意味着我真的看懂了代码和电路之间的关系而不是简单地把别人的工程烧录进去就完事。开源项目的意义不就在这里嘛它给你一个不用从零开始的起点但往哪里走、怎么走还是得靠你自己。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询