ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

STM32+HX711智能计价电子秤完整实战:从硬件选型到标定调试

STM32+HX711智能计价电子秤完整实战:从硬件选型到标定调试

电子秤这项目,放在嵌入式入门进阶这个节点上,真的是再合适不过了。做之前你可能以为就是个“称重+单价×重量=金额”,上手之后才发现,模拟前端采集、滤波算法、量程标定、按键交互、低功耗、掉电保存这些全都要碰一遍,几乎是把一套小产品的完整链路走通了。网上关于STM32的智能计价电子秤资料不少,但大多数只贴个代码、给个原理图,真正把“为什么这么设计”“调试时为什么卡住”讲清楚的不多。这篇就把我自己做这个项目时从硬件选型到软件实现的完整思路翻出来,结合实测中踩过的坑,给准备做毕业设计、比赛作品或者单纯想练手的朋友一份能直接照着做的方案。

先交代一下我做的这套东西是什么:主控STM32F103C8T6,称重传感器加HX711差分ADC采集,12864 OLED显示,三个按键完成去皮、单价设定、累计等操作,带超量程报警和掉电参数保存。整机静态电流控制到几十微安,两节18650供电实测能用很久。项目不算复杂,但做完它对STM32的GPIO、定时器、外部中断、Flash读写、低功耗模式这些资源的理解会明显上一个台阶,比单纯点灯、驱动外设要有意思得多。

1. 项目概述与整体设计思路

1.1 智能计价电子秤的应用场景与功能定位

先想清楚产品到底要解决什么问题。菜市场散称区、水果店、快递驿站按重量算运费、小卖部按斤卖干货,这些场景里传统的机械秤早就被电子秤替代了,但市面上一两百块的低端电子秤问题不少:按键手感差、显示模糊、没有单价记忆,换个商品要重新按单价,高峰期排队很烦。我这个项目做的就是“够用且可控”的智能计价秤:称重精度到克以内,单价直接按键输入,金额自动计算,去皮方便,断电后再开机单价、标定参数都不用重新弄。

这套方案适合三类人:一是准备嵌入式方向毕业设计的学生,功能点覆盖广、指标容易写;二是做课程设计或电子设计竞赛的队伍,硬件成本不到一百块,软件实现不依赖复杂算法但又能体现工程思维;三是对称重、压力传感这类模拟采集感兴趣的开发者,想搞明白HX711为什么能放大几微伏的信号、该怎么滤波标定。

我最终定下来的核心指标是这样的:量程5kg,显示分辨率1g,精度误差控制在±1g以内(常温、水平放置、标准砝码条件下实测);支持0.00到999.99元/千克的单价输入;去皮范围覆盖全量程;单价和标定参数在掉电后不丢失。这个规格对应菜市场散称场景已经完全够用,甚至比不少低端商品秤的体验要好。

1.2 为什么选STM32而不是其他方案

选型这件事值得多说两句。你完全可以用专用秤重芯片,比如芯海、纳芯微的测量SoC,集成度高、出厂校准好,改一下寄存器就能量产,但这样做完你对核心原理还是黑的,而且这类芯片资料少、开发工具不友好,不适合学习。反过来用51单片机也行,HX711读取是GPIO模拟时序,51的IO完全够用,但51的资源太紧张:显示要刷屏、按键要扫描、Flash还要存参数,程序写起来处处受限,后期扩展几乎没有空间。

STM32F103C8T6在这个项目里是性价比很高的选择。它是M3内核、72MHz主频、64KB Flash、20KB RAM,跑一个裸机状态机绰绰有余,还有足够的定时器做低功耗唤醒、硬件I2C/SPI备用。最关键的是生态成熟,CubeMX图形化初始化、HAL库封装后,新手不用跟寄存器死磕,老手也能用标准库或者寄存器操作抠细节。如果预算紧张或者想走无线化,换成ESP32或ESP8266也行,但注意它们内部ADC噪声大、不适合直接采称重信号,老老实实外挂HX711的话又多一个通信环节。所以追求稳定、练嵌入式基本功,STM32是当前最优解。

1.3 系统总体架构

整个系统分四层:物理层是称重传感器,把重量变成微弱的差分电压信号;采集层是HX711,带24位Sigma-Delta ADC和128倍可编程增益;控制层是STM32,负责读数据、滤波、标定、算金额、管理按键和显示;交互层包含OLED、蜂鸣器、按键。数据流是这样的:传感器输出毫伏级差分信号 → HX711内部放大并转为24位数字量 → STM32通过GPIO模拟时序读取原始码值 → 软件滤波和标定换算成重量 → 结合单价计算金额 → 显示调节。

这个架构看着简单,但每一层的设计选择都有讲究。比如为什么不用STM32内置ADC直接采传感器?因为应变片电桥满量程输出只有10mV到20mV,STM32内置12位ADC的参考电压是3.3V,对应分辨率也就0.8mV左右,直接采连1g的毫伏变化都分辨不出来。外接HX711相当于把“小信号放大+高精度采样”这个脏活外包出去,主控只做读数和逻辑,分工清晰。

2. 硬件方案与关键电路设计

2.1 核心器件选型与替换建议

称重传感器我用的是最常见的电阻应变式平行梁传感器,量程5kg,四线制(红黑绿白),满量程灵敏度约2mV/V。选5kg是因为我手头有标准砝码方便校验,如果你想称更大的东西,换成10kg或50kg完全没问题,电路不用改动。传感器量程有个经验法则:日常使用重量最好不要超过量程的70%,保留超载余量,否则长期压着会让弹性体变形、零点漂移加剧。

HX711是24位ADC,内部集成稳压电路和差分输入,最大增益128倍时输入信号满幅约±20mV,正好匹配应变片电桥输出。它有两个参考产品经常被拿来对比:一是ADS1232,同样的24位Sigma-Delta、带内部温度传感器、增益可选1/2/64/128,价格稍贵但性能略好;二是国产的CS1231,封装更小、功耗更低、SPI接口,适合对体积敏感的手环、体脂秤方案。对学校项目来说,HX711芯片两块钱左右、模块几十块,资料漫天飞,最折腾人也最不容易翻车。

主控选了STM32F103C8T6,48脚LQFP封装,价格在几块钱到十几块钱之间波动,Flash 64KB、RAM 20KB。如果画PCB嫌LQFP焊接麻烦,可以用STM32F103C8T6的最小系统板,插面包板或直接飞线,一样能做。我后来画了块PCB,但初期验证阶段就是用核心板加模块飞线完成的,逻辑完全一致。

显示部分我推荐0.96寸I2C接口的SSD1306 OLED,128×64分辨率。它功耗低、显示内容灵活,能同时显示金额、单价、重量三组数据,还能调大字号。缺点就是强光下看不清,如果秤要放在户外或者阳光直射环境,老老实实换LED数码管或者LCD1602都行,数码管在强光下的可读性远好于OLED。按键用三个轻触开关就够了,后面我讲具体怎么分配功能。

2.2 传感器、HX711与STM32的接线规划

硬件接线这件事,我一开始以为照着网上原理图连就行,实际连的时候还是翻车了一次,把传感器红黑接反,HX711读数直接满幅失真。这里把最终确认可用的连线表列出来:

信号传感器/HX711STM32引脚说明
HX711 SCK模块SCKPA1时钟输入,低到高移位
HX711 DOUT模块DOUTPA0数据输出,低电平表示转换完成
HX711 VCC模块VCC5V或3.3V推荐5V,内部稳压后供电更稳
HX711 GND模块GNDGND必须与单片机共地
传感器红E+接HX711激励正激励电压一般为5V
传感器黑E-接HX711激励负
传感器绿S+接HX711通道A正输入
传感器白S-接HX711通道A负输入

这个引脚规划有几个细节要注意:PA0和PA1我同时需要考虑外部中断和复用功能,万一其他模块占用就冲突了,所以原理图阶段就要把引脚资源表画出来,避免做PCB时才发现引脚打架。HX711的VCC我用的5V,因为它内部稳压电路会把AVDD稳到5V或者按芯片手册配置,给传感器电桥提供一个稳定的激励源。如果你用3.3V供电,也可以工作,但信噪比会下降,实测零点跳动会略微增大。

HX711模块和单片机之间靠GPIO模拟时序,不需要任何协议库,这就意味着只要引脚电平兼容就行,3.3V单片机读5V模块的数字输出也没问题(DOUT输出高电平约为VCC,而HX711模块如果VCC=5V,其DOUT高电平是5V左右,STM32引脚一般是FT兼容5V的,PA0/PA1是兼容5V的,可以直连;如果用的引脚不是FT电平容忍,最好串个1k电阻分压)。

2.3 电源、稳压与硬件抗干扰设计

电源部分如果只求能跑,用USB供电就够了。但既然是“智能计价电子秤”的项目,我建议直接上电池,顺便体验一把低功耗设计:两节18650串联供电,经LM2596或者MP1584降压到5V,再给单片机和HX711。注意一点,HX711的模拟供电和数字供电要好好滤波:AVDD对地加一个47uF电解电容和0.1uF陶瓷电容并联,这个组合能显著抑制ADC读数跳动,我实测滤波电容从无到有,零点稳定性肉眼可见地提升。

硬件抗干扰这块给新手几个明确建议:

第一,传感器线要双绞线或者屏蔽线,而且尽量远离电机、继电器、PWM走线。称重系统最怕的就是高频噪声耦合进模拟前端,虽然HX711是差分输入能抑制共模干扰,但线要是拉太长、挨着大电流走线,照样会跳字。

第二,模拟地和数字地单点汇合。HX711模块的GND和单片机GND之间用一根尽量粗的短导线或者直接在PCB底层大面积铺铜连在一起,不要绕圈也不要形成环路。

第三,按键脚、复位脚加上拉电阻和100nF滤波电容,能减少按键抖动引起的外部中断误触发。蜂鸣器如果是无源蜂鸣器,用三极管驱动,注意续流二极管或者RC吸收,防止关闭瞬间的反电动势干扰传感器。

3. 核心代码实现与关键算法

3.1 工程搭建与代码分层策略

这一节把软件工程的做法捋顺,很多人写嵌入式的通病是“main.c五百行、寄存器满天飞”,项目能跑但改一个显示函数要全局搜,维护成本高。我先用STM32CubeMX生成基础工程,选STM32F103C8T6芯片,配置好PA0/PA1为GPIO输入/输出、外部中断、三个按键GPIO、OLED的I2C(如果选I2C OLED,可以把I2C1 SCL/SDA设为PB6/PB7)、一个定时器作为软件时基(比如TIM4做1ms中断)、Flash和RTC相关时钟。生成代码之后,我额外建了四个目录:

Core/ -- CubeMX生成的启动文件和内核相关 Drivers/ -- HAL库 App/ -- 业务逻辑:weigh、key、ui、data_store、main_task Middlewares/ -- OLED驱动、HX711驱动等第三方代码

App目录下的文件才是整个项目的核心,main.c只做初始化和调用App_Init()、App_Loop()。这样的分层带来的直接好处是:我想把HX711驱动从GPIO模拟改成硬件SPI,只用改Drivers层,上层业务不用动;我想加一个Wi-Fi模块上报数据,新增一个network文件就行,不影响称重逻辑。这个习惯如果你现在养成了,后面做嵌入式Linux或者更大项目时会轻松很多。

3.2 HX711 读取与滤波:从时序到稳定读数

HX711的数字接口很简单:DOUT拉低表示转换结束,SCK产生24个上升沿把24位数据依次移出,第25个上升沿让芯片进入下一次转换。数据是二进制补码格式,最高位是符号位,读取后要转成有符号数。基础读取函数的经典写法如下:

uint32_t HX711_Read(void) { uint32_t count = 0; uint8_t i; // 等待DOUT变低,表示转换数据已经准备好 while (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) == GPIO_PIN_SET); for (i = 0; i < 24; i++) { HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); delay_us(1); count = count << 1; if (HAL_GPIO_ReadPin(HX711_DOUT_GPIO_Port, HX711_DOUT_Pin) == GPIO_PIN_SET) { count++; } HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); delay_us(1); } // 第25个脉冲,让HX711开始下一次转换 HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_SET); delay_us(1); HAL_GPIO_WritePin(HX711_SCK_GPIO_Port, HX711_SCK_Pin, GPIO_PIN_RESET); return count; }

读取一次只能得到一个原始码值,但HX711的输出速率默认10Hz(通道A 128增益),也就是说每100ms才刷新一次。如果直接把这个码值去标定显示,零点处会看到个位数字一直跳,这不是芯片坏了,而是正常噪声叠加。解决办法是在应用层做滤波,我试过三种方案,差异明显:

滑动平均滤波(N=8):实现简单,动态响应快,但偶尔一个毛刺会把结果拉偏。 中值滤波(窗口5):能干掉脉冲毛刺,但输出不平滑,显示数字会有“台阶感”。 滑动平均+中值组合:先取5个原始值排序取中值,再对连续4个中值做滑动平均,实测读数稳定性和动态响应都能接受。

这个组合的成本是多读几次数据,好在HX711读取本身非常快,用不了多少CPU。最终我确定了每次称重显示周期大约200ms更新一次,取组合滤波后的结果,既不会让人感觉秤“迟钝”,也不会看到读数疯狂跳变。

3.3 标定流程与重量换算

所有称重设备的核心都在标定。简单说,标定就是建立“ADC原始值”和“实际重量”之间的映射关系。工程上最可靠的是两点标定法:零点取空秤读数,满点取已知标准砝码读数,然后线性插值。

我标定的流程是这样的:首先保证秤在水平台面上、传感器四个角受力均匀(如果四个角受力不同,读数会是斜的,这一点下面讲常见坑)。空秤时连续取50次组合滤波后的原始值求平均,记为zeroRaw。放上一个精确的标准砝码(我用500g和2kg两个档位分别校验),取50次求平均记为refRaw。比例因子factor = (refRaw - zeroRaw) / 标准重量(单位g)。实际重量weightGram = (当前原始值 - zeroRaw) / factor。

这套逻辑写起来不复杂,但有一个小坑:factor如果用浮点数运算,单片机的小数点保留要注意,我直接用float,最终显示用取整,精度实测能到±0.5g左右;如果为了固件精简用整数运算,很容易把小数部分截掉,导致称重出现系统性偏差。所以标定参数保存的时候我会把zeroRaw和factor都转成uint32_t,但计算时明确转成float再做算数。

标定参数存哪?很多方案会外挂AT24C02 EEPROM,但我觉得对F103来说没必要,直接用内部Flash的一个扇区。F103的Flash按页擦除,每页1KB(小容量芯片每页可能不同,这个要看芯片手册),我选最后一个扇区,把结构体一次性写入。注意写Flash前要整个扇区擦除,擦除操作耗时要几十毫秒,不能在正常称重过程中插进来,否则会卡主循环。

3.4 去皮逻辑与置零切换

去皮是计价秤的刚需功能。买菜时用户得先放个容器,再按去皮把容器重量清零。实现逻辑不复杂:记录当前实际重量作为皮重tareWeight,显示重量 = 实际重量 - 皮重。但有个细节容易忽略:去皮之后,实际重量不能超过传感器量程减去皮重再加载货,否则传感器过载。所以我的代码里专门加了一个判断:

if (actualWeight > (MAX_LOAD - tareWeight)) { // 提示超量程,蜂鸣器报警,置零后不能正常计价 }

另外“去皮”和“置零”要分清:置零是把当前值当作零点存储到标定参数里,对系统来说相当于永久改了零点;去皮只是临时把当前值当作皮重,下次重新上电就恢复。我这套系统里,短按去皮键执行去皮,长按则进入置零操作,这样同一个键承担两个功能,UI上也能提示“去皮”和“清零”状态。

3.5 单价输入、金额计算与显示布局

单价输入是纯交互逻辑,设计不好用起来特别别扭。我用了三个按键:K1负责单价数字输入和位选,K2负责加减,K3负责确认与去皮。具体交互方案:

初次输入单价时,OLED先显示0.00,K1每按一次切换到位数(百位、十位、个位、小数第一位、小数第二位),当前选中的位反色闪烁;K2在选中位上加一,超过9自动归零;确认后K3锁定单价,此时每放置一次商品,称重刷新后自动计算金额 = 重量(kg) × 单价(元/kg)。

金额计算我用的是整数分的方式避免浮点误差:weightGram是float,单价unitPrice是uint16_t(单位是分/千克)。总金额cents = (uint32_t)(weightGram / 1000.0f * unitPrice),最后两位小数显示到“分”。这样做的好处是显示和计算都不用担心浮点丢精度,后面给外部设备传金额也方便。

显示界面我切成上下两行:上方用16号字体显示金额,中下方用12号字体分别显示单价和重量,单位用kg和元/kg,因为OLED亮度衰减和刷新次数有关,我还做了30秒无操作自动熄屏,但保持称重和计价正常进行。

3.6 掉电保存、低功耗与报警设计

掉电保存我用了前面说的内部Flash方案。值得强调的是,保存不能太频繁——Flash擦写寿命一般是1万次到10万次,你要是每次称重都保存,几个月就废了。我的策略是:单价和标定参数只在“单价确认”或“置零”时保存一次;称重过程中的临时数据不保存,掉电后恢复出厂零点标定即可。

低功耗这块,我把板子整机电流降到了可接受范围,三个手段叠加:OLED熄屏,HX711进入掉电模式(PD_SCK持续高电平超过60us即可进入掉电,这个寄存器操作是在读取函数里完成的:读完第25个脉冲后,如果让SCK保持高电平一段时间,芯片进入掉电),单片机进入STOP模式,用RTC闹钟每100ms唤醒一次去检测重量变化。如果检测到重量变化超过阈值,就唤醒屏幕并恢复正常工作;超过几分钟无动作再进休眠。这套逻辑做完以后,两节18650供电大概能撑很久,比一直开机刷屏省太多。

报警设计也不复杂:超量程或金额超过上限时,PWM驱动蜂鸣器响三短声,OLED第一行闪烁显示“Over”之类的提示。

4. 联调流程、调试技巧与常见问题排查

4.1 我把调试步骤总结成了顺序清单

拿到一个新板子或者飞线搭的电路,一上来就写完全部代码然后烧录,这不叫调试,叫赌运气。我推荐的拆解顺序是:先点亮最小系统和串口——确认时钟、复位、下载通道没问题;再单独读HX711原始值并串口打印,确认模拟前端和传感器接线正确;然后调OLED显示,确认I2C通信和地址没问题;再写按键扫描,最后才把称重、显示、按键组合起来跑完整流程。

这样做的核心原因是隔离变量。如果一上来就烧全部代码,出问题大概率不知道是显示没初始化还是键没扫到还是标定参数不对。每层都验证通过以后,组合阶段出问题就只可能出在状态机逻辑或时序上。我的Type-C串口打印帮了大忙,比如调试时发现某个按键偶尔响应,看一下按键扫描打印的原始电平,马上就知道是没去抖还是中断优先级冲突。

4.2 高频问题排查实录(含速查表)

做这个项目的人大概率遇到过下面这些问题,我把自己的排查过程整理成表,方便你照着来:

现象可能原因排查与解决
板子上电无反应电源接反、复位电容没焊、BOOT0悬空进不了Flash启动测3.3V/5V对地电压,检查BOOT0拉低、复位脚电平,用示波器看8M晶振
HX711读数一直0x7FFFFF或极值传感器E+和E-接反、差分输入短路、HX711供电不够用万用表量E+/E-电压差,确保约1V级差;交换红黑线
零点读数跳动超过几个码电源纹波大、传感器线与干扰源太近、滤波窗口小加AVDD大电容,屏蔽线单端接地,加大滤波次数
称重结果四角偏差大传感器受力不在中心、平台刚性不足重新固定传感器,保证四个安装孔受力均匀,不要用胶粘
OLED不显示或花屏I2C地址错误、接线反、波特率过高、SSD1306复位时序不对用I2C扫描工具确认0x3C或0x3D地址,SCL/SDA交换,把I2C速度降到100k
按键偶尔不响应内部/外部上拉缺失、未去抖GPIO配置上拉,软件延时10-20ms去抖,或用定时器扫描状态机
下载程序失败下载引脚被复用、芯片锁死、BOOT0没拉低按住复位下载,Flash全擦,检查PA13/14未被占用,必要时串口ISP清锁定

这里单独说一下“I2C读设备ID读到A1A1”的问题。虽然这个项目用的是OLED不是ILI9341,但我在帮别人排查SPI屏时见过太多次这种怪现象:读ID得到的值是0xA1A1而不是芯片真实ID。这种问题十有八九不是芯片坏了,而是读ID的寄存器地址不对、时序参数没匹配(比如SPI模式搞成了Mode 0而芯片要Mode 3)、或者数据位顺序反了。我自己的经验是:凡是遇到这种“读数看起来有规律但就是不正常”的问题,先别调代码,拿逻辑分析仪看一眼波形,CLK、MOSI、MISO三根线的相位对不对一目了然。很多嵌入式问题都是这种排查思路——先确认硬件时序,再怀疑固件逻辑。

4.3 调参心得:我标定时遇到的真实案例

标定环节我遇到过一个很典型的问题:第一次标定时,我把500g砝码放上去,显示552g,偏了10%。检查了HX711增益、滤波都没问题,后来才发现是秤盘底下的支撑结构没做稳,传感器弹性体上放砝码时整个平台轻微晃动,等效于给传感器加了一个额外的偏置力矩。把支撑结构换成四角平衡的铝板后,标定一次通过。

还有一个容易忽视的问题:温度漂移。传感器在刚开机的前几分钟,内部应变片会因为通电自热和环境影响发生零点漂移,我控制的方案是开机后做一个“预热”流程,显示“Init...”倒计时几秒才开始允许称重,这个细节在商品秤上是标配,咱们自己做的也应该加上。

5. 项目复盘与后续扩展方向

5.1 我在这套方案里验证过的几个关键结论

整个项目做完,最大的收获倒不是“会用STM32读传感器了”,而是对“嵌入式产品的完整生命周期”有了体感。硬件选型直接决定后面的工作量,比如用了I2C OLED虽然省引脚,但I2C调试本身对新手是个坎;用了HX711虽然价格便宜、资料全,但它的10Hz输出速率让滤波算法的窗口长度不能太大,否则动态响应会差到让人想砸秤。

代码分层确实能帮你节省大量时间。我写这套系统时,因为前两个星期已经把weigh、ui、key这些模块分开并且各自调试通了,最后联调只花了一个下午,出bug也能快速定位到模块而不是在main函数几百行里翻。

标定和称重原理这部分,值得多看几遍传感器手册。我后来试着用STM32内部ADC直接采集,效果很差,才真正理解为什么这类产品都外挂专用ADC——不是STM32不行,而是应用场景需要的是微伏级分辨率和长期稳定性,这恰恰是通用MCU内置ADC的短板。

5.2 站在项目基础上的扩展方向

这个项目改造成本很低,我列几个自己考虑过或者已经动手试过的方向,供你参考:

第一,加联网远程监控。用一个ESP8266模块通过串口或者SPI和STM32通信,把重量、金额、交易流水定时上传到云平台。市面上就有用巴法云这类物联网平台做数据看板的,手机端就能看到秤的状态,这在商超管理、无人售货柜里很有实用价值。注意加联网之后,功耗策略和本地数据备份都要重新设计,不能因为网络模块把整个系统的低功耗毁掉。

第二,把裸机改造成RTOS系统。这个项目逻辑不算复杂,裸机状态机完全能Hold住,但如果你想让OLED刷新、HX711采集、按键扫描三个任务解耦,用FreeRTOS或RT-Thread明显更舒服。特别是OLED刷新可以用低优先级任务,按键和称重用高优先级,实时性更有保障。换个RTOS之后再看这个项目,你会发现代码组织方式又能优化一轮。

第三,换更高精度的传感器和ADC。把HX711换成24位的AD7190或者国产高精度ADC,传感器换成0.02%精度等级,再配合温度补偿,整机可以做到实验室分析天平级别的分辨率。不过这个级别的项目要处理的问题从“代码”变成“硬件和计量”,成本也会上去。

最后再分享一个我的小技巧:不管用什么开发环境,我都习惯在工程里加一个自检函数,上电后自动打印关键模块的硬件状态——读HX711原始值、OLED地址、Flash里标定参数的CRC校验值。这样即使隔了几个月再拿起这个板子,也能快速判断硬件是好是坏,不至于一上来就陷入“是不是代码坏了”的怀疑循环。这点对我这种喜欢把项目翻出来复用的人来说,比什么都管用。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进