1. 先看全貌:这个开源项目到底在解决什么问题
做嵌入式这几年,我在开源社区翻过不少STM32项目,大部分情况是:代码能跑,但原理图只有个截图,仿真根本没给。所以这次看到这个项目的时候,我反而多留了个心眼——它把代码、原理图、仿真三件套配齐了,这种项目在STM32方向里不算多,但恰恰是最适合拿来系统的学一遍的。
先说清楚这个项目是干什么的。它本质上是一个基于STM32F103C8T6的小型环境监测与开关控制系统:通过DHT11采集温湿度,在OLED屏幕上显示实时数据,支持按键设置上下限阈值,当温度或湿度越限时,自动控制继电器通断来带动风扇、加热器这类负载,同时把状态通过串口打印到上位机。
功能链路是完整的:采集 → 显示 → 判断 → 执行 → 上报。硬件成本很低,一块核心板加几个外围器件就能搭起来,很多课设和毕设题目也都长这样。但"题目常见"不等于"实现合格",它的价值主要体现在三件套的配合度上:有代码可以改逻辑,有原理图可以改硬件,有仿真可以先把想法验证一遍再动手买元器件焊接。
我在评价这类开源项目的时候,通常会按三个维度来打分:代码可维护性、原理图规范性、仿真可复现性。代码决定你改它的成本,原理图决定你抄板的安全感,仿真决定你调试的效率。这篇文章就是把这三个维度挨个拆开说清楚,最后再补一组我复现时踩过的坑。
1.1 硬件资源与引脚分配逻辑
先看硬件分配。STM32F103C8T6这颗芯片大家应该很熟了,Cortex-M3内核,主频72MHz,64KB Flash,20KB RAM,48个引脚。在这个项目里,引脚划分得很典型:
| 功能模块 | 引脚 | 接口类型 | 关键器件 |
|---|---|---|---|
| DHT11温湿度 | PA0 | 单总线 | 4.7k上拉电阻 |
| OLED显示屏 | PB6/PB7 | I2C | 0.96寸SSD1306 |
| 继电器控制 | PB0 | GPIO输出 | 三极管驱动+续流二极管 |
| 板载LED指示 | PB1 | GPIO输出 | 330欧限流电阻 |
| 阈值设置按键 | PA1/PA2 | GPIO输入 | 10k上拉+RC滤波 |
| 串口日志 | PA9/PA10 | USART1 | CH340或直接USB转TTL |
| 调试下载 | PA13/PA14 | SWD | ST-Link |
引脚的分配思路其实有个隐性规律:I2C和USART这类复用功能尽量放在默认映射位置,这样初始化代码不用重映射,省掉一堆麻烦;按键和LED这类普通IO放在一起,方便布线;继电器这种可能会产生电磁干扰的执行器件,跟传感器引脚保持一定距离。
这种分配方式对于新手来说非常友好,因为它能最大程度降低"代码和原理图对不上"的概率。我见过不少开源项目,原理图里引脚乱飞,代码里还得加AFIO重映射配置,一不留神就把自己绕晕了。
1.2 为什么"代码+原理图+仿真"三件套值得学
其实很多人的学习路径是反的:拿到代码直接烧,烧进去发现灯不亮,然后就开始瞎猜。这个项目给了三条路平行推进的可能性。
仿真先行是最推荐的方式。在没打板之前,用Proteus或者在线仿真平台把逻辑跑通,确认传感器的数据读取时序、继电器翻转逻辑、串口报文格式都没有问题,再回来看原理图去理解硬件为什么这么接,最后才是买元器件动手。
原理图是中间的"翻译层"。它把芯片引脚的电气行为翻译成实际的电路连接。很多人代码写得溜,但一看原理图就懵,其实是因为缺少"引脚 ↔ 信号 ↔ 器件"三者之间的对应训练。这个项目把三者绑在一起,正好逼着你建立这种对应关系。
代码则是最上层的表达。底层硬件怎么动作,最终都要落在寄存器和GPIO电平上。有了仿真验证逻辑、原理图对照硬件,再回头读代码,你会发现很多东西是"原来如此"——比如为什么DHT11的时序要求那么严格,为什么继电器控制要加一级三极管驱动,这些都能在原理图和代码的相互印证中理解通透。
2. 代码质量评价:一份值得借鉴的STM32工程应该长什么样
代码是这个项目里我最先看的部分。评价标准只有一条:如果我想把这个项目移植到另一颗芯片上,或者改造成别的功能,我要不要重写?
2.1 工程结构与模块划分
项目的代码基于标准外设库(SPL)开发,工程目录分了几个层次,典型结构大概是这样:
├── USER // main.c, stm32f10x_it.c, 系统配置 ├── HARDWARE // 外设驱动层:dht11.c, oled.c, relay.c, key.c ├── APP // 应用逻辑层:menu.c, control.c, protocol.c ├── SYSTEM // 延时、串口、中断优先级等基础支持 └── CORE // 内核相关文件,启动文件、系统时钟这套划分方式很传统,但确实好用。外设驱动层只干一件事:把某个外设的操作封装成函数,不掺杂业务逻辑。比如DHT11_Read_Temperature()就只负责读取和返回温度值,至于是不是越限、要不要开继电器,那是应用层control.c的事。
应用逻辑层里有个典型的控制循环,主函数大概长这样:
int main(void) { SystemInit(); Delay_Init(); USART1_Init(115200); OLED_Init(); DHT11_Init(); Relay_Init(); Key_Init(); while (1) { DHT11_Read_Data(); // 采集温湿度 Control_Threshold_Check(); // 阈值判断 OLED_Display_Update(); // 刷新显示 Protocol_Send_Report(); // 串口上报 Delay_Ms(500); // 主循环周期控制 } }主循环干净利落,业务逻辑一眼就能看明白。这也是我评价一个STM32项目代码的第一个加分项:主循环是不是能看懂。如果拿到一个项目,main函数里一坨一坨的嵌套逻辑,连初始化都要翻好几层才能找到,那后续改代码的维护成本会成倍上涨。
2.2 核心逻辑与关键时序实现
DHT11是目前入门项目里出现频率最高的传感器之一,它对时序的要求比较严格:主机发出起始信号后,DHT11会拉低80us再拉高80us表示响应,然后每一位数据以50us低电平起始,26-28us的高电平表示"0",70us的高电平表示"1"。
所以代码里读取数据时用的是阻塞延时配合GPIO电平读取,注册了一个DHT11_Read_Bit()这样的函数,通过延时判断高电平持续的时间来区分0和1。这段代码的写法通常很直接:
uint8_t DHT11_Read_Bit(void) { uint8_t i; while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == RESET); // 等待低电平结束 Delay_Us(40); // 延时40us if (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET) // 高电平持续40us以上 { i = 1; while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN) == SET); // 等待高电平结束 } else { i = 0; } return i; }这里有个新手容易踩的坑:Delay_Us()必须是精确的微秒级延时。如果项目里用的是SysTick做系统时钟,那就需要用汇编或者DWT(Data Watchpoint and Trace)来做微秒延时,单纯靠循环减法的延时在不同优化等级下误差会很大。这个项目采用的是基于SysTick的简洁延时实现,实测下来在8MHz外部晶振、72MHz主频下还是比较稳的。
2.3 按键消抖与状态机的设计思路
按键处理这部分,项目没有用简单的延时消抖,而是做了一个小状态机,我觉得这点很值得拿出来说一下。机械按键按下和松开的瞬间都会有抖动,大概持续5到10ms,如果不处理,一次按下会被识别成多次触发。
常见的消抖方式有两种:一是检测到电平变化后延时10到20ms再次确认;二是用定时器做扫描,每隔5ms采样一次,连续多次采样都稳定才判定为有效。这个项目用的是扫描式消抖,并且把按键动作分成了"按下、确认按下、释放、确认释放"几个状态。
这种思路的好处是实时性更好。比如用户连续按三下按键,如果每次都用20ms阻塞延时消抖,那整个流程会变得很迟钝;而状态机方式下,主循环照常跑,定时器中断每5ms扫描一次按键,既不会阻塞其他任务,又能准确识别连续操作。
对于同时要处理传感器读取、OLED刷新、串口上报的项目来说,这种"主循环+定时器时间片"的架构比裸奔阻塞延时靠谱得多。这也是我从这个项目里学到的比较核心的一个编程思路。
2.4 评价代码时我最看重的三个细节
第一是命名规范。这个项目里所有函数都带模块前缀,DHT11_、OLED_、Relay_、KEY_,变量命名也基本是语义化的,比如temperature_val、humidity_val、threshold_temp_high。嵌入式项目最怕的就是a、b、c这种变量满天飞,过两周自己都不知道写的什么。
第二是注释的"度"。这个项目的注释不多,但都写在关键节点上,比如DHT11时序里的延时说明、继电器控制逻辑的触发条件。它没有每一行都注释,因为那是废话;它注释的是"为什么这么写"。这两者的区别很关键。
第三是可移植性。外设驱动的头文件里把引脚、端口、时钟都用宏定义做了封装,换芯片或者换板子的时候只需要改宏定义,不需要动函数内部的逻辑。这一点在项目改造时能省下大量时间。比如把DHT11从PA0换到PB3,只需要改#define DHT11_PORT GPIOB和#define DHT11_PIN GPIO_Pin_3,然后记得在初始化函数里打开GPIOB的时钟就行。
整体评价:这份代码的工程质量在开源项目里属于中上水平,虽然不算多惊艳,但作为学习和改造的底子,已经非常合格了。
3. 原理图设计评价:从最小系统到外设电路的规范性
代码看完了,接下来对照原理图。原理图评价的核心是安全性:电源能不能稳住、信号会不会串扰、有没有为了省钱省掉必要的保护电路。
3.1 最小系统设计的合理性
先看电源部分。板子用USB的5V输入,经过一颗AMS1117-3.3稳压芯片降到3.3V给MCU和其他外设供电。AMS1117是LDO线性稳压芯片,输入输出压差小,适合这种电流需求不大的场景。
电源设计里有个细节我比较在意:AMS1117的输入输出端都加了10uF和0.1uF的电容组合。10uF的钽电容或电解电容负责储能,应对瞬态电流波动;0.1uF的陶瓷电容负责滤除高频噪声。两者配合,电源纹波才能控制在合理范围内。这个项目在这点上没省料,值得表扬。
然后看时钟电路。STM32F103C8T6支持外部8MHz晶振,两个负载电容用的是20pF。这个取值是常见做法,但如果你用的晶振负载电容是12pF或者18pF,需要对应调整。我一般会根据晶振手册来配,如果实在查不到,用20pF也能正常工作,只是频率精度可能略受影响。
复位电路就是经典的10k上拉电阻加100nF电容到地,按键一端接地,按下时拉低复位引脚。SWD调试接口引出了SWDIO、SWCLK、GND三根线,外加一个可选的复位脚。对于F103来说,三线SWD已经足够下载和调试了。
BOOT0的处理也值得说。这个项目把BOOT0通过10k电阻下拉到地,保证从Flash启动。这里有个细节:有些板子为了省事直接把BOOT0接地,但接一个下拉电阻可以避免在下载或特殊操作时因为外部干扰导致意外进入Bootloader模式,这种细节是原理图规范性的体现。
3.2 外设电路的关键计算
外设电路部分我重点说两个:LED限流电阻和继电器驱动电路。
LED限流电阻的计算是入门必会。LED正常工作电流取5mA左右,红色LED的正向导通压降大概1.8V到2.0V,STM32 GPIO输出高电平是3.3V,所以限流电阻:
R = (3.3V - 1.8V) / 5mA = 300欧
项目里用了330欧,取值很合理,既保证了亮度,又不会让GPIO输出过流。如果用的是蓝色或白色LED,正向压降会到3.0V以上,限流电阻就得相应减小,这点画原理图的时候要留意。
继电器驱动电路是很多新手容易看懵的地方。继电器的线圈需要比较高的电流(一般几十到上百毫安),STM32的GPIO根本拖不动,所以需要三级管做电流放大。项目用了S8050这颗NPN三极管,基极通过1k电阻接GPIO,发射极接地,集电极接继电器线圈,线圈两端并联一颗1N4148续流二极管。
这个续流二极管非常关键。继电器线圈是感性负载,断电瞬间会产生很高的反向电动势,如果不加续流二极管,这个电压可能直接打坏三极管甚至MCU。续流二极管的接法要特别注意:阳极接三极管集电极(也就是线圈的低端),阴极接电源正极,这样才能在断电瞬间给线圈电流提供泄放回路。原理图里这个二极管的方向画反了的话,一上电就短路,那是灾难性的。
3.3 原理图绘制规范与工具细节
说到原理图绘制,现在很多人在嘉立创EDA上画。热词里提到"dht11原理图嘉立创画图",确实,嘉立创EDA免费、上手快,还跟嘉立创PCB打板无缝衔接,适合新手。
画原理图有几个规范要遵守。第一是栅格设置,嘉立创EDA默认栅格一般设为0.1inch或者2.54mm,画图时开启"对齐到栅格",这样引脚对齐、连线整洁,后续转PCB布线也会轻松很多。第二是网络标签的统一,电源用+3.3V、+5V、GND,信号用语义化命名,比如DHT11_DATA、OLED_SDA,不要在原理图里直接拉长线,信号多了以后会乱成一团。第三是电源符号和接地符号要统一,不要这里用VCC那里用+3.3V,最后网络表导出全乱套。
封装选择上,DHT11一般是个四脚直插模块,继电器选用5V继电器,注意引脚间距和焊盘尺寸要匹配。焊接的时候直插器件还好,贴片电容电阻用0805封装比较适合手工焊接,太小的0603对于新手来说难度会陡增。
3.4 原理图设计中的风险点和改进建议
再说几个我在原理图里经常发现的隐患,这个项目避开了大部分,但也留了一些可以优化的空间。
第一,去耦电容的位置。每个MCU的电源引脚旁边都要放一个0.1uF的陶瓷电容,并且要尽量靠近芯片引脚放置,走线要短。如果去耦电容放得离引脚很远,高频噪声滤不掉,可能导致芯片工作不稳定。
第二,SWD接口的上拉/下拉。SWDIO建议加上拉电阻,SWCLK建议加下拉电阻,这样在调试器未连接时引脚状态是确定的。这个项目把SWD接口直接引出,没加电阻,好在F103内部有上拉和下拉,默认情况下问题不大,但在电磁环境差的地方可能会出现调试器连接不稳定的情况。
第三,地平面。如果打双层板,底层尽量保持完整的地平面,特别是继电器这种大电流器件,它的地回路要单独走线,不要跟MCU的模拟地纠缠在一起。星型接地在大功率或高频场景下特别重要,虽然这个项目电流不大,但养成这种习惯没坏处。
4. 仿真验证评价:如何用仿真在打板前把逻辑跑通
仿真这部分是很多开源项目的短板,但恰恰是博主最看重的效率工具。先说结论:仿真不能完全替代实物调试,但可以帮你节省至少一半的调BUG时间,尤其是逻辑层面的问题。
4.1 Proteus仿真STM32的正确姿势
Proteus是很多人大学时用过的仿真软件,它对STM32F103系列有一定支持能力。用Proteus仿真的核心步骤是:先画好电路原理图,把STM32F103C8T6放到画布上,接好电源、晶振、复位电路,然后添加你需要的虚拟外设,比如虚拟终端(Virtual Terminal)用来模拟串口、LED、按键等,最后在Keil里编译生成hex文件,双击芯片加载hex文件,点击运行。
这里有几个注意事项。第一,Proteus默认的STM32模型可能需要设置晶振频率,你要把它设成跟实际工程一致,不然串口波特率会算不对。第二,Proteus仿真速度比较慢,尤其是跑DHT11这类对时序敏感的传感器时,仿真器对延时函数的模拟可能和实物有偏差,软件自带的延时函数在Proteus里可能需要微调。第三,Proteus对ADC和UART的支持相对成熟,但对定时器输入捕获这类外设的模拟精度参差不齐,需要实测确认。
4.2 在线仿真平台:快速跑逻辑的轻量方案
如果你不想安装Proteus这种重量级软件,Wokwi这类在线仿真平台是个很好的替代方案。它直接在浏览器里写代码、画电路、看波形,对Arduino、ESP32等平台支持得最好,STM32的支持也在逐步完善。
以我的使用感受来说,在线仿真平台最大的优势是"零配置"。注册账号、新建项目、粘贴代码、选好芯片型号,几十秒就能跑起来。对于验证某个具体的逻辑,比如串口报文格式对不对、按键消抖状态机是否正常,在线仿真完全够用。
它的短板也很明显:外设模型有限,DHT11这种传感器没有现成模型,你可能要用滑动变阻器模拟模拟量,或者用一个按钮手动触发高低电平来模拟时序。另外对中断、DMA、定时器这类硬件外设的行为模拟也比较粗糙。所以我的建议是:在线仿真用来快速验证核心逻辑,Proteus用来跑完整的软硬件配合,实物永远是最准的。
4.3 串口与传感器的仿真实操体会
这个项目里有串口日志功能,在Proteus里我用虚拟终端仿真过一版。流程是:在Proteus里放一个"VIRTUAL TERMINAL",把它的RXD接STM32的TX引脚(PA9),把TXD接STM32的RX引脚(PA10),注意交叉连接,然后设置波特率115200,数据位8,无校验,停止位1。
跑起来之后,虚拟终端里确实能看到项目上报的温湿度数据和状态信息。这一步验证的价值在于:协议格式对不对、数据帧是否完整、有没有乱码,都能在电脑上直观看到,不需要接真实的串口线。
关于串口时序还可以提一个思路:如果将来要写更复杂的串口接收逻辑,可以参考FPGA的UART_RX接收仿真方法——把波特率时钟生成、起始位检测、数据位采样、停止位校验都做细。虽然STM32用中断接收比较多,但理解了底层时序,调试串口问题时会更从容。
4.4 仿真和实物到底差在哪
仿真能帮你验证逻辑,但仿真通过不代表实物就能跑。最大的差异来自电气特性:仿真里的电压是理想的,不存在纹波、噪声、串扰;仿真里的器件是理想模型,不存在DHT11上拉电阻手抖焊歪的情况;仿真里的时钟是精确的,不存在晶振起振慢或者频率偏差。
我还遇到过一种情况:同样的代码,在Proteus仿真里能正常显示OLED,但实物上屏就是花屏或者不亮。排查半天,发现是I2C总线上拉电阻没有焊,或者上拉电阻用的是10k而不是4.7k,导致I2C时序在实物上不稳定。这种问题在仿真里根本不会出现,因为Proteus的I2C模型太理想了。
所以我的建议是:仿真负责"验逻辑",实物负责"调电气"。两者配合,把能提前暴露的问题在阶段就解决掉,剩下真正需要示波器、万用表的活再拿到实物上做,效率最高。
5. 完整复现过程与高频问题排查实录
最后这部分是我自己克隆这个项目时踩过的坑,每个问题都花过一些时间,整理出来供大家参考。很多问题看起来五花八门,本质上都是环境、接线、时序三个方面的问题。
5.1 Keil5同时兼容C51和STM32的安装细节
很多人的电脑不只是玩STM32,还要兼顾学校里的51单片机实验,那就涉及到"一个Keil下同时装C51和MDK"的问题。实际上Keil的C51和MDK-ARM是两个独立的产品,可以装在同一台电脑上,但要注意几点。
最省事的顺序是:先装C51,再装MDK-ARM。两者默认安装路径相同的话,后装的MDK会覆盖部分公共文件,但各自的编译器是独立的。装完之后,桌面上只有一个Keil uVision5的图标,新建工程时如果你的工程基于8051芯片,它会自动调用C51的编译器;如果是ARM内核芯片,会调用ARMCC或者AC6编译器。
容易踩的坑是License问题。C51和MDK的License是分开的,如果你只有MDK的License,编译51工程时会提示"No License";反之亦然。解决方法是把两个License都添加进去,在Keil的License Management界面里,License ID Code填一个,添加完再填另一个,两个都会显示为有效。
STM32芯片包安装也在这里面。装完MDK之后,还需要在Pack Installer里安装STM32F1系列的Device Family Pack,也就是Keil.STM32F1xx_DFP。如果在线安装速度慢,可以去Keil官网下载对应的.pack文件,然后通过Pack Installer的File → Import菜单离线导入。
5.2 ST-Link连接与烧录问题
ST-Link无法识别USB设备是我被问过最多的问题之一。如果你把ST-Link插上电脑,设备管理器里看不到任何STM32相关的设备,或者看到一个带着黄色感叹号的未知设备,大概率是驱动问题。先去ST官网下载最新版的ST-Link USB Driver装上,一般能解决。
驱动没问题但还是识别不了,就要查硬件了。第一,USB线是不是只有供电没有数据传输线,这个坑我踩过不止一次,看上去一模一样的两根安卓线,功能完全不同。第二,ST-Link和目标板之间的接线,SWDIO、SWCLK、GND、3.3V四根线要一一对应,千万别接反。第三,目标板供电是否正常,有些ST-Link虽然能对外输出3.3V,但电流很小,带不动整个板子,这时候要用外部电源给板子供电。
如果连上之后能识别但下载失败,可以试试ST-Link Utility这个工具。它除了能烧录程序,还能查看芯片的Flash、Option Bytes、读写保护状态。很多时候下载失败是因为芯片被设置了读保护,用ST-Link Utility把读保护解除再下载就好了。
5.3 硬件上电后的常见故障
程序烧进去之后,板子没反应是另一个高频问题。这时候先从电源和时钟查起:用万用表量3.3V电压是否正常,如果电压偏低,查AMS1117输出端的电容有没有焊反(钽电容接反会短路甚至炸);用示波器或者逻辑分析仪看8MHz晶振是否起振,如果晶振引脚上没有正弦波,检查负载电容和晶振本身。
OLED花屏的排查思路:先确认I2C地址对不对,SSD1306常见的地址是0x3C或者0x3D,软件里设置的地址要和硬件地址一致,可以通过改变SA0引脚的电平来切换。再查I2C总线的上拉电阻,F103的I2C在硬件上需要外接上拉,一般用4.7k,如果没接或者阻值太大,通信时序会不稳定。最后把I2C时钟频率降下来试试,有些OLED模块对400kHz的快速模式兼容性不好,降到100kHz就能正常显示了。
DHT11读取失败要么全0要么全255,优先查数据线的上拉电阻,DHT11单总线要求数据线上有上拉电阻,阻值范围4.7k到10k都可以,没有上拉电阻的话数据线处于浮空状态,读取结果必然是错的。然后查延时函数是否准确,一些移植过来的延时函数跟主频不匹配,本来应该延时40us的地方变成了400us,时序肯定对不上。
5.4 高频问题排查速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| ST-Link电脑不识别 | 驱动缺失、USB线是充电线 | 安装ST-Link USB Driver,换数据线 |
| 能识别但下载失败 | 芯片读保护、SWD接线错误 | 用ST-Link Utility解除读保护,核对接线 |
| 程序烧进去板子没反应 | 电源异常、晶振未起振、BOOT0配置错误 | 量3.3V电压,示波器查晶振,检查BOOT0电平 |
| OLED花屏或黑屏 | I2C地址不对、上拉电阻缺失、时钟太快 | 核对0x3C/0x3D地址,补4.7k上拉,降I2C时钟 |
| DHT11读不到数据 | 上拉电阻缺失、延时不准、线太长 | 补4.7k上拉,校准微秒延时,缩短杜邦线 |
| 继电器不停抖动 | 基极未加下拉、MCU上电瞬间误触发 | 基极到地加10k下拉电阻,GPIO初始化先拉低 |
| 串口输出乱码 | 波特率不匹配、晶振频率设置错误 | 核对代码和上位机的波特率,检查HSE_VALUE |
最后说几句我的评价和心得
如果非要给这个开源项目打一个总分,我会给到8分以上。代码结构清晰可读,原理图能看出来是认真画过的,仿真部分覆盖了核心逻辑验证,作为嵌入式入门和课设改造的素材,含金量是够的。它的扣分项主要在DHT11这个传感器本身精度和稳定性都很一般,如果要做真正意义上的监测系统,建议换成SHT30这类数字温湿度传感器,I2C接口,精度高一个数量级。
我自己在实践中最深的体会是:拿到开源项目不要急着"跑起来"就结束,一定要把代码、原理图、仿真这三者对着看一遍。代码里每操作一个寄存器,去原理图里找对应的电路,再在仿真里复现一遍行为,这个过程走完,你对项目才算真正"懂"了。很多人学了很久嵌入式,遇到新项目还是手足无措,就是因为平时只在代码层面打转,没有建立这种三重对应的直觉。
最后分享一个小技巧:如果你也想做类似的"三件套"开源项目,记住,仿真不一定要完整复刻整个系统,只仿真你最有把握出错的部分就行。我通常会把串口通信、按键逻辑和传感器时序单独拿出来仿真验证,这三块恰恰是最容易藏着隐藏BUG的地方。验证通过之后,再回到实物上去调电气,这样整个开发周期能明显缩短。