ESP8266_RTOS_SDK V3.3 IDF Style环境搭建与hello_world烧录实战
最近翻出一块吃灰的ESP-01S想把它接到本地MQTT服务上做几个简单的控制结果第一步就卡在了编译环境上。网上一搜大量资料教的还是ESP8266_RTOS_SDK老版本那套gen_misc.sh交互式配置跟原厂目前主推的V3.3 IDF Style完全不是一回事。不少教程用着旧的Flash配置思路和现在的分区表、bootloader结构也对不上照抄很容易一编译就是一堆错。这篇就是写给同样准备从零开始玩ESP8266_RTOS_SDK的人我会从选型讲起说清楚V3.3 IDF Style和老版本到底差在哪然后完整走一遍Ubuntu下的工具链、源码拉取、环境变量、hello_world编译烧录全流程最后把我实际踩过的坑逐个拆开。内容不绕弯子照着做基本能出结果。1. 老芯片的新生态ESP8266_RTOS_SDK V3.3该不该换1.1 两条SDK路线先分清ESP8266的官方SDK一直有两条线NONOS SDK和RTOS SDK。NONOS虽然名字叫“非操作系统”但实际也有个简化版的任务调度适合做透传、单任务小逻辑优点是内存占用小、启动快、教程多。RTOS SDK则是基于FreeRTOS的完整开发框架带网络协议栈、多任务调度、组件管理适合业务逻辑稍微复杂的场景比如同时跑Wi-Fi连接、MQTT、OLED显示、按键扫描——这些事情摊在NONOS里全靠你自己维护状态机写起来非常痛苦。我手头这个ESP-01S要同时处理本地按钮、继电器反馈和MQTT订阅用NONOS写不是不行但代码会越堆越乱。RTOS SDK里每个模块一个task消息队列一接结构清楚得多。所以我的选择很明确直接用RTOS SDK。至于版本千万不要再去下载V2.x时代的包了V2.x那套交互式脚本用来用去还是那几步组件结构不透明第三方库要手动往工程里塞稍微升级一点就各种不兼容。V3.3之后整个工程组织方式向ESP-IDF靠拢维护体验好了不止一个量级。1.2 V3.3 IDF Style到底改了什么先给个结论ESP8266_RTOS_SDK的V3.3版本不是简单的增量更新它把整个工程的构建思路重做了一遍官方管这个叫IDF Style。所谓IDF Style并不是说ESP8266能用上ESP32那套纯CMake的idf.py工具链而是指它引入了类似ESP-IDF的组件目录结构、依赖解析方式和menuconfig配置机制。底层构建仍然基于GNU Make但你看工程的方式已经完全变了。这个差异对开发的影响是实打实的。我用一个表把V2.x老式做法和V3.3 IDF Style做个对照对比项V2.x老做法V3.3 IDF Style配置方式gen_misc.sh交互式问答配置项一问一答make menuconfig可视化菜单工程结构官方SDK目录里改组件边界模糊类似IDF的main/components结构自带sdkconfig组件管理手动把第三方库拷进app目录官方仓库通过子模块管理组件依赖关系清晰Flash布局需要自己理解boot/partition/app的偏移make会自动处理bootloader、分区表和应用镜像烧录方式要手动算地址make flash一句搞定环境依赖Python2时代的脚本逻辑构建脚本切换到Python3体系这一改动对新手最友好的地方在于烧录。老版本里常见的问题是“我该把bin写到哪个地址”很多人对着0x00000和0x10000反复查资料。V3.3 IDF Style下编译产物、bootloader和分区表都是自动组织的你只要执行make flash脚本按分区表把该写的东西写到该写的位置。这一点在我实际体验里省了特别多时间。不过说句公道话IDF Style也引入了一个新门槛对子模块的管理更依赖网络拉取。V3.3仓库不再是单独一个压缩包就能跑干净官方把很多外部组件作为git子模块放到仓库里第一次拉取如果网络不稳定后面编译会各种碰壁。这个坑我放到第3章仔细说。2. Ubuntu下工具链准备依赖、PATH和Python的一个大坑2.1 系统依赖清单我的做法是在一台Ubuntu 22.04 LTS的干净虚拟机上操作。教程里用20.04也没问题关键是别用那种滚动更新的激进发行版否则系统库一变SDK里的构建脚本可能要打补丁没必要给自己找麻烦。Windows用户也别硬刚IDF Style虽然理论上支持Windows但串口权限、路径分隔符、子模块符号链接这些都会带来额外变量你第一课的目标是跑通编译链不是调试MSYS2环境。老老实实装个WSL或者虚拟机直接复用Linux流程。先把基础包装上sudo apt update sudo apt install -y build-essential git wget flex bison gperf \ python3 python3-pip python3-setuptools cmake libncurses-dev libffi-dev libssl-dev第一遍搭建时很多人只记得装gcc和git忘了libncurses-dev结果后面make menuconfig一启动就报找不到ncurses头文件。还有flex和bison这两个工具在SDK构建的配置解析阶段会被调用缺了会冒出一堆莫名其妙的语法错误。这些包看起来不起眼但别跳过。2.2 预编译工具链安装ESP8266用的是Tensilica Xtensa LX106架构跟PC上的x86完全不同所以必须用专门的交叉编译工具链。原厂提供了预编译好的xtensa-lx106-elf工具链直接下载解压就行千万不要自己拿crosstool-NG去编译那是一个能消耗一整天的无底洞。工具链解压位置建议放在~/esp下后面SDK也放在这里方便统一管理mkdir -p ~/esp tar -xzf xtensa-lx106-elf-linux64-*.tar.gz -C ~/esp export PATH$HOME/esp/xtensa-lx106-elf/bin:$PATH确认是否安装成功xtensa-lx106-elf-gcc -v能正常打印版本信息说明工具链已经就位。注意工具链目录里bin下的可执行文件很多你只需要把这一个bin目录加进PATH不需要往里再套一层。我见过有人把PATH指到xtensa-lx106-elf/bin/xtensa-lx106-elf/bin这种低级错误折腾了半个小时才定位到。2.3 Python环境的那个隐藏坑V3.3 IDF Style的构建脚本已经切到Python3体系但很多老教程还在让你装python2和pip2如果照着做后面做menuconfig的时候会经常出现“ModuleNotFoundError”一类的问题。我个人的建议是系统里如果没有特殊遗留需求直接统一用python3pip装包时加上--user不要用sudo去装。还有一个很隐蔽的问题部分构建脚本内部调用的是python而不是python3。Ubuntu 22.04里默认没有python这个符号链接如果你执行make时遇到/usr/bin/env: python: No such file or directory说明脚本在找python命令。这时候可以给当前用户做一个别名或者符号链接sudo ln -s /usr/bin/python3 /usr/bin/python这个坑在ESP8266_RTOS_SDK的make流程里比想象中常见尤其是那些从老版本迁移过来的脚本片段习惯了写python。提前处理掉比报错再查要舒服得多。3. 拉取V3.3源码分支、子模块和IDF_PATH3.1 源码拉取与分支切换源码直接去原厂代码仓库拿V3.3对应的分支名是release/v3.3。因为SDK里带子模块第一条clone命令就必须加--recursive否则后面还得补一次子模块初始化网络开销反而更大cd ~/esp git clone --recursive --branch release/v3.3 https://github.com/espressif/ESP8266_RTOS_SDK.git如果之前没有指定分支默认拉到了master或别的release切分支的时候要注意切换之后子模块的引用也会变化稳妥的做法是切完分支再执行一次子模块更新。这也是我要特别强调的分支和子模块状态必须绑定在一起只切分支不更新子模块编译时项目结构和SDK版本不匹配错误会出现在深层的头文件和链接阶段排起来非常难受。3.2 子模块缺失的三种表现与修复V3.3仓库把MQTT、JSON、wolfSSL这些第三方组件都作为子模块挂在components目录下。子模块没拉全编译时不会一开始就告诉你“子模块缺失”而是表现为下面三种情况之一一是编译刚开始各个组件的Makefile扫描阶段就报“No such file or directory”指向一个空目录二是某个头文件找不到比如你用了mqtt功能结果#include mqtt_client.h直接失败三是链接阶段出现一堆未定义的符号看起来像代码写错其实是整个组件源码根本不存在。修复命令其实就那么几条cd ~/esp/ESP8266_RTOS_SDK git submodule sync git submodule update --init --recursivegit submodule sync很多人会漏掉它会把子模块的远程仓库URL同步成当前项目记录的值特别是你改过clone地址或者网络环境之后这一条能让后续update少很多麻烦。子模块数量不少第一次拉取耗时较长中间断网也是常事不用慌把上面两条命令多跑几遍就行git会断点续拉。3.3 环境变量IDF_PATH和requirements.txt代码就位后把环境变量写进shell配置免得每次开终端都要手动exportecho export IDF_PATH$HOME/esp/ESP8266_RTOS_SDK ~/.bashrc echo export PATH$HOME/esp/xtensa-lx106-elf/bin:$PATH ~/.bashrc source ~/.bashrc然后初始化Python依赖。SDK仓库里带了requirements.txt里面主要是配置菜单生成、串口烧录时需要的那几个Python库。直接装python3 -m pip install --user -r $IDF_PATH/requirements.txt这里用--user的原因是不污染系统Python环境避免和系统包冲突。装完之后你不需要额外安装任何IDE插件也不需要配置什么复杂的项目文件编译命令直接基于Makefile跑就行。到这一步环境层面已经齐了。4. 从hello_world开始menuconfig、编译和烧录4.1 复制工程而不是原地改SDK自带的示例工程在examples目录下第一个练手项目就是get-started/hello_world。我强烈建议把示例目录原样复制一份出来在副本上做修改cd ~/esp cp -r ESP8266_RTOS_SDK/examples/get-started/hello_world my_hello cd my_hello这么做的理由有两个一是SDK更新时你git pull后不会被自己改过的示例文件挡住合并二是后面升级工程版本时diff起来只看自己的代码不会被一堆无关的示例改动干扰。这个习惯在ESP32的IDF开发里同样适用属于基础修养。4.2 menuconfig里的关键配置编译前先执行make menuconfig这个命令会读取sdkconfig文件并弹出一个终端配置界面。第一次编译前sdkconfig还不存在menuconfig会基于默认配置生成。界面里需要关注的几项Serial flasher config下的Default serial port要改成你实际的串口设备。Linux下一般是/dev/ttyUSB0或/dev/ttyACM0取决于USB转串口芯片类型。Flash size大多数ESP-01S模组是1MB我自己用的ESP-12F是4MB。这个值必须跟板子实际容量一致写大了会出分区越界写小了浪费空间。拿不准就看模组丝印或者查芯片型号不要靠猜。Flash frequency和CPU frequency早期模组CPU频率跑80MHz比较稳新模组跑160MHz也没问题。如果你不确定保持默认就好跑不起来再降低频率排查。Flash mode里的QIO、DIO这些选项对应的是SPI Flash的传输模式。大多数模组用DIO兼容性最好QIO理论上速度快一点但个别Flash颗粒在QIO模式下不稳定。强行追快不如求稳我一般选DIO。改完选择Save生成sdkconfig。之后每次改代码再编译menuconfig里的配置都会保留不用重复设置。注意这个sdkconfig文件是生成物不要提交到git里每个人的板子Flash大小可能不同别人拉下来覆盖了反而麻烦。4.3 编译、烧录和串口监控配置保存后直接编译make -j4-j4表示并行编译能显著加快速度。第一次编译SDK会把所有组件都构建一遍日志会刷很长看到生成build/hello_world.bin之类的产物并且没有报错整个工具链就算打通了。烧录命令make flash ESPPORT/dev/ttyUSB0这里要特别说一下ESP8266 RTOS SDK的Flash布局bootloader在0x00000分区表在0x08000附近应用程序镜像从0x10000开始写。老版本SDK里这三个地址的逻辑经常被人搞混IDF Style下make flash会按照sdkconfig和分区表自动计算写入位置你不需要手动指定。这个自动化的价值用过老流程的人都懂。烧录重启之后可以用串口监控看输出make monitor ESPPORT/dev/ttyUSB0正常情况下串口会不停打印系统启动日志最终看到“Hello world!”之类的输出就说明你的第一块ESP8266板子已经能跑RTOS SDK了。5. 实测中踩过的坑工具链、串口与子模块5.1 工具链相关的两个高发错误第一个是明明装了工具链make时还报xtensa-lx106-elf-gcc: command not found。原因几乎都是PATH没生效我犯过的错是改了~/.bashrc后没source新终端里又没重新登录。自查方法很简单报错的那个终端里直接敲下xtensa-lx106-elf-gcc -v如果命令找不到说明PATH根本没配好不是SDK的问题。第二个错误是编译过程中突然出现一串“fatal error: stdio.h: No such file or directory”。这个多半不是真的缺stdio.h而是工具链的头文件搜索路径没找对常见于工具链解压目录被移动过或者PATH里拼了多余路径。最简单的处理是删掉重新解压把工具链固定在~/esp下不要挪走。5.2 串口权限和下载模式Linux下第一次接USB转串口经常报“could not open port /dev/ttyUSB0: Permission denied”。这是当前用户不在dialout组导致的sudo usermod -aG dialout $USER执行完注销重新登录一次。这个组名在不同发行版上可能略有差异但Ubuntu系基本就是dialout不要在权限问题上硬杠直接加组就行。还有一类烧录失败表现为写入时一直卡在“Connecting...”多数情况下是板子没进下载模式。很多ESP8266开发板是冷启动自动进入下载模式的但也有板子需要按住IO0对应的Flash按键再按一下复位键才能进入烧录状态。如果你的板子没有自动下载电路老老实实按一下再试。另外波特率设置太高也可能导致连接失败menuconfig里把烧录波特率从921600降到115200成功率会明显提升。5.3 子模块与网络问题的处理节奏我做第二遍环境搭建时为了模拟全新环境故意先不拉子模块结果编译hello_world这种最基础工程也崩了。V3.3 IDF Style对子模块的依赖比我想象的要重不是只有MQTT才需要基础硬件驱动组件也走同一套机制。处理外来子模块问题有个比较高效的口诀先sync再update断了就重来。中间如果某个子模块一直拉不下来先刷新整个仓库的引用状态git submodule foreach git fetch git submodule update --recursive这样能定位是哪个子模块的锅然后再单独处理那一个。千万不要自己手动去网上下载压缩包丢进components目录手动放置会造成git状态不一致后面的git操作、版本检查都会变得异常混乱。5.4 编译输出里那些值得留意的关键词第一次make的时候很多人会被大量日志淹没建议养成过滤关键信息的习惯。看到“CC”“AR”“LD”都是正常编译过程看到“warning: unused variable”可以先不管最需要关注的是“error:”以及链接阶段的“undefined reference to”。另外因为并行编译用了-j4报错信息和具体文件的关系可能不是按顺序打印的真报错时建议先重新只跑一次不带-j4的单线程make错误顺序会清楚很多。这个技巧救过我很多次特别是自己加了一些组件之后第一次编译报错的时候。6. 从第一块板子到能稳定干活几个经验总结这套环境搭完不等于万事大吉后面真正开始写业务的时候还会遇到不少问题。我自己的经验是先别急着在工程里堆功能给板子做一个“最小可用系统”的验证Wi-Fi连接、一个GPIO点灯、串口日志打印这三样跑通之后再考虑MQTT、EEPROM、云平台这些更重的模块。建议把SDK版本和工具链版本记录在项目的README里。ESP8266_RTOS_SDK后续还有维护版本工具链也可能跟着更新你换机器或者换人接手时版本一致性能少很多莫名其妙的兼容问题。我因为没记版本隔了几个月重新搭环境SDK和小工具链版本对不上折腾了半个晚上才搞明白这个教训相当实在。另外如果准备长期开发哪些本地改动是临时的、哪些需要回馈到自己的代码仓库一开始就要想清楚。我之前图省事直接在examples里改代码后来SDK一升级git checkout直接把我改的东西全覆盖了那批代码还没进自己的git仓库只能凭着肌肉记忆重写了一遍。从第一天开始就复制工程到独立目录管理后面能省掉很多这种风险。最后想说的是ESP8266确实老了单核、160MHz、几十KB内存跟现在动辄双核几百兆的芯片没法比。但正因为它老出问题的姿势基本都被人踩过了资料虽旧但密度高拿来做嵌入式入门、做智能家居小项目性价比和折腾感都刚刚好。V3.3 IDF Style这套环境算是我用过的ESP8266方案里最接近现代嵌入式开发流程的一套值得花一个晚上把它跑通。

相关新闻

基于圆阵MUSIC的声源定位:从麦克风到方位角的完整实现

基于圆阵MUSIC的声源定位:从麦克风到方位角的完整实现

简介:基于单层圆形麦克风阵列的声源定位项目,提供可运行的Python源码、实验音频与项目说明,代码已经过测试,适合计算机、电子信息、物联网等专业学生用于毕业设计、课程设计或初期项目立项演示。整个压缩包共68个文件,…

2026/10/13 18:47:29 阅读更多 →
基于Bright Data MCP与实时抓取的RAG应用防幻觉方案

基于Bright Data MCP与实时抓取的RAG应用防幻觉方案

1. 为什么你的RAG应用总在“张口就错”做过RAG应用的人大概都经历过这种尴尬:用户问了一个明明很具体的问题,模型回答得头头是道,语气笃定、结构工整,但内容全是编的。更让人头疼的是,你翻遍知识库也找不到它引用的那些…

2026/10/12 18:21:27 阅读更多 →
OpenCV轮廓提取实战:从预处理到形状匹配的完整链路

OpenCV轮廓提取实战:从预处理到形状匹配的完整链路

简介:这份资源围绕OpenCV轮廓提取功能展开,面向正在学习计算机视觉、图像处理的高校学生与开发者,帮助读者理解从二值图像中计算轮廓、绘制轮廓的完整流程。内容以findContours与drawContours两个核心函数为主线,逐一讲解image、c…

2026/10/14 1:56:48 阅读更多 →

最新新闻

Dropout 正则化原理与实战:从过拟合到泛化能力提升

Dropout 正则化原理与实战:从过拟合到泛化能力提升

1. 为什么一个"随手关掉神经元"的操作能成为深度学习的基石第一次在代码里写下nn.Dropout(p0.5)的时候,我其实没太当回事——不就是训练时随机扔掉一半神经元嘛,听起来像个正则化的小把戏。直到有一次复现一篇图像分类论文,模型在训…

2026/10/14 4:24:51 阅读更多 →
从60到150 t/s:Strata推理栈与INT4量化在48G显存上的实战调优

从60到150 t/s:Strata推理栈与INT4量化在48G显存上的实战调优

1. 先说说那三秒:149.7 t/s 砸到眼前那天晚上我蹲在测试机前面,盯着终端里不断滚动的数字,一时没回过神来。屏幕上清清楚楚写着“149.7 t/s”。按标题里的说法,就是那套组合——内部代号 Strata 的推理栈,加上一个叫 q…

2026/10/14 4:24:51 阅读更多 →
Java毕设实战:基于爬虫的题库自动生成系统完整解析

Java毕设实战:基于爬虫的题库自动生成系统完整解析

简介:毕设项目-利用爬虫的题库自动生成系统 是面向计算机相关专业本科生毕业设计场景的完整工程,适用于需要快速搭建可运行题管理平台的Java开发者。针对题库建设中题目来源单一、手工录入效率低等问题,整体以Java为后端核心、Vue为管理端页面…

2026/10/14 4:24:51 阅读更多 →
机械原理课程设计洗瓶机:凸轮机构实现推头匀速回程三倍速

机械原理课程设计洗瓶机:凸轮机构实现推头匀速回程三倍速

简介:基于机械原理的洗瓶机课程设计资料面向机械专业本科生,完整呈现从功能分解、运动方案设计到执行机构选型的全过程,适合完成课程设计或复习机构学知识时参考。内容围绕瓶子推进、旋转与刷洗三大动作展开,明确了推进距离600mm、…

2026/10/14 4:24:51 阅读更多 →
旅游线路查询接口分页漂移导致数据抓取错位的排查与规避

旅游线路查询接口分页漂移导致数据抓取错位的排查与规避

1. 一个看似普通的查询需求,怎么就翻车了事情是这样的,前阵子帮一个做旅游内容聚合的朋友看他们后台的数据对账问题。他们有一个模块是抓取某旅游线路平台(就是那种典型的“黑马旅游网”风格的线路查询站点)的线路数据&#xff0c…

2026/10/14 4:24:51 阅读更多 →
西门子RPC开发实战:从通信接口到产线落地的完整路径

西门子RPC开发实战:从通信接口到产线落地的完整路径

简介:这份西门子RPC开发功能文档面向工业自动化领域的开发者、设备集成工程师与数控系统调试人员,聚焦SINUMERIK 840D/840Di/810D平台下远程过程调用的接口规范与开发方法。文档系统梳理了主机接口、PLC/NCK接口、HMI与NCK/PLC的OEM交互接口等核心模块&a…

2026/10/14 4:23:50 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/12 18:11:17 阅读更多 →