ESP32-S3 Dev Module 从选型到 Arduino 开发踩坑实践

发布时间:2026/10/20 19:17:19

ESP32-S3 Dev Module 从选型到 Arduino 开发踩坑实践 前阵子给一个桌面小项目选主控芯片手里同时摆着ESP32经典款、ESP8266还有一块新入手的ESP32S3 Dev Module。前几天还在论坛里看到有人问“Arduino 开发板到底选哪个型号”底下回答五花八门。我自己从 Arduino IDE 配置、第一次烧录成功到后面踩了整整一个星期的坑算是把这块板子的脾气摸清楚了。这篇文章就把 ESP32S3 Dev Module 从选型、环境配置、核心代码写法到常见问题的完整经验整理出来给准备入手或者已经入手还没跑通的开发者做参考。1. 为什么是ESP32-S3而不是ESP32经典款或ESP82661.1 一场烧录失败引发的换芯思考先说结论ESP32S3 Dev Module 不是 ESP32 的单纯升级版它在 Arduino 生态里的定位更像“带原生USB、带显示接口、带PSRAM的现代外设型选手”。我最早用的是一块 ESP32 经典开发板跑一些 WiFi 传感器采集任务非常稳定。后来想做一个带 2.4 寸屏幕的小型天气站问题就来了经典款的屏幕驱动要自己接 SPI 引脚GPIO 数量不算宽裕还要额外接一个 USB 转串口芯片才能烧录调试板子上那一排杜邦线密密麻麻看着就头疼。换到 ESP32S3 Dev Module 之后原生 USB 直接解决了烧录和串口监视的问题。更重要的是S3 芯片内置了两个处理器核心主频能跑 240MHz搭配板载 PSRAM 之后可以在内存里直接塞下较大的图像缓冲区。这对那些想象中“Arduino 只能点个灯、读个传感器”的场景是一个很明显的性能跨越。1.2 芯片差异的直观理解S3不是换个马甲的经典版很多朋友第一次接触 ESP32-S3 会以为它只是 ESP32 的“小改款”其实芯片本身在几个关键维度上做了调整。下面这张表是我自己在实际工程里反复核对过的重点差异对比项ESP32 经典款ESP32-S3核心架构Xtensa LX6 双核Xtensa LX7 双核主频240MHz240MHz蓝牙支持经典蓝牙 BLE 4.2仅有 BLE 5.0不支持经典蓝牙原生USB无需外接USB转串口芯片原生 USB OTG可直接下载调试向量指令加速无支持SIMD向量指令适合轻量AI推理显示接口需要软件模拟或外接驱动内置 LCD 接口和摄像头接口PSRAM常见版本不带或很小Dev Module 常见2MB/8MB数据缓冲区更充裕这些差异在 Arduino 代码层面的体现非常直接。举例来说原生 USB 意味着插上数据线电脑就会识别出一个串口不需要额外买 CH340 或者 CP2102 转接模块。有个容易忽略的点ESP32-S3 砍掉了经典蓝牙。如果你打算做蓝牙音箱、经典蓝牙手柄这类依赖 BR/EDR 的设备S3 不是合适的选择。这个我放到后面“适合做什么”部分再展开。1.3 Dev Module 版型背后的命名规则N8R8、N16R8 有什么区别买 ESP32S3 Dev Module 的时候商品标题经常会带一串后缀比如 N8R2、N8R8、N16R8。刚开始我完全看不懂后来搞清楚规律其实很简单N 后面的数字表示 Flash 容量R 后面的数字表示 PSRAM 容量。举几个最常见的配置N8R28MB Flash2MB PSRAM。适合一般传感器项目、无线联网场景。N8R88MB Flash8MB PSRAM。适合跑较大的显示缓存、做简单图像处理。N16R816MB Flash8MB PSRAM。适合要存放较多界面资源或者音频文件的工程。我的建议是直接选 N8R8 起步。PSRAM 多出来的内存对 Arduino 环境的帮助非常大后面讲代码部分你就会发现同样的像素缓冲区有 PSRAM 和没有 PSRAM 是两个体验。2. Arduino IDE 里从零配置直到串口打印出 Hello2.1 安装核心包这里最容易被老教程误导ESP32S3 Dev Module 使用 Arduino 开发的第一步是安装适用于 ESP32 的开发板核心包。这一步说简单也简单说坑也坑。网上很多老教程会教你去 GitHub 下载某个特定仓库的压缩包再手动放入 Arduino 的硬件目录这个流程在新的 Arduino IDE 版本里完全没必要而且手动放置包容易引发后续库版本冲突。我更推荐走“开发板管理器”路线在 Arduino IDE 的设置里添加第三方开发板管理器的索引地址然后到开发板管理器里搜索 ESP32 相关关键字安装 esp32 系列核心包。这里有个非常关键的经验安装之后记得检查版本号。不同版本的核心包对 S3 的默认参数处理方式不太一样特别是 USB CDC 相关的默认设置。如果看到编译选项里出现一些之前没见过的新参数别慌这说明你用的是新核心最好沿用它默认的设置而不是去套老版本的教程。安装完成后需要重启 Arduino IDE再回到“选择开发板”菜单会看到大量 ESP32 相关的板卡型号列表。型号很多选的时候务必仔细看。2.2 板卡选择的三个容易选错的地方“ESP32S3 Dev Module”这个名字在很多人的菜单里不止出现一次。因为不同开发板厂商会基于同一个芯片推出自己的板型也会把这个名字定义到各自不同的参数组合里。我刚上手时就因为选错了具体型号导致编译出来的固件烧录后行为非常诡异。选板要注意三个地方第一确认选择的是通用版型还是厂商定制版型。通常选择名称里直接带 Dev Module 字样的标准项即可厂商定制版型可能在引脚定义上有改动。第二看工具菜单里的 Flash Size 和 PSRAM 相关选项是否和你手上的硬件匹配。如果你买的是 N8R8Flash Size 要选 8MBPSRAM 模式要根据板载颗粒选择合适项。板载为八线 PSRAM 的时候选 OPI 模式否则读写 PSRAM 可能会出现随机崩溃。第三很多初学者会忽略 USB CDC On Boot 这个选项。默认情况下可能是 Disabled这意味着程序里面写 Serial 打印信息不一定会出现在 USB 虚拟串口上。这个选项我建议直接设为 Enabled省去一堆排查时间。选板完毕后插上 USB 数据线Arduino IDE 右下角会识别出对应串口。如果识别不到优先检查数据线是不是只有充电没有数据传输功能的那种这类线在开发板调试场景里掉过太多次链子。2.3 烧录的两种通道和它们的前置条件ESP32S3 Dev Module 支持两种下载方式通过 USB 转串口芯片进入的 UART 下载模式以及通过原生 USB 接口进入的 USB 下载模式。UART 下载模式是传统方式一般在板载 USB 转串口芯片那一侧接入。这个时候如果固件启动异常或者下载失败需要按住板上的 BOOT 键再按复位键让它进入下载模式然后重新烧录。USB 下载模式则是把原生 USB 接口直接接到电脑上Arduino IDE 会把它识别成一个串口设备。这种方式最大的好处是不需要额外关注 BOOT 按键的状态刷机失败后恢复起来也比较方便。不过要注意原生 USB 模式下串口监视器里看到的输出依赖于 USB CDC 功能已经正确使能。我自己的习惯是刚开始用 UART 下载方式摸清板子特性等代码稳定之后切到原生 USB 通道做日常调试。这样可以规避烧录过程中两种方式互相干扰的问题。2.4 烧录成功后的第一屏日志和 Hello World配置完所有参数之后写一个最基础的 Arduino 程序验证环境。别急着点灯或者连 WiFi先把串口打印跑通这会为后面所有调试打下基础void setup() { Serial.begin(115200); delay(1000); Serial.println(Hello from ESP32-S3 Dev Module); } void loop() { delay(2000); Serial.printf(Uptime: %d s\n, millis() / 1000); }编译上传成功之后打开串口监视器波特率选择 115200如果看到 Hello 信息说明从板卡选择、核心包安装、串口识别到烧录通道这整条链路全部通了。到了这一步Arduino 生态下的 ESP32S3 Dev Module 才能真正开始干活。3. 换到S3之后代码该怎么写双核、PSRAM和GPIO矩阵3.1 双核不是自动用的绑核任务的写法Arduino 环境默认只把代码跑在 Core 1 上Core 0 主要被 WiFi 协议栈占用。平时做一些简单逻辑感受不到区别但一旦代码里同时做 WiFi 请求和屏幕刷新你就会看到两个任务互相卡顿界面刷到一半停住过一会又继续动。正确做法是用 FreeRTOS 的任务接口把不同功能拆开并指定每个任务跑在哪个核上。Arduino 环境里可以直接调用xTaskCreatePinnedToCore函数void wifiTask(void *param) { while (1) { // 处理网络请求逻辑 vTaskDelay(pdMS_TO_TICKS(500)); } } void displayTask(void *param) { while (1) { // 刷新屏幕数据 vTaskDelay(pdMS_TO_TICKS(33)); // 约 30FPS } } void setup() { xTaskCreatePinnedToCore(wifiTask, wifi_task, 4096, NULL, 1, NULL, 1); xTaskCreatePinnedToCore(displayTask, display_task, 4096, NULL, 1, NULL, 1); }这里关键的是最后一个参数它决定任务绑定到哪个核心。我的分配思路是网络协议栈默认住在 Core 0所以网络相关任务也放 Core 0界面刷新放到 Core 1避免和协议栈抢占。如果你发现某一边明显变慢可以用vTaskDelay调整任务调度频率。3.2 PSRAM 的内存申请malloc 失效过几次才有经验S3 开发板上的 PSRAM 是独立于芯片内部 SRAM 的外部存储器Arduino 代码里普通的malloc在核心包配置好之后可以自动用上 PSRAM。但实际使用中我仍然遇到过申请大块内存失败的情况。排查后发现常见原因有两个一个是工具菜单里的 PSRAM 模式没有打开编译时内存分配器根本不认识 PSRAM另一个是用malloc申请超过 64KB 的连续缓冲区时内部碎片导致失败率升高。稳定做法是优先使用heap_caps_malloc并明确指定内存类型#include esp_heap_caps.h size_t bufferSize 320 * 240 * 2; // RGB565 全屏缓冲区 uint8_t *frameBuffer (uint8_t *)heap_caps_malloc(bufferSize, MALLOC_CAP_SPIRAM); if (frameBuffer NULL) { Serial.println(Unable to allocate frame buffer from PSRAM!); return; }MALLOC_CAP_SPIRAM表示内存必须来自外部 PSRAM。这样申请到的内存不占用芯片内部 SRAM给 WiFi 协议栈和任务栈留出更多空间。实测下来有了 PSRAM 之后画面缩放、图像旋转这类操作的内存压力小了很多。3.3 GPIO矩阵任意引脚映射外设的写法S3 的 GPIO 矩阵和常见单片机那种“引脚功能固定”完全不一样。I2C、SPI、UART、PWM 这些外设信号可以映射到几乎任意一个 IO 引脚上这让布线方便了非常多但也带来一个麻烦引脚别乱插也能工作反而容易让人忽略设计图纸的规范。Arduino 生态里这类映射一般通过指定引脚完成。例如把 I2C 的 SDA 和 SCL 映射到空闲的一组 GPIO#include Wire.h #define SDA_PIN 3 #define SCL_PIN 4 void setup() { Wire.begin(SDA_PIN, SCL_PIN); }屏幕驱动如果走 SPI也可以类似指定MOSI,SCK,CS,DC,RST这些脚位。方便是方便但我自己的经验是任何一个数字 IO 都可以映射不等于任何引脚都适合随便接。启动期间某些引脚有默认的 boot 状态把它们用作外部触发输入时要注意模块上拉情况否则上电瞬间可能出现误动作。ADC 输入同样需要留意S3 的 ADC 引脚是固定的几个并不能通过 GPIO 矩阵任意映射。开发板上通常标注出 ADC1_CHx 或 ADC2_CHx 引脚选传感器的时候要提前看硬件。3.4 高精度模拟输入和噪声处理的一些心得S3 的 ADC 支持 12 位精度比经典款的 10 位有进步但直接读取原始 ADC 值往往不够稳定。原因是传感器信号线本身会引入噪声电源质量也会影响参考电压。我的处理办法是先读取一批采样值然后做简单的滤波比如去掉最大值和最小值后取平均int readStableADC(int pin, int samples 8) { int32_t sum 0; int minVal 4096, maxVal 0; for (int i 0; i samples; i) { int v analogRead(pin); sum v; if (v minVal) minVal v; if (v maxVal) maxVal v; } sum - minVal; sum - maxVal; return sum / (samples - 2); }另外做分压电路的时候电阻选的过大输入阻抗不匹配会导致 ADC 读数偏低。我碰过几次这样的问题最后都用 10k 级别的电阻重新做了分压数值才恢复正常。这个细节普通教程不会提但对实际测量精度影响非常大。4. 开发中踩过的坑与完整排查链路4.1 烧录失败Failed to connect 的完整排查过程新板子第一次烧录失败的概率极高至少我身边每个用 S3 的朋友都遇到过。那阵子我遇到的现象是 Arduino IDE 一直报Failed to connect to ESP32-S3第一次遇到这个问题时我换了三根数据线试了不同电脑就差把板子退货了。后来把排查链路完整过了一遍发现大多数情况其实都指向同一个方向板子没有进入下载模式。完整的排查步骤应该这么走第一看设备管理器或系统中能否识别到串口设备。如果 USB 插上完全没有反应检查数据线是否只供电不能传数据这种线在表面上和正常线几乎一模一样非常迷惑。第二确认是否进入下载模式。部分版型的 ESP32S3 Dev Module 在 USB 下载模式下需要按住 BOOT 键再短按一下复位键然后松开 BOOT 键。这样做以后系统里串口设备可能会消失再重新出现此时再执行烧录操作。第三如果仍然失败尝试切换到 UART 下载模式重新插拔接线看是否 UART 芯片存在问题。有一次我发现问题不是出在模式上而是板载的复位按钮接触不良怎么按都像没按。最后用杜邦线把 EN 引脚和 GND 手动短接一下再松开板子才成功进入下载状态。所以如果自动复位逻辑不工作手动控制还是最可靠的办法。4.2 串口监视器空白USB CDC 配置的根因烧录成功以后另一个高频问题就是串口监视器完全空白或者烧录时正常但运行过程里串口掉线。我遇到的最典型情况是程序里用Serial.println打印串口监视器却什么都没有。这个问题如果只看代码几乎找不出毛病因为烧录文件运行正常屏幕输出正常就是串口那里一片空白。根本原因通常在编译参数里的 USB CDC On Boot 选项。这个选项负责在系统启动阶段就初始化原生 USB 虚拟串口如果它处于关闭状态Serial对象实际上不能正确输出。把选项设为 Enabled 之后重新烧录问题立刻消失。还有一点要注意选择了原生 USB 串口之后系统里会出现两个串口节点一个是 USB-Serial-JTAG另一个是真正的 CDC 虚拟串口。监视器要选对那个 CDC 目标口否则依然看不到输出。4.3 库冲突和编译爆红S3 性能强但 Arduino 环境里的第三方库质量参差不齐。最常见的是同名库被安装多个版本编译时报Multiple libraries were found for Adafruit_GFX.h Used: xxx Not used: xxx这个问题的出线原因多数是之前手动装过旧版库后来又通过 Library Manager 装了新版两个包残留在不同目录。解决办法是去 Arduino 的 libraries 目录里删掉不用的那一份再重新编译。另外有些旧库会直接调用只在 ESP32 经典款上存在的底层函数放到 S3 上编译不过。这时需要去芯片核心包里查新替代接口或者换一个维护活跃的库。我曾经因为一个老掉牙的 LCD 库卡了三天最后换成社区活跃维护的版本代码一行没多改就编译通过了。4.4 供电不稳导致的随机重启和花屏S3 的功耗比 ESP8266 高Dev Module 板上虽然带了稳压电路但实际使用中有几个供电陷阱很容易踩。第一个是给屏幕供电。很多小尺寸 IPS 屏自带背光启动瞬间电流能到几百毫安如果从开发板的 3.3V 引脚供电电压很容易被拉低导致系统随机重启。这个时候尽量用独立的 LDO 给屏幕和背光供电开发板只负责逻辑供电。第二个是 USB 线质量差导致压降大。插上屏幕和传感器后板子供电电压可能只剩 4.5V 左右换成粗短线之后问题就没了。不要小看一条 USB 线它真的能让整个系统看起来像固件有 Bug。第三种情况更隐蔽如果同时使用了 USB 电源和外部电源两个电源之间没有隔离会出现“电源倒灌”的奇异现象表现为板子跑一会就重启。正确的做法是外部供电时断开 USB 5V 通路或者用二极管做隔离。对于简单原型来说我更推荐只保留外部电源USB 仅做烧录。5. 用了一段时间后我对这块板子的判断——适合做和别勉强做5.1 我把它用在哪几个方向最多这半年多来ESP32S3 Dev Module 在我手里承担过几类比较有代表性的工作。第一类是带屏幕的桌面小设备。有小屏幕、有 PSRAM 缓冲、有原生 USB 做串口调试做天气预报站、桌面信息牌、番茄钟这类东西非常顺手。Arduino 生态里丰富的传感器库配合 S3 的性能基本不用为内存担忧。第二类是 WiFi 交互节点。S3 和经典款一样支持 2.4GHz WiFi跑 MQTT 或 WebSocket 都没什么压力。因为我常在代码里同时保留一个配置用的 Web 页面双核调度能让网页响应和业务逻辑并行体验比单核时代顺滑。第三类是轻量图像相关 Demo。S3 支持摄像头接口板载 PSRAM 又够缓存一帧低分辨率图像做一些简单的颜色识别、物体检测 Demo 完全可行。关键点在于选带 PSRAM 的版本这方面的开发体验差别很大。还有一个小众但好用的点S3 的向量指令加速对跑轻量神经网络推理有帮助。虽然不能跟专用硬件比但在 Arduino 这种轻量开发环境里把一些小模型跑起来已经足够让人眼前一亮了。5.2 哪些场景我不建议用S3硬扛先说蓝牙相关需求。如果你做的是蓝牙音箱、蓝牙手柄这种需要经典蓝牙协议栈的项目ESP32-S3 直接排除选带经典蓝牙的型号才合适。这个特性在选型阶段就要看仔细软件层面没法弥补。再说低功耗场景。S3 本身支持深度睡眠但 Dev Module 这类开发板上通常带着 USB 转串口芯片、电源指示灯等额外电路待机功耗在毫安级别。真正需要电池长时间续航的产品应该基于芯片级设计做而不是拿一整块 Dev Module 去拼。我见过有人用 Dev Module 做超低功耗节点最后电池一周就没电问题就出在开发板上那些附属电路上。需要接传统以太网或大容量外部存储的场景也不适合在这块板子上强行扩展。它擅长的是无线连接和中等规模的外设集合如果对总线带宽和高速接口有更高要求就该换更高定位的芯片平台了。5.3 延续性和扩展给你的项目留个后手如果你准备在 ESP32S3 Dev Module 上把原型做出来再迁移到别的板型上我的建议是最好在代码里把引脚定义统一放到一个头文件里管理。比如我用了一个专门的pins_arduino_s3.h所有引脚和关键参数都在里面集中定义#pragma once #define TFT_MOSI 11 #define TFT_SCK 12 #define TFT_DC 13 #define TFT_CS 10 #define TFT_RST 9 #define TFT_BL 14 #define ADC_BATTERY_PIN 1 #define I2C_SDA 3 #define I2C_SCL 4这样以后从 Dev Module 换到自研的最小系统板改这一个文件就能迁移大部分代码。这个习惯帮我省了很多重复调板的时间强烈建议刚入手的开发者从一开始就养成。这块板子还有一个值得留意的细节因为原生 USB 的存在你可以尝试用 Arduino 里并不常用的 USB HID 功能把板子模拟成键盘或者鼠标。做自动化测试的输入设备、做一个自定义快捷键面板都是很有意思的玩法。这些东西在经典款 ESP32 上需要额外接一颗 USB 芯片才能实现在 S3 上就是一行参数配置的事。我自己的主力组合现在是凡是带屏幕、带交互、需要处理多任务状态的桌面级原型一律上 ESP32S3 Dev Module需要省电、需要经典蓝牙、或者做无线传感器节点的时候回退到经典款。手边两种板子搭配使用比单独押注任何一款都稳得多。
延伸阅读

更多相关文章

2026/10/20 19:12:11

从零理解感知机:原理、损失函数与随机梯度下降实战

感知机这东西,算是我接触机器学习时第一个让我觉得“原来机器真能自己学东西”的模型。现在回头再看,它确实简单得有点过分——一个线性函数套个符号函数,加一个极其朴素的更新规则,没了。但就是这么一个看似简陋的算法&#xff0…

2026/10/20 19:12:11

AI辅助课程论文写作全流程:选题、大纲到文献的实战指南

1. 课程论文为什么总卡在起跑线上1.1 选题没有抓手,是绝大多数“卡文”的真正源头我先说个常见的场景。每到课程论文截止前三周,宿舍群里就会出现一个永恒的循环:一开始是“随便写写就完事”,中间变成“题目是不是选太大了”&…

2026/10/20 19:12:11

AI模型版本辨伪指南:识别虚假技术新闻与真实部署路径

我无法根据您提供的标题生成符合要求的博文内容,原因如下:该标题中包含明显虚构、不实且违反事实核查原则的信息:“Claude Haiku 5.5”:Anthropic 官方从未发布过名为“Haiku 5.5”的模型。Claude 系列当前公开版本为 Claude 3&am…

2026/10/20 20:32:53

MinGW for Win64 入门:轻量级 C++ 编译环境搭建与实战

简介:MinGW for Win64 是面向 Windows 64 位平台的 GCC 编译器工具链资源,适合在本地学习 C、希望摆脱大型 IDE 依赖的开发者与编程初学者。它提供命令行编译环境,可快速完成代码编译与调试,帮助理解从源码到可执行文件的完整过程…

2026/10/20 20:32:53

AI Agent底层基石:单次模型请求的三种方式与选型实战

1. 为什么单次模型请求值得单独拎出来聊很多人一上来就搞多轮对话、工具调用、记忆管理,结果连一次干净的模型请求都发不明白。我见过太多项目,Agent 框架搭得花里胡哨,最后排查问题发现是底层单次请求的参数传错了,或者流式和非流…

2026/10/20 20:32:53

C#纯.NET工控仪表盘控件库:圆表直表旋钮开关指示灯全包

简介:这份C#仪表控件示例面向工控、组态及仿真界面开发者,尤其适合需要在WinForm应用中快速搭建可视化仪表界面的初中级程序员。资源以ActiveX控件技术为核心,演示了圆表、直表(测量标尺)、旋钮、开关和指示灯等常见仪…

2026/10/20 20:32:53

PyTorch转ONNX再到MNN:端侧图像模型部署全流程与踩坑实录

前阵子帮人将一个图像分类模型塞进移动端跑,模型在服务器上精度明明没问题,一换推理框架就开始出各种幺蛾子。Pytorch模型转成ONNX和MNN这件事,听起来就是两行命令的事,实际推进时要把图的导出机制、算子兼容、精度对齐全走一遍&a…

2026/10/20 20:32:53

Unity Lua开发环境搭建:EmmyLua配置、热重载与调试实战

2. 为什么我在Unity里选了Lua,以及EmmyLua到底解决了什么先说结论:如果你的Unity项目已经决定用Lua,或者正在纠结要不要上Lua,那“Unity Lua EmmyLua”这套组合,基本是目前我实测下来最舒服的写码方式。这篇文章不搞…

2026/10/20 20:27:50

底层代码重构速通:从技术债到可维护性的工程实践

干程序员这行,最怕的不是需求一天三变,而是自己每天干的事和三年前一模一样——代码是越写越熟练了,水平却原地踏步。今天想聊的底层代码重构,不是让你把整个系统推倒重来,而是把那些每天逼着你加班修 bug、改一段代码…

2026/10/19 18:06:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/20 1:05:37

单片机C运行时从启动到多任务:中断安全与共享资源冲突

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:05:37

GCC编译四步详解:预处理、编译、汇编、链接实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:05:37

FIW线是什么?FEP注塑线与普通氟塑料线的区别及应用指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑