超声波测距模块HC-SR04原理、代码实现与工程实践全解析
最近在做一个智能小车项目需要实现自动避障功能超声波测距模块就成了我的首选方案。但在实际调试过程中发现网上很多教程要么代码不完整要么对原理和误差处理讲得不够透彻导致新手很容易卡在数据不准或模块不响应的问题上。本文将为你系统梳理超声波测距从核心原理、硬件连接到代码实现的完整闭环。无论你是刚接触 Arduino 或树莓派的爱好者还是需要在嵌入式项目中集成测距功能的开发者都能通过本文获得一套可直接复用的解决方案并理解背后的时序逻辑和常见避坑要点。1. 超声波测距的核心原理与模块选型在开始接线和写代码之前理解超声波测距的工作原理至关重要这能帮助你在后续调试中快速定位问题。1.1 什么是超声波测距超声波测距是一种非接触式的距离测量方法。它模仿了蝙蝠等生物的“回声定位”能力模块发射一束人耳听不见的超声波频率通常高于20kHz当这束声波遇到障碍物后会反射回来被模块接收。通过精确测量从“发射”到“接收到回波”所经过的时间再结合声音在空气中的传播速度就能计算出模块到障碍物的距离。其核心计算公式为距离 (声速 × 时间) / 2公式中的“除以2”是因为声波走了一个来回。1.2 常见模块HC-SR04详解在创客和嵌入式领域HC-SR04是最经典、最普及的超声波测距模块。它价格低廉、使用简单是入门和实践的首选。工作电压5V DC工作电流约15mA探测角度小于15度探测距离官方标称2cm - 400cm实际有效距离约2cm - 200cm精度可达3mm引脚定义4个引脚VCC电源正极接5VTrig触发控制信号输入接收来自MCU的脉冲信号Echo回响信号输出向MCU输出高电平脉冲GND电源地除了HC-SR04你可能会遇到一些变种或升级模块如HY-SRF05引脚兼容性能类似。US-100内置温度补偿可通过UART或GPIO模式工作精度更高。JSN-SR04T防水型探测距离更远。本文将以HC-SR04为例进行讲解其原理和方法同样适用于其他GPIO触发型的超声波模块。2. 环境准备与硬件连接2.1 所需材料清单在开始实验前请确保你已准备好以下硬件主控板任选其一Arduino Uno / Nano / Mega本文示例以Arduino为主树莓派 (Raspberry Pi) 3B/4B/ZeroESP8266 (NodeMCU) 或 ESP32超声波模块HC-SR04 × 1连接线杜邦线公对公或公对母根据主控板接口而定若干电源USB数据线或适配器用于给主控板供电障碍物用于测试的平面物体如书本、墙壁2.2 电路连接示意图与步骤连接原理HC-SR04的VCC和GND分别为模块供电Trig和Echo是信号引脚需要连接到主控板的数字IO引脚Digital I/O Pins。以下是Arduino Uno与HC-SR04的连接方式HC-SR04 引脚连接到 Arduino Uno 引脚说明VCC5V提供5V工作电压Trig数字引脚 9用于发送触发脉冲Echo数字引脚 10用于接收回波脉冲GNDGND共地确保电压基准一致接线步骤将HC-SR04模块平稳地插入面包板或用杜邦线直接连接。使用一根杜邦线连接Arduino的5V引脚到模块的VCC。使用一根杜邦线连接Arduino的GND引脚到模块的GND。使用一根杜邦线连接Arduino的数字引脚 9 (D9)到模块的Trig。使用一根杜邦线连接Arduino的数字引脚 10 (D10)到模块的Echo。重要提醒务必确保电源正负极VCC和GND连接正确接反极易烧毁模块。如果你使用3.3V系统的主控板如ESP8266、树莓派需要注意HC-SR04的Echo脚输出是5V电平。直接连接可能会损坏3.3V主控板的GPIO安全的做法是使用电平转换电路如分压电阻将5V降至3.3V或者选择Echo脚支持3.3V输入的模块变种。3. 驱动原理与核心代码拆解HC-SR04的工作完全由时序控制理解此时序是编写正确驱动代码的关键。3.1 模块工作时序图解读模块的每一次测距都需要主控板MCU严格按照以下时序进行操作初始化Trig和Echo引脚均保持低电平。发送触发信号MCU向Trig引脚发送一个至少10微秒µs的高电平脉冲。模块自动动作模块检测到Trig的上升沿后会自动发射8个40kHz的超声波脉冲并同时将Echo引脚拉高。等待回波超声波在空气中传播遇到障碍物后返回。接收回波模块接收到返回的超声波后将Echo引脚拉低。至此Echo引脚高电平的持续时间就是超声波从发射到返回的整个飞行时间。计算距离MCU通过测量Echo高电平的时间t单位微秒代入公式计算距离。3.2 基础驱动代码实现Arduino下面是一个最基础、最清晰的Arduino驱动代码包含了详细的注释。// 定义HC-SR04模块连接的引脚 const int trigPin 9; // 触发引脚 const int echoPin 10; // 回波引脚 // 定义声速厘米/微秒20摄氏度干燥空气中的近似值 const float speedOfSound 0.0343; // 343 m/s 0.0343 cm/µs void setup() { // 初始化串口通信用于在电脑上显示结果 Serial.begin(9600); // 配置引脚模式 pinMode(trigPin, OUTPUT); // Trig需要输出控制信号 pinMode(echoPin, INPUT); // Echo是输入信号用于读取 // 初始化状态确保Trig为低电平 digitalWrite(trigPin, LOW); delayMicroseconds(2); // 短暂稳定 } void loop() { // 1. 发送一个10µs的高脉冲触发测距 digitalWrite(trigPin, HIGH); delayMicroseconds(10); // 必须至少10µs digitalWrite(trigPin, LOW); // 2. 读取Echo引脚的高电平持续时间 // pulseIn()函数会等待引脚变为高电平开始计时再等待变为低电平停止计时并返回持续的微秒数。 // 参数引脚 状态 超时时间可选单位微秒 long duration pulseIn(echoPin, HIGH, 30000); // 设置30ms超时对应约5米距离 // 3. 计算距离单位厘米 // 距离 (时间 * 声速) / 2 float distance duration * speedOfSound / 2.0; // 4. 通过串口输出结果 Serial.print(Distance: ); Serial.print(distance); Serial.println( cm); // 每次测量间隔500毫秒避免信号相互干扰 delay(500); }代码关键点解析pulseIn(pin, value, timeout)这是Arduino的核心函数用于精确测量脉冲宽度。第三个参数timeout很重要它设定了等待脉冲的最大时间避免程序卡死。这里设为30000µs30ms对应声波最远传播约5米来回10米的时间。声速的取值代码中使用了0.0343 cm/µs。这是声音在20℃干燥空气中的速度343米/秒。温度对声速影响很大后文会讨论温度补偿。单位换算duration单位是微秒(µs)声速单位是厘米/微秒(cm/µs)计算出的distance单位就是厘米(cm)。4. 完整实战构建一个带温度补偿的测距仪基础代码在恒温环境下尚可但实际应用环境温度多变。为了提高精度我们需要引入温度传感器进行实时声速校准。4.1 项目升级增加DS18B20温度传感器我们将使用DS18B20数字温度传感器来获取环境温度。它采用单总线协议只需一个数据引脚精度较高。新增硬件连接DS18B20的VDD接 Arduino5VDS18B20的GND接 ArduinoGNDDS18B20的DQ接 Arduino数字引脚 2并接一个4.7KΩ上拉电阻到5V4.2 完整代码实现首先你需要在Arduino IDE中安装DallasTemperature和OneWire库。可以通过“工具” - “管理库”进行搜索安装。// 项目带温度补偿的超声波测距仪 // 依赖库OneWire, DallasTemperature #include OneWire.h #include DallasTemperature.h // HC-SR04 引脚定义 const int trigPin 9; const int echoPin 10; // DS18B20 引脚定义 const int oneWireBus 2; OneWire oneWire(oneWireBus); DallasTemperature sensors(oneWire); // 0℃时的声速米/秒 const float speedOfSoundAt0C 331.3; void setup() { Serial.begin(9600); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); digitalWrite(trigPin, LOW); // 启动温度传感器 sensors.begin(); Serial.println(Ultrasonic Ranging with Temperature Compensation); Serial.println(-----------------------------------------------); } void loop() { // 步骤1读取环境温度 sensors.requestTemperatures(); float temperature sensors.getTempCByIndex(0); // 获取第一个传感器的摄氏温度 // 检查温度读数是否有效DS18B20读取失败返回-127 if (temperature -127.0) { Serial.println(Error: Could not read temperature!); delay(1000); return; } // 步骤2根据当前温度计算精确声速 (v 331.3 0.606 * T) float speedOfSound speedOfSoundAt0C (0.606 * temperature); // 单位米/秒 // 转换为 厘米/微秒 float speedOfSound_cm_per_us speedOfSound * 100.0 / 1000000.0; // 步骤3触发超声波测距 digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); // 步骤4测量回波时间 long duration pulseIn(echoPin, HIGH, 30000); // 超时30ms // 步骤5计算并输出距离 if (duration 0) { float distance duration * speedOfSound_cm_per_us / 2.0; Serial.print(Temperature: ); Serial.print(temperature); Serial.print( C | ); Serial.print(Sound Speed: ); Serial.print(speedOfSound); Serial.print( m/s | ); Serial.print(Distance: ); Serial.print(distance); Serial.println( cm); } else { // 超时或未检测到回波 Serial.println(Measurement timed out or no echo received.); } // 每秒测量一次 delay(1000); }4.3 运行与结果验证按照电路图连接好HC-SR04和DS18B20。将代码上传到Arduino。打开串口监视器波特率9600。在模块前方放置障碍物观察输出的距离值。尝试用手温影响DS18B20传感器观察声速和距离计算值的变化。你会看到类似以下的输出其中声速会根据温度动态调整Ultrasonic Ranging with Temperature Compensation ----------------------------------------------- Temperature: 25.50 C | Sound Speed: 346.50 m/s | Distance: 15.32 cm Temperature: 25.62 C | Sound Speed: 346.63 m/s | Distance: 15.30 cm5. 常见问题与深度排查指南在实际使用中你可能会遇到各种问题。下表列出了最常见的问题现象、原因及解决方案。问题现象可能原因排查思路与解决方案串口始终输出0或极小值1. 接线错误或接触不良。2.Echo引脚未正确配置为INPUT。3. 障碍物太近2cm或太远400cm超出模块量程。4. 障碍物表面不反射超声波如绒毛、海绵。1.断电后重新检查所有连线尤其是VCC和GND。2. 检查代码中pinMode(echoPin, INPUT)。3. 确保障碍物在2-200cm之间且表面平整坚硬。4. 换用书本、墙壁等物体测试。输出距离值固定不变或乱跳1. 电源干扰或功率不足。2. 测量间隔太短上一次回波干扰下一次触发。3. 环境噪声干扰其他超声波源、电机振动。4.pulseIn超时时间设置不当。1. 尝试给Arduino单独供电或使用外部稳压电源。2. 在loop()中增加delay(100)以上。3. 让模块远离电机、风扇或在安静环境下测试。4. 根据最大量程调整pulseIn超时参数。pulseIn超时返回01. 障碍物超出最大探测距离。2.Trig触发脉冲宽度不足10µs。3. 模块损坏。4.Echo引脚电平不兼容3.3V系统接5V模块。1. 将障碍物移近。2. 确保digitalWrite(trigPin, HIGH); delayMicroseconds(10);被执行。3. 用万用表测VCC电压是否为5V或用另一个模块替换测试。4. 3.3V主控必须加电平转换电路。测量精度差波动大1. 声速未做温度补偿。2. 障碍物角度倾斜导致回波减弱。3. 测量对象是小尺寸或复杂形状物体。4. 供电纹波大。1.强烈建议加入温度传感器进行补偿如本文实战部分。2. 确保模块正对障碍物平面。3. 超声波束有角度对小物体测距不准是物理限制。4. 在VCC和GND之间并联一个10µF-100µF的电解电容进行滤波。模块发热严重电源接反这是最危险的情况。**立即断电**检查VCC和GND是否接反。接反极易永久性损坏模块。高级排查工具如果你有逻辑分析仪或示波器可以同时观察Trig和Echo引脚的波形这是最直接的调试方法。你应该能看到一个短暂的Trig脉冲以及一个宽度随距离变化的Echo脉冲。6. 工程实践与优化建议将超声波模块集成到实际项目中时需要考虑更多工程化因素。6.1 软件层面的优化滤波算法单次测量存在偶然误差。通常采用中值滤波或均值滤波。// 示例连续采样5次取中值 #define SAMPLE_SIZE 5 float getFilteredDistance() { float samples[SAMPLE_SIZE]; for (int i 0; i SAMPLE_SIZE; i) { samples[i] measureSingleDistance(); // 封装好的单次测量函数 delay(50); // 小间隔避免干扰 } // 简单排序取中值可优化为更高效的算法 sortArray(samples, SAMPLE_SIZE); return samples[SAMPLE_SIZE / 2]; }非阻塞式编程在需要同时处理其他任务如控制电机、通信时应避免使用delay()和阻塞的pulseIn()。可以使用millis()进行状态机管理或使用中断来检测Echo下降沿。// 状态机思路伪代码 unsigned long triggerTime; enum State { IDLE, TRIGGERED, WAITING_ECHO }; State currentState IDLE; void loop() { switch(currentState) { case IDLE: if (millis() - lastMeasureTime 100) { startMeasurement(); currentState TRIGGERED; triggerTime micros(); } break; case TRIGGERED: // ... 控制Trig引脚时序 currentState WAITING_ECHO; break; case WAITING_ECHO: // 检查Echo引脚电平结合micros()计算时间差 // 计算完成后currentState IDLE; break; } // 这里可以执行其他任务 }超时与异常处理必须为每次测量设置合理的超时并在代码中处理超时情况防止程序卡死。6.2 硬件与布局的考量电源去耦在模块的VCC和GND引脚之间就近并联一个0.1µF的陶瓷电容和一个10µF的电解电容可以有效抑制电源噪声提高稳定性。物理安装安装时确保模块前方探测区域无遮挡。避免将模块安装在会产生振动的部件如电机附近振动会影响声波传播。多模块干扰如果系统需要使用多个超声波模块它们之间会相互干扰。解决方案是分时复用同一时间只触发一个模块。物理隔离让模块朝向不同方向或使用屏蔽罩。编码发射使用更高级的、能发射特定编码信号的超声波模块。6.3 替代方案与边界认知了解技术的边界同样重要绝对精度限制受温度、湿度、气压影响民用超声波模块的精度通常在毫米到厘米级。对精度要求高的场合如工业测量需选用专业级传感器并做全环境补偿。探测对象限制对柔软、多孔、细小或极端角度的物体探测效果会变差甚至失效。响应速度限制受声速限制测量远处物体需要更长的“飞行时间”这限制了系统的最大采样频率。对于更远距离数米至数十米或更复杂环境户外、雨天可以考虑激光测距Lidar或毫米波雷达但这些方案成本和复杂度也更高。掌握超声波测距不仅仅是连接模块和复制代码。从理解声波飞行时间原理到完成硬件连接再到编写稳定的驱动代码并处理温度补偿最后通过滤波和状态机优化将其融入实际项目这是一个完整的嵌入式传感器应用闭环。

相关新闻

基于Python与Vosk的《我的世界》本地语音控制自动化方案

基于Python与Vosk的《我的世界》本地语音控制自动化方案

1. 先搞清楚“语音控制MC外挂”到底能做什么,不能做什么 看到“语音控制MC外挂”这个标题,很多人第一反应可能是“用嘴玩游戏”或者“解放双手的神器”。但作为一个在游戏开发和自动化脚本领域折腾过不少项目的人,我得先泼点冷水&#xff1a…

2026/10/18 1:42:22 阅读更多 →
C#单件模式实战:从线程安全到Lazy<T>的最佳实践

C#单件模式实战:从线程安全到Lazy<T>的最佳实践

1. 单件模式:为什么它既是基石,又是“坑王”?在C#开发里,尤其是做上位机、工业控制或者需要长期运行的服务端应用时,你肯定遇到过这样的场景:整个系统只需要一个配置管理器、一个日志记录器,或者…

2026/10/18 1:49:48 阅读更多 →
Claude 4.8 代码重构实测:从问题识别到设计模式建议

Claude 4.8 代码重构实测:从问题识别到设计模式建议

引言 代码重构是软件开发中最需要经验判断的环节。2026年AI模型的重构能力已经从"改代码"进化到"给建议"——Claude 4.8不仅能识别代码问题并重构,还会主动推荐设计模式并解释理由。最近我在猪猪AI(titiai.cn)上做了一轮…

2026/10/18 2:29:38 阅读更多 →

最新新闻

1~30秒参考音频克隆任意声音:Seed-VC 零样本语音转换完整零训练指南

1~30秒参考音频克隆任意声音:Seed-VC 零样本语音转换完整零训练指南

1~30秒参考音频克隆任意声音:Seed-VC 零样本语音转换完整零训练指南 【免费下载链接】seed-vc zero-shot voice conversion & singing voice conversion, with real-time support 项目地址: https://gitcode.com/GitHub_Trending/se/seed-vc 有一场会要开…

2026/10/19 2:01:28 阅读更多 →
MiniCPM-V-2_6-GPTQ 视频理解全流程:64 帧看懂一整段视频

MiniCPM-V-2_6-GPTQ 视频理解全流程:64 帧看懂一整段视频

MiniCPM-V-2_6-GPTQ 视频理解全流程:64 帧看懂一整段视频 【免费下载链接】antimicrox Graphical program used to map keyboard buttons and mouse controls to a gamepad. Useful for playing games with no gamepad support. 项目地址: https://gitcode.com/Gi…

2026/10/19 2:01:28 阅读更多 →
biliTickerBuy 完整使用指南:免费开源的 B 站会员购抢票辅助工具,开售自动下单

biliTickerBuy 完整使用指南:免费开源的 B 站会员购抢票辅助工具,开售自动下单

biliTickerBuy 完整使用指南:免费开源的 B 站会员购抢票辅助工具,开售自动下单 【免费下载链接】biliTickerBuy b站会员购购票辅助工具 项目地址: https://gitcode.com/GitHub_Trending/bi/biliTickerBuy 开售那几秒,你连刷七八次页面,「立即购买」刚亮起就弹出排队提示…

2026/10/19 2:01:28 阅读更多 →
低功耗设计中的反直觉陷阱:为什么进入 STOP 模式电流反而变大了?

低功耗设计中的反直觉陷阱:为什么进入 STOP 模式电流反而变大了?

摘要: 可穿戴设备续航从 7 天缩水到 2 天,电池容量没变、固件逻辑没改,问题出在低功耗模式上。更诡异的是——进入 STOP 模式后电流反而比 RUN 模式更大。这不是硬件故障,而是低功耗设计里最反直觉的一类陷阱:GPIO 悬空、外设时钟未关、上拉下拉配错、调试接口未禁用……每…

2026/10/19 2:01:28 阅读更多 →
Qwen-Image-Layered-6bit分层质量调优:steps与resolution如何取舍才最划算

Qwen-Image-Layered-6bit分层质量调优:steps与resolution如何取舍才最划算

【免费下载链接】Qwen-Image-Layered-6bit 项目地址: https://ai.gitcode.com/hf_mirrors/zimengxiong/Qwen-Image-Layered-6bit 点击查看 免费下载 Qwen-Image-Layered-6bit 是面向 Apple Silicon 的 6-bit 量化图像分层模型,能把任意图片分解为多张 R…

2026/10/19 2:01:28 阅读更多 →
ABAP Cloud 的 OLTP 开发,从数据增删改查走向完整的业务事务

ABAP Cloud 的 OLTP 开发,从数据增删改查走向完整的业务事务

采购申请页面上的保存按钮,背后通常不只有一次数据库写入。申请抬头需要保存,行项目需要关联,金额需要计算,供应商需要校验,当前操作者还必须具备相应权限。只要其中一项没有满足业务要求,系统就不能把这张申请当成一份完整、有效的业务单据。 这类围绕业务数据开展读取…

2026/10/19 2:00:28 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 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/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 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/18 0:55:02 阅读更多 →
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/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练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/18 12:16:16 阅读更多 →