十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于STM32的开源图书馆环境监测系统:温湿度光照粉尘采集与仿真

基于STM32的开源图书馆环境监测系统:温湿度光照粉尘采集与仿真 图书馆这个地方看着安静其实环境参数特别讲究。人一多CO₂浓度上去了闷得慌梅雨季湿度大书页发霉北方的冬天又干得嘴唇起皮。我在学校做实验室助理那阵子管理员三天两头问我能不能搞个小玩意儿实时看看阅览室的温湿度、光照和空气状况。市面上的成品监测仪要么贵得离谱要么数据不开放没法自己二次开发。后来我就动了心思用STM32搭一套图书馆环境监测系统把代码、原理图、仿真全部整理开源出来。这套东西能采集温湿度、光照强度、空气中的颗粒物浓度本地OLED实时显示超阈值蜂鸣器报警还能通过串口把数据推给上位机记录。适合刚入门STM32的在校学生、想做课程设计的同学以及想低成本部署多点监测的小型场馆管理员参考。整套方案主控成本控制在三十块以内仿真工程不用买任何硬件就能跑通逻辑非常适合拿来当练手项目。1. 项目缘起与整体方案设计1.1 图书馆场景到底需要监测哪些量先说场景需求不谈需求直接上代码的都是耍流氓。图书馆和普通家庭环境最大的区别在于它是一个人员密集、静态陈列物品多、对防潮防霉有刚性要求的封闭空间。我蹲点观察了一周把痛点归成四类。第一类是温湿度。纸质书最怕的是高温高湿温度长期超过28℃、相对湿度长期高于65%霉菌孢子就开始活跃书脊的胶装容易开胶。同时温度太高人也坐不住阅览室的舒适区间大概在22℃到26℃、湿度40%到60%之间。第二类是光照。书库长期被强光直射纸张会发黄变脆这就是所谓的光老化。靠窗的书架和过道尽头光照差异很大管理员其实很想知道哪些区域需要加遮光帘。监测光照不是为了省电是为了保护文献。第三类是空气质量里的颗粒物。人流量大的时候地面扬尘、衣物纤维都会飘起来PM2.5和PM10浓度会明显上升对过敏体质的读者很不友好。这个量不像温湿度那么直观必须靠传感器量化。第四类是可扩展项比如CO₂浓度和噪声。CO₂是判断通风是否到位的好指标人一多它就涨噪声则直接关系阅览体验。这两项我在开源版本里预留了接口但没有做成默认必装原因后面在选型章节会讲清楚。把这四类需求翻译成工程语言就是温度、湿度、光照强度、颗粒物浓度四个必测物理量加两个可选量再加一个报警输出和一个数据上传通道。1.2 为什么选STM32而不是树莓派或Arduino这是每个做环境监测的人都要问自己的第一个问题。我三种方案都实际做过给你掰扯清楚取舍逻辑你就能明白为什么这个项目落在STM32上。树莓派是跑操作系统的。它的优势是算力强、能跑Python、联网方便但缺点在图书馆这种场景里被放大了启动慢、断电不友好、功耗高、长期运行有SD卡损坏风险。你要的是一个插上电就默默工作几个月不用管的小盒子不是一台会死机的迷你电脑。而且树莓派成本摆在那里要做多点部署一个阅览室放三四个预算立刻爆表。Arduino Uno开发门槛最低生态也成熟问题是资源太紧。UNO只有2KB RAM、32KB Flash你要同时跑DHT11时序、驱动OLED、做滤波算法、再挂个串口协议栈很快就捉襟见肘。而且UNO的ADC是10位、参考电压固定做颗粒物这种需要一定精度的采集有点勉强。STM32F103系列是一个甜点。它基于ARM Cortex-M3内核主频72MHzFlash 64KB、RAM 20KB资源对这个小项目来说绰绰有余。ADC是12位有多路通道可以同时接模拟和数字传感器。外设丰富I2C、SPI、USART、定时器一应俱全。更关键的是价格F103C8T6核心板加上最小系统单板成本能压到十几块批量部署毫无压力。低功耗模式也成熟如果做电池供电的版本待机电流能压到微安级。一句话总结取舍要联网算力选树莓派要极简原型选Arduino要性价比、稳定性和可量产性的平衡STM32F103是最不容易翻车的选择。1.3 系统整体架构与数据流方案定了STM32接下来把系统拆成三层感知层、处理层、交互层。这个分层不是为了好看是为了让每部分能独立调试、独立替换。感知层就是各个传感器。温湿度用DHT11或者DHT22光照用BH1750数字光照传感器颗粒物用GP2Y1010AU0F这类光学粉尘传感器。它们的输出形式不同有的走单总线有的走I2C有的直接出模拟电压处理层要能全部兼容。处理层是STM32主控。它的活儿分四步第一步按各自的时序或协议把原始数据读进来第二步做必要的换算和滤波比如粉尘传感器的模拟电压要换算成浓度值温湿度要做滑动平均去抖动第三步做阈值判断超限就触发报警第四步把数据打包一路送OLED显示一路通过串口或ESP8266推给上位机。交互层包括OLED显示、蜂鸣器报警和上位机。OLED用SSD1306128x64分辨率能把四个测量值加状态图标排得很清楚。蜂鸣器负责本地声光提示。上位机这部分我在开源版本里给的是Python串口接收脚本收到数据后追加写CSV方便后面做趋势分析。整个数据流可以这样理解传感器是眼睛STM32是大脑OLED是脸串口和上位机是嘴。眼睛看到什么大脑判断一下脸上显示出来需要报告的时候就用嘴说出去。提示分层设计的好处是当你发现某个传感器不合适想换型号时只需要改感知层驱动和处理层的一小段换算代码其他部分完全不用动。我在第一版里用的是模拟温度传感器后来换成DHT11改动量不到二十行。2. 硬件选型与原理图设计拆解2.1 主控最小系统的关键细节很多新手拿到核心板就直接插杜邦线开工结果跑着跑着程序莫名复位查半天查不出问题。根源往往在最小系统上。STM32F103C8T6要稳定工作最小系统必须包含几样东西电源滤波、复位电路、时钟电路、启动模式配置和调试接口。电源部分核心板通常自带AMS1117-3.3V稳压输入5V输出3.3V。但你要注意AMS1117的静态电流和压差都不算优秀如果整个系统峰值电流超过300mA比如加上WiFi模块瞬间发射建议单独给WiFi供电或者在3.3V上并一个大电容。我自己在板子上并了100μF电解电容加0.1μF陶瓷电容专治上电瞬间的电压跌落。复位电路一般是10kΩ上拉加100nF到地核心板已经做了不用重复。时钟电路是重点F103外部晶振用8MHz配合内部PLL倍频到72MHz。这里有个坑晶振旁边的负载电容通常是20pF左右如果你画PCB时走线太长或者用了劣质晶振可能出现起振慢甚至不起振。仿真里看不出来实物上表现为程序跑飞或者串口乱码。启动模式BOOT0和BOOT1要拉对。正常运行BOOT0接GND从Flash启动要串口下载就临时拉高BOOT0。我见过有同学把BOOT0悬空结果偶尔启动到系统存储器模式程序根本不跑查了半天以为是代码问题。调试口SWD就两根线SWDIO和SWCLK强烈建议硬件上留出排针。调试阶段你会感谢自己。用ST-Link下载和单步调试比串口打印高效得多。下面这张表把关键引脚分配列出来方便你对着原理图接线。功能模块引脚接口类型备注DHT11温湿度PA0单总线需4.7kΩ上拉BH1750光照PB6/PB7I2C1SCL/SDA需上拉OLED SSD1306PB8/PB9软件I2C独立于硬件I2C粉尘传感器PA1ADC1_IN1模拟量输入蜂鸣器PB5GPIO输出经三极管驱动ESP8266PA9/PA10USART1TX/RX交叉2.2 传感器选型背后的取舍选传感器是这个项目最容易花冤枉钱的地方我把每种的选择逻辑讲透。温湿度这块DHT11和DHT22是绕不开的两个选项。DHT11便宜单只不到五块但精度只有±2℃温度和±5%湿度分辨率也低。DHT22贵一些精度能到±0.5℃和±2%量程也更宽。图书馆场景其实DHT11够用因为你要看的是有没有超出舒适区间而不是精确到小数点后两位。我在开源版本里默认用DHT11代码里留了宏定义想换DHT22改一个参数就行两者的时序协议几乎一样只是数据位数和换算公式不同。光照传感器我纠结过光敏电阻和BH1750。光敏电阻便宜到几毛钱但它是模拟量输出随温度漂移而且要做标定才能得到勒克斯值个体差异还大。BH1750是数字I2C输出直接给你勒克斯lux值精度高、免标定虽然单价要五六块但省下来的标定和调试时间远超这点成本。对图书馆这种要横向比较不同区域光照的场景BH1750的绝对值输出很关键。颗粒物传感器是个大坑必须重点讲。市面上便宜的粉尘传感器大多是红外光学原理靠颗粒物散射红外光来估算浓度输出模拟电压。它的问题是只能给相对趋势不能给准确绝对值而且受温湿度影响大。我选的是GP2Y1010AU0F这个经典型号便宜、资料多但它需要脉冲式驱动LED采样时序有讲究直接接ADC读出来是不准的。它的红外LED要按周期通断在LED点亮的那一瞬间采样才能避开环境光干扰。这个时序细节后面代码章节会展开。CO₂和噪声我为什么没做成默认配置CO₂传感器无论NDIR还是电化学价格都偏高而且需要一个预热过程不适合频繁断电的场景。噪声的话用驻极体麦克风加放大电路能做但需要额外做FFT或者取包络对初学者来说增加了理解成本。所以这两项做成预留接口想扩展的人自己接我不会把它们塞进主体流程里拖慢所有人。传感器型号单价区间接口精度适用度温湿度DHT113-5元单总线±2℃/±5%RH推荐温湿度DHT2210-15元单总线±0.5℃/±2%RH进阶光照BH17505-8元I2C1-65535lux推荐光照光敏电阻0.5元ADC需标定不推荐粉尘GP2Y101015-25元模拟脉冲相对趋势推荐粉尘PMS500340-60元UART较准进阶2.3 电源与外围电路的避坑设计电源这一块看着简单实际是稳定性问题的重灾区。整个系统有三类负载数字部分STM32、OLED、模拟部分粉尘传感器、无线部分ESP8266。它们的供电特性完全不同。数字部分对电压波动不敏感但对噪声敏感。OLED刷新时会有脉冲电流如果和模拟部分共用一条细走线噪声会串到ADC里导致粉尘读数跳动。我的做法是模拟部分单独走一根电源线并且在粉尘传感器的VCC和GND之间就近放0.1μF加10μF的滤波电容。ESP8266是最大的害群之马它发送数据时瞬时电流能到200mA以上很多人的系统一联网就复位就是因为它把3.3V拉下去了。解决办法要么给它单独供电要么在它的电源脚旁边放一个470μF的电解电容做能量缓冲。我用的是后者实测联网瞬间电压跌落从0.4V降到0.1V以内复位问题消失。蜂鸣器虽然电流不大但它是感性负载关断瞬间会产生反向电动势。直连GPIO不仅可能烧IO口还会干扰附近的信号。标准做法是用一个NPN三极管比如S8050做开关GPIO接基极串1kΩ电阻蜂鸣器接在集电极和VCC之间并联一个反向的续流二极管。这个二极管很多新手会漏掉加上之后蜂鸣器咔咔的杂音都会小很多。PCB布局上晶振要尽量靠近主控下面不要走线最好挖空或者敷铜隔离。I2C的两根线走线不要太长超过20厘米就考虑降低速率或者加缓冲。这些都是仿真里体现不出来、必须靠经验积累的细节。3. 固件代码实现与关键驱动3.1 开发环境搭建和工程骨架工欲善其事环境先搭好。我推荐用Keil MDK或者STM32CubeIDE前者资料多、寄存器级操作直观后者免费、HAL库封装好、跨平台。开源工程我提供了CubeIDE版本的完整配置用Keil的同学可以参考着改。CubeIDE里第一步是用CubeMX配置外设这一步千万别偷懒手写寄存器。配置清单大致是RCC里开启外部晶振HSE时钟树把SYSCLK配到72MHzGPIO里把用到的引脚配好模式和上下拉ADC1开启通道1并设置采样时间USART1配成115200波特率I2C1配成标准模式100kHz。配置完生成代码工程骨架就有了。这里有个小经验CubeMX生成的中断优先级和DMA配置容易让新手迷惑。这个项目其实不需要DMA数据量很小直接轮询读就行。中断只用到了滴答定时器做延时外加一个串口接收中断。保持简单是这个项目的一个设计原则能用轮询就不上中断能不上DMA就不上DMA减少出错面。工程目录我分成几个文件夹Core放主逻辑Drivers放CubeMX生成的库User放自己写的传感器驱动比如dht11.c、bh1750.c、oled.c、dust.c。每个驱动只对外暴露两三个函数读写和初始化这样主逻辑里调用起来清爽换传感器也只需替换对应文件。3.2 温湿度与光照驱动实现DHT11的难点在时序它用的是单总线协议通信全靠拉高拉低的时间长短来编码没有独立时钟线。主机先拉低至少18毫秒作为起始信号然后释放DHT11响应后再连续送40位数据8位湿度整数、8位湿度小数、8位温度整数、8位温度小数、8位校验和。关键点是每一位数据的0和1靠高电平持续时间区分0是26到28微秒1是70微秒左右。所以读的时候要先用while等电平变化再延时大约30微秒后采样判断这时是高还是低。这个延时精度要求高不能被打断。我实现的时候是先关总中断读完再开避免其它中断打乱时序。// dht11.c 关键读取函数简化示意 uint8_t DHT11_ReadByte(void) { uint8_t i, byte 0; for (i 0; i 8; i) { while (DHT11_PIN 0); // 等待50us低电平结束 Delay_us(40); // 延后40us判断电平 byte 1; if (DHT11_PIN 1) byte | 1; while (DHT11_PIN 1); // 等待本位高电平结束 } return byte; }注意Delay_us这类微秒延时函数千万别用系统滴答定时器实现因为SysTick默认1毫秒中断精度不够。要么用空循环掐时间要么用定时器做精确计数。我用的是空循环加编译优化等级固定的方式简单可靠。BH1750就舒服多了纯I2C通信命令很简单上电后发送0x01开电源发0x10进入连续高分辨率模式之后直接读两个字节拼起来除以1.2就是lux值。这里要提醒一句BH1750的测量范围大但在强光下高分辨率模式会饱和如果需要测很亮的环境要切到低分辨率模式。// bh1750.c 读取函数 float BH1750_ReadLux(void) { uint8_t buf[2]; I2C_ReadBytes(BH1750_ADDR, buf, 2); uint16_t raw (buf[0] 8) | buf[1]; return raw / 1.2f; }代码里我加了一级滑动平均滤波连续采5次取平均再上报。别小看这一步DHT11和BH1750在真实环境下读数都会有小幅跳变不滤波的话OLED上的数字一直闪看着就像坏了。3.3 颗粒物传感器的脉冲采样技巧这是整个项目里最容易被做错的地方我单独拿出来说。GP2Y1010AU0F的引脚里有一根LED驱动脚它要求你按周期给一个短脉冲去点亮内部的红外LED然后在点亮后的大约0.28毫秒时刻去读模拟输出脚这时候读到的是有LED照射时的散射光强度减去LED熄灭时的本底值才是真正的粉尘信号。如果你不按这个时序直接把输出脚接ADC一直读读到的其实是环境光加电路噪声数值随光照变化完全没有意义。很多网上抄来的代码就是这么干的能跑但数据不可信。正确的做法是用一个定时器或者软件延时产生周期为10毫秒、宽度约0.32毫秒的脉冲。点亮后延时0.28毫秒采样熄灭后再采一次作为本底。可以这样写// dust.c 采样一次 float Dust_ReadOnce(void) { float v_on, v_off, voltage; LED_PIN_HIGH(); // 点亮红外LED Delay_us(280); // 等待稳定 v_on ADC_Read(DUST_CH); LED_PIN_LOW(); // 熄灭 Delay_us(40); v_off ADC_Read(DUST_CH); voltage v_on - v_off; // 去除本底 // 电压转浓度经验公式需按传感器单独标定 return (voltage - 0.6f) / 0.005f; }换算公式里的系数不是固定值不同批次传感器有差异我用的是公开资料里常见的经验系数。想要更准得上标准粉尘环境标定普通项目用相对趋势就够了。这里我给的建议是多做几次采样取中位数而不是平均值因为偶尔会有异常大的跳变平均值会被带偏中位数抗干扰更强。3.4 显示、报警与数据上报逻辑OLED走的是SSD1306驱动我用的是软件I2C原因是硬件I2C已经被BH1750占了而且软件I2C的引脚可以随便换调试方便。显示内容我排成两列左边温度湿度右边光照粉尘顶上留一行显示状态和是否报警。刷新频率不用太高每500毫秒刷一次就够刷太快占CPU还伤屏。报警逻辑是核心业务。我给每个量都设了上下限比如温度低于18℃或高于28℃报警湿度低于35%或高于65%报警光照超过某个lux值报警粉尘超标报警。报警时蜂鸣器按响两秒停一秒的节奏间歇鸣叫而不是一直响这样既不吵人又能引起注意。OLED上对应的数值会闪烁或者前面加个感叹号。数据上报我用的是USART1直接接USB转TTL就能在电脑上看如果想无线可以用ESP8266做透传。协议设计得很简单一行一个数据包用逗号分隔T24.5,H55.2,L320,D12.3,SOK。这样上位机解析起来毫无难度用Python的split就能拆开。# 上位机接收脚本片段 import serial ser serial.Serial(COM3, 115200, timeout1) with open(env_log.csv, a) as f: while True: line ser.readline().decode(utf-8, errorsignore).strip() if line.startswith(T): f.write(line.replace(, ,).replace(,, ,) \n)上位机这边我特意做成追加写CSV不覆盖方便长期记录。你甚至可以挂个脚本每周生成一张趋势图这些扩展空间都留给使用者。这里有个小提醒CSV文件长时间写要记得定时flush或者用with语句保证关闭时落盘不然断电会丢最后一段数据。4. 仿真验证与联调过程4.1 为什么这个项目一定要跑仿真有人觉得做STM32项目直接上实物就行仿真多余。我以前也这么想直到有一次接错了电源脚一口气烧了两块板子加一个传感器才知道仿真省钱有多重要。仿真的价值有三个。第一是验证逻辑不接硬件就能确认代码流程走不走得通、状态机对不对、阈值判断准不准。第二是验证原理图仿真软件里可以把元件拖进来连线很多接线错误在画图阶段就暴露了。第三是方便教学和分享你把仿真工程发出去别人不用买任何东西就能跑起来看效果特别适合开源项目传递。我在开源包里提供的仿真工程包含了主控、传感器模拟源、OLED显示和串口终端。传感器数据用软件方式注入可以手动拖动滑块调节温湿度光照值实时看系统怎么响应。这个对理解阈值逻辑特别直观。4.2 仿真工程的搭建步骤搭建顺序建议是先放主控最小系统再逐个挂外设每挂一个就测一次不要一次性全连完再调那样出问题你根本不知道是哪一步的错。第一步加载STM32F103C8的模型把时钟和电源接好。仿真软件里晶振和复位可以省略但电源和地一定要接。第二步挂OLED先跑一个最简单的Hello World显示确认I2C时序没问题。第三步挂DHT11的模拟模型设置初始温湿度看主程序能不能读出正确值。第四步挂BH1750和粉尘传感器模型这里粉尘用的是模拟电压源加脉冲响应需要把采样时序在仿真里也模拟出来。仿真里最麻烦的是时序模拟。真实DHT11的微秒级延时仿真软件跑起来时钟频率不一样可能会有偏差。我的经验是把仿真时钟调慢一点或者把延时参数按比例放大先验证逻辑正确性时序精度的最终确认还是要在实物上做。仿真阶段挂载模块验证目标常见失败现象第一阶段主控电源能下载能跑空程序无时钟、无响应第二阶段OLED能显示字符花屏、全亮、无显示第三阶段DHT11能读温湿度读数全0或全1第四阶段BH1750粉尘能读光照浓度数值恒定不变第五阶段串口能输出数据包乱码、收不到4.3 仿真跑通之后怎么过渡到实物仿真跑通不代表实物就顺。我总结仿真和实物之间有三个典型差异必须提前知道。第一个差异是电源噪声。仿真里电源是理想3.3V实物上有纹波、有压降。凡是仿真里正常、实物里复位或者ADC跳动的先查电源。用示波器看3.3V的纹波超过100mV就要处理。第二个差异是时序精度。仿真里延时函数按指令周期跑实物上受中断、编译优化影响实际延时可能差几十个微秒。DHT11这类对时序敏感的器件实物上要重新校准延时参数。我的办法是先在实物上用示波器量一下GPIO翻转的实际时间再修正循环次数。第三个差异是传感器个体差异。仿真里粉尘传感器的换算系数是理想的实物上每只传感器都要标定。我第一次拿实物测读数比仿真里偏高30%就是系数没标定导致的。提示过渡阶段最有效的方法是分模块替换。先只把OLED从仿真换成实物其它还留在仿真里确认没问题再换下一个。这样任何异常都能立刻定位到刚替换的那个模块。5. 常见问题与排查技巧实录5.1 传感器读数异常怎么查温湿度读数为零或者固定不变先去查上拉电阻。DHT11是开漏输出没有上拉电阻就永远是低电平读出来全是0。标准是用4.7kΩ上拉到3.3V不能用10kΩ太大了上升沿变慢时序会出错。光照值一直不变八成是I2C没通。用万用表量SCL和SDA在空闲时应该是高电平如果一直低就是被拉死了常见原因是传感器供电没接或者地址写错。BH1750的地址是0x23或者0x5C取决于ADDR脚接高还是接低接错就读不到。粉尘值乱跳回到上一章讲的脉冲时序。先确认LED驱动脚有没有在正确翻转用示波器看那根脚的波形正常应该是10毫秒周期、几百微秒宽度的脉冲。如果一直是高或者一直是低那就不是算法问题是引脚配置问题。现象可能原因排查动作温度恒为0上拉电阻缺失补4.7kΩ上拉光照不变I2C地址错核对ADDR脚接法粉尘大跳变未做本底扣除检查v_on-v_off数据全乱码波特率不匹配核对115200莫名复位电源跌落并大电容、查WiFi供电5.2 代码层面的高频坑第一个坑是Delay_us不准。前面说过别用SysTick做微秒延时。还有编译优化等级Keil里O0和O3下空循环延时差好几倍要么把延时函数放在固定的优化文件里要么用定时器实现。第二个坑是I2C卡死。软件I2C如果没做超时处理某次通信失败后一直等应答整个程序就卡住了。我的做法是每个等待加一个最大循环次数超了就返回错误让主循环继续跑。这个防御性编程习惯能救命。第三个坑是浮点运算。F103没有硬件浮点单元所有float运算都是软件模拟慢且占空间。显示和滤波里能不用浮点就不用温度可以用0.1℃为单位的整数存储需要显示时再转。这个优化能让程序跑得更顺。第四个坑是中断里做耗时操作。有同学把OLED刷新或者传感器读取放进定时器中断里结果中断执行时间过长其它中断被延迟系统时序就乱了。记住一个原则中断里只做标记和搬运重活留给主循环。5.3 实测经验与长期运行建议这套系统我在阅览室连续挂了一个学期积累了几条书上不会写的经验。外壳一定要开散热孔。我第一版用密封塑料盒装夏天盒内温度比环境高了五六度测出来的温度完全失真。后来在前后面板各开了几排小孔读数立刻对齐了。传感器本身也会轻微发热探头不能紧贴主控芯片。长期运行要加看门狗。STM32自带独立看门狗我配了4秒超时主循环里定时喂狗。有一次因为静电干扰程序跑飞看门狗把它拉回来了数据只丢了十几秒没人察觉。如果没这个机制可能就得手动去重启。数据记录建议存到SD卡或者定时上传别只放内存里。RAM掉电就没了攒一周的数据一次断电全丢。我在上位机脚本里加了每分钟落盘一次配合CSV追加写即使电脑断电最多丢一分钟的数据。最后分享一个校准小技巧。温湿度传感器久了会有漂移每隔几个月拿一个靠谱的参考仪表放在旁边两个读数对比如果偏差超过阈值就在代码里加一个补偿常量。这个常量写成宏定义方便以后调整。光照和粉尘同理定期用标准环境对比一次心里就有底了。这套图书馆环境监测系统从选型到跑通我的体会是真正花时间的从来不是写代码而是搞清楚每个数据背后的物理含义、把硬件时序抠准、以及处理真实环境里的各种意外。代码和原理图都是死的把为什么这么做想明白你换成任何场景都能重新搭一套出来。
返回列表