news 2026/11/5 1:05:28

用STM32F745ZG与串口24位ADC搭建多路远距离温度采集系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用STM32F745ZG与串口24位ADC搭建多路远距离温度采集系统

去年做一套多联机外机的电装控制板时,温度采集通道一共排了12路,分布在主控板和几个离散的温度采集盒里。最后定下的方案,就是用标题里的组合:STM32F745ZG做主控,温度采集全部交给ADS122U04IPWR。这块芯片不是普通ADC,而是一个自带UART接口的24位多通道精密ADC,模拟前端内置PGA、激励电流源、工频滤波器;主控只管发命令、收数据,其余脏活累活全部由芯片自己扛。选这个组合的核心原因很朴素:UART总线在工业现场比SPI好用太多,传感器和主控可以隔着几十米拉线,一根串口线就能把挂在总线上的多片ADC全部管理起来,不用去考虑SPI引脚复用、片选扩展这些破事。做HVAC控制器的、做工业仪表的,都适合参考这套方案,尤其是你正在找“带串口的精密ADC”和“Cortex-M7主控”怎么配合的完整链路。

1. 项目整体设计与关键需求解析

1.1 ADC选型背后的几个真实痛点

很多刚接触温度采集的工程师,第一反应是选个SPI接口的ADS1220或ADS124S08,然后开始布局SCLK、MOSI、MISO、CS四条线。在PCB上短距离走线确实没问题,但当传感器要分布在几个采集盒里、离主控好几米远的时候,SPI方案会变得非常难受。

第一个痛点是片选。SPI ADC每片都需要一个独立的CS,假设主控带4路片选,那最多挂4片ADC;要挂8片、12片,要么外扩GPIO,要么用译码器。板子上两三个译码芯片塞进去,不仅占用面积,还增加故障点。第二个痛点是信号完整性。SPI的SCLK通常是几MHz甚至几十MHz的时钟,长线缆传输时反射、振铃、串扰都会冒出来,必须在软件里把SPI时钟降到很低才能稳定通信,这又把ADC的高采样率优势浪费了。第三个痛点是隔离。工业现场经常要加隔离,SPI四条线隔离意味着四路数字隔离器,成本高、功耗大,几乎没人愿意这么干。

ADS122U04这类UART ADC正好打了这三个痛点。它把通信接口换成UART,物理上只有TX和RX两条线,主控端也只需要一个普通串口。线缆可以拉长到几十米甚至上百米,只要把电平换成RS-485或者RS-422,电机房到控制柜之间的温度采集就成了常规操作。多片ADC挂在同一条总线上,通过命令寻址区分设备,片选问题彻底消失。这一点在做项目选型时,价值是决定性的。

1.2 为什么主控选STM32F745ZG而不是F1/F4

STM32F745ZG这颗料是Cortex-M7内核,主频跑到216MHz,内部带1MB Flash和320KB SRAM。做一套温度采集,单从算力上说用F103都绰绰有余,我选F745ZG不是炫技,而是因为这颗料承担的任务远不止读温度。

当时的项目里,主控同时跑着Modbus RTU主从通信、RS-485组网、人机交互界面,以及后续要加入的故障诊断和参数记录功能。F745ZG的Cortex-M7内核带DSP指令和硬件浮点单元,做温度滤波、热电偶冷端补偿、传感器线性化计算的时候,效率比M3/M4高一大截。特别是浮点运算,写温度换算代码时不需要做定点数变换,直接float运算,调试期省了大量时间。

另外,F745ZG内置多个USART,串口资源充足。一个USART给板载ADC总线,一个USART走Modbus,一个USART接调试模块,互不干扰。还有一点是平台化思维:同一个主控方案如果只是换了传感器类型和量程,固件和硬件改动很小,就能覆盖下一个项目。当公司同时维护两三套设备时,主控平台统一意味着BOM采购更方便、工程师上手更快、售后备件更简单。单看一颗芯片的价格确实略高,但放到整个项目的维护成本里算,反而最划算。

1.3 系统整体架构到底长什么样

这套系统的信号流向并不复杂。传感器(PT100或PT1000)接入ADS122U04的模拟输入通道,ADC负责激励电流输出、PGA放大、24位模数转换和工频滤波。主控STM32F745ZG通过UART接口向ADC发送配置命令和读取命令,拿到原始ADC码后,换算成电压、电阻,最终解算出温度值,再走Modbus或者其他总线把温度数据发送到上位机或PLC。

如果现场环境复杂,ADC也可以放在传感器附近而不是主控板上。ADC的UART信号经过RS-485收发器后,沿着双绞线传到主控端,再经过RS-485收发放回TTL电平给STM32。模拟信号不需要长距离传输,长距离传输的是数字信号,这样抗干扰能力和稳定性完全不一样。我区分两种场景:近距离板载安装,ADC和MCU在同一块PCB上,UART直连;远距离采集盒安装,ADC靠近传感器,UART转RS-485后长线传输。两种场景的固件逻辑完全一致,区别只在电平转换和物理层布线。

2. 模拟前端与测量链路设计

2.1 PT100还是PT1000,这是个选择题

工业自动化和HVAC领域用得最多的温度传感器是PT100和PT1000。两者都是铂电阻,0°C时的标准阻值不同,PT100是100Ω,PT1000是1000Ω。温度系数都是约0.385Ω/°C(对应PT100)或3.85Ω/°C(对应PT1000),材料特性相同,但使用场景差异明显。

HVAC项目里我倾向选PT1000。原因之一是电阻值大,同样的激励电流在PT1000上产生的电压信号更大,对后级PGA的增益要求更低、对布线电阻的影响也更小。原因之二是自热效应,激励电流流过电阻时会产生焦耳热,电阻越大、电流越小,自热越小。用250μA激励PT1000,在100Ω级别导线电阻上产生的误差远小于用1mA激励PT100的情形。

工业现场如果测的是-50°C到+500°C的大范围温度,往往选PT100。PT100的电阻变化范围小,ADC端可以用更大的PGA增益,量程可以做得更宽。但PT100对导线电阻极其敏感,两线制接线会引入不可忽略的误差,所以工业上测PT100通常要求三线制或四线制。系统支持哪种传感器,取决于你想面对哪个行业,我在硬件上把两种都预留了,只需要改电阻参数和ADC配置寄存器,固件里做对应的分度表切换就行。

2.2 激励电流、PGA增益和基准电压的配合

ADS122U04内置了两个可编程激励电流源,电流档位可以配置。最关键的参数匹配逻辑是:确保最大被测电阻在激励电流下产生的电压,经过PGA放大后,不要超过ADC的基准电压。基准电压可以是内部2.048V,也可以是外部精密基准。

拿一个典型的HVAC场景举例:测温范围是-20°C到+150°C,用的是PT1000。

PT1000在-20°C时的阻值大约是1000 × (1 + 0.00385 × (-20)) = 923Ω。在150°C时大约是1000 × (1 + 0.00385 × 150) = 1577.5Ω。如果激励电流选250μA,那么低温端信号电压是230.75mV,高温端信号电压是394.375mV。如果PGA增益选4倍,放大后分别是0.923V和1.5775V,正好落在2.048V基准的量程内,低温端也在满量程的45%左右,分辨率不浪费。这个组合在HVAC常见的温度范围内非常好用。

选型时要留出余量。假如测量范围拉到300°C,PT1000阻值会到2155Ω,250μA激励下电压是538.75mV,PGA放大4倍就成了2.155V,超过2.048V基准,ADC超出满量程。这时候要么降PGA到2倍,要么降激励电流到200μA,要么换外部基准。核心思路是“最大信号经过PGA后不超过基准,最小信号经过PGA后不小到被噪声淹掉”。

2.3 电源、接地和UART链路的实战注意点

ADS122U04的模拟电源AVDD和数字电源DVDD我建议分开处理。AVDD用低噪声LDO供电,比如LP5907或者类似超低噪声LDO,直接由24V工业电源经过一级降压到3.3V,但模拟部分的前级必须干净。数字部分的DVDD可以由同一路3.3V供电,但要注意不要在模拟电源地上直接灌数字噪声。

模拟地AGND、数字地DGND和主控GND之间怎么处理,我的做法是单点连接。PCB上把模拟地分割出来,ADC的模拟地回流路径经过模拟地区域,数字地单独走,在整板电源入口处汇合。不要在多处没有控制地拼一起,否则地环路会引入共模噪声,直接在ADC码上表现为来回跳动的几个LSB。

UART链路分两种情况。板载近距离场景,ADC的TX/RX直接连STM32的PA9/PA10这类串口引脚,TTL电平一致,无需转换。远距离场景,我在ADC模块上加了RS-485收发器,MCU端也加一个,中间用屏蔽双绞线。ADC的UART波特率我用了9600bps,这个速率在几十米双绞网上非常稳定,而且ADC本身的数据速率只有20SPS,9600bps完全够用。有人喜欢拉到115200,除非你确定线缆质量和距离都非常好,否则没必要冒这个风险。

3. 固件设计与数据流实现

3.1 ADS122U04的初始化与寄存器配置思路

ADS122U04的UART协议本质是字节流命令,常用命令包括读寄存器RREG、写寄存器WREG、读取转换数据RDATA、启动转换等。所有命令的细节要以TI官方数据手册为准,这里给出我在项目里实际封装过的代码片段,作为骨架参考。

// 写寄存器:命令字节高4位是写标志,低4位是寄存器地址 // 具体命令编号请以ADS122U04数据手册为准 uint8_t adc_write_reg(uint8_t reg, uint8_t value) { uint8_t buf[2]; buf[0] = 0x40 | (reg & 0x0F); buf[1] = value; HAL_UART_Transmit(&huart1, buf, 2, 10); // 命令发出后留出处理时间,约几十微秒到百微秒 delay_us(100); return 0; } uint8_t adc_read_reg(uint8_t reg) { uint8_t cmd = 0x20 | (reg & 0x0F); HAL_UART_Transmit(&huart1, &cmd, 1, 10); uint8_t value = 0; HAL_UART_Receive(&huart1, &value, 1, 10); return value; }

初始化顺序很关键。上电后先等电源稳定,然后给ADC配置激励电流源、配置通道复用和PGA增益、配置转换模式和滤波强度。我建议一次上电后把整组寄存器全部写一遍,而不是只改几个需要的位。因为ADC有可能是异常复位后处于未知状态,全量写入配置可以确保状态收敛到预期。固件里把配置表做成const数组,启动时循环调用写寄存器函数,后续需要修改量程或增益时,直接改配置表,代码很清爽。

通道选择方面,ADS122U04支持多路模拟输入。如果测的是单路PT1000,用差分方式接在AIN0和AIN1上,能抵消共模干扰。如果测多路温度,用内部多路复用器逐通道扫描,每切换一次通道,需要等待足够稳定时间再取数,具体等待时间与滤波器设置有关,我会预留几百毫秒做保守处理。

3.2 STM32F745ZG端的串口与DMA处理

主控端串口采用UART加DMA加IDLE中断的方式接收。ADC返回的每一帧数据虽然不长,但用DMA环形缓冲最稳妥,不需要CPU时刻盯着串口寄存器。

#define ADC_DMA_BUF_SIZE 64 uint8_t adc_dma_buf[ADC_DMA_BUF_SIZE]; // 初始化时调用 HAL_UART_Receive_DMA(&huart1, adc_dma_buf, ADC_DMA_BUF_SIZE); // 并使能IDLE中断 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);

当串口线上出现一帧完整数据后,硬件会拉出IDLE中断,我再在中断回调里把DMA当前计数位置记录下来,这就是本帧数据的终点。由于ADC的命令与返回是严格一问一答的,主控主动发起读取,不会出现多帧粘包的问题。比较麻烦的情况是ADC因为上电时序异常没有收到命令,导致主控等不到响应,所以在软件上加了超时重发机制,每次等待串口接收最多50ms,超时则重发读取命令,连续重发3次仍失败则报线路故障。

波特率方面,STM32与ADC都要使用同一波特率。我在初始化里配置为9600,8位数据,无校验,1停止位。注意两个芯片的时钟误差叠加后,总偏差要小于UART容忍范围。STM32的时钟来自外部晶振,ADS122U04内部有振荡器,两者的误差都在正常范围内,实测9600bps下通信非常稳定。

3.3 原始码转电压、再转温度的换算流程

从ADC读回来的原始码是24位二进制补码形式。换算成电压的基本公式是:

Voltage = code / 8388608.0 × VREF / Gain

其中8388608是2的23次方,对应24位ADC的满量程一半;VREF是基准电压(2.048V),Gain是PGA增益(比如4倍)。用STM32的硬件浮点计算非常快,不需要任何优化技巧。

电压再转电阻就简单了,因为是恒流源激励,R = Voltage / I_EXT。如果用250μA激励,比如电压是275mV,电阻就是1100Ω。最后电阻转温度,工程上有两种做法。低精度场景用线性近似:

Temperature = (RT - R0) / (R0 × α)

其中R0是0°C时的标准阻值(PT1000就是1000Ω),α取0.00385。这个近似在0°C到100°C范围内误差很小,但到了150°C以上偏差会明显增大。高精度场景必须查分度表,把IEC60751标准的电阻-温度表做成数组,用二分查找加插值,计算量也很小。我实际固件里两种都实现了,用宏开关切换。

// 线性近似,适用于快速调试 float rt_to_temp_linear(float rt, float r0, float alpha) { return (rt - r0) / (r0 * alpha); } // 查表法入口 float rt_to_temp_iptc95(float rt) { // 二分查表并线性插值,具体实现略 return interpolation(pt1000_table, table_size, rt); }

3.4 数据滤波与标定经验

ADS122U04自带数字滤波器和工频滤波功能,能抑制50Hz和60Hz干扰。软件层面我另外叠加了一套组合滤波:先做中值滤波剔除偶发的尖峰毛刺,再做滑动平均平滑输出。

ADS的转换结果直接参与滑动平均前,我会先丢弃前两个数据点。因为通道切换后第一两组数据可能还在稳定过程中,直接使用会让平均值明显偏大。这不是算法问题,而是模拟前端建立时间不够的典型表现。实测下来,切换通道后等待200ms再取数,输出值立刻稳定。

标定是温度测量绕不开的一步。ADC本身经过出厂校准,但外部恒流源的精度、基准电压的误差、PGA的增益误差都会引入系统偏差。简单标定方法是用一个精密电阻箱模拟RTD,至少取0°C和100°C两个点的标准阻值,让固件记录实际ADC读数,然后拟合一条修正曲线。相比改硬件参数,软件标定省力得多。批量生产时,给每台设备烧录一个标定系数即可,不用动任何电路。

4. 常见问题与调试实录

4.1 UART通信异常:设备无响应该怎么办

实际调试中最常遇到的现象是:主控发送寄存器配置命令后,ADC没有任何返回,或者返回的数据明显错位。这个问题第一次遇到时,我先用示波器抓了UART波形,确认TX引脚确实有帧信号,但RX线上一直没动静。

排查路径从物理层开始。检查RX和TX是否正确接成交叉——ADC的TX要接主控的RX,ADC的RX要接主控的TX,这是一个低级错误但极其常见。确认接线没问题后,再检查电平是否一致,ADC的IO电平是不是3.3V,主控的串口是不是也配置成了3.3V,两者都满足才有通信基础。

还有一个容易被忽略的点:ADS122U04初始化需要时间,某些环境下复位后要等一段时间才能正确响应命令。我后来在固件里加了一道上电延时,至少等待5ms再发第一条命令。如果是几片ADC级联的菊花链,还要逐片检查地址配置,一根总线上如果地址冲突,也会出现整体无响应的情况。

协议层方面,建议在调试初期先读寄存器ID或版本信息,确认通信通路正常,再去做复杂的配置和读取。通信正常后,我会用逻辑分析仪把收发两端的消息记录下来,一张图能看清命令和返回的对应关系,比代码排查高效得多。

4.2 读数跳动和工频干扰的处理顺序

ADC读数低速跳几个LSB,往往不是ADC本身的问题,而是前端信号或供电的问题。先用示波器看AVDD上的纹波,纹波明显超过几毫伏,就说明供电不干净。模拟电源前级加磁珠或π型滤波,通常能改善。

再看传感器引线。两线制接法下,导线电阻会带来误差,导线所处环境如果有变频器、电机启动或开关电源的噪声耦合,ADC数就会乱跳。此时除了改成四线制,还要看信号线有没有和动力线走同一个线槽。把传感器线单独走管,或者换成屏蔽双绞线,干扰会大幅下降。

代码层可以做的动作是把ADS122U04的工频滤波器打开。板上ADC的数字滤波器能对50Hz和60Hz产生陷波,实测打开后低频纹波被压掉。软件层面再加滑窗平均,读数跳动范围能收敛到0.5°C以内。下面是我整理的一个快速排查表,遇到问题按顺序查,基本都能定位。

现象可能原因排查措施
读数整体偏移恒流源或基准偏差未标定用精密电阻箱校准增益和偏移
读数波动大供电纹波大或基准不稳示波器测AVDD,加强滤波
读数周期性跳跃工频干扰耦合进模拟输入开启ADC内部工频滤波器
读数偶发尖峰通信帧丢失导致解析错位增加通信超时重发和软件中值滤波
某个通道结果异常通道切换后未充分稳定切换后增加等待时间
温度显示与实际偏差大传感器接线方式引起的误差改三线制或四线制接线

4.3 传感器引线电阻与自热误差的取舍

工业现场传感器往往离ADC有几米甚至几十米,两线制接法的误差公式是:误差温度 = 2 × 导线电阻 / (R0 × α)。如果导线电阻是10Ω,PT100在0°C时,误差就是2×10 / (100×0.00385),约等于51.9°C。两线制PT100完全没法远距离用,所以工业仪表基本都是三线制或四线制。

三线制的思想是:让一根导线只传输激励电流,另一根导线用于测量电压参考,用电流路径的导线压降抵消电压路径上的压降。四线制是最彻底的方案,激励电流走一对线,电压测量走另外一对线,测量回路基本没有电流,导线压降不影响精度。ADS122U04的差分输入结构和内部激励电流源,正好能把三线制或四线制的优势发挥出来。

激励电流的自热误差反过来也要控制。250μA在PT1000上产生的功耗只有0.0625mW,PT1000本身的温度升高几乎可以忽略。但如果用1mA激励,功耗就是1mW,PT1000可能被加热出0.1°C到0.3°C的误差,这在HVAC控制上可能不重要,但在高精度工业测量中会导致系统偏差。激励电流档位的选择本质上是信号幅度和自热误差之间取舍。

5. 实测优化与经验扩展

5.1 把“能出数”变成“出得准”的三个动作

第一版固件里温度数据已经能通过串口读出来,但和标准水银温度计或精密温度计对比时,误差有2°C左右。排查发现主要有三个偏差来源:激励电流的实际值不是标称值、PGA增益存在约0.1%的误差、ADC内部基准存在偏差。单靠芯片手册里的指标,不可能直接达到现场要求的精度。

于是做了三个修正动作。第一,用高精度电阻箱作为标准电阻,在0°C、50°C、100°C三个点做静态标定,计算出每个设备的增益系数和偏移量,写到Flash存储区保存。第二,改用外部精密基准作为ADC参考源,虽然成本增加一点,但基准温漂从内部基准的几十ppm降到几ppm,整机温漂明显改善。第三,固件里对RTD做了非线性修正,不再用简单的线性近似,而是用IEC60751的分度表查表线性插值。这三步做完后,整机实测误差基本控制在0.2°C以内,已经能满足HVAC和大多数工业应用要求。

这套“先通信、后测量、再标定”的三步走流程,我给后面接手的人留成了文档。没有标定的温度采集只能算功能演示,真正交付给客户,必须把标定流程和误差评估报告做出来。这是从工程师到产品级交付的重要门槛。

5.2 多片ADC级联的组网技巧

ADS122U04一个很实用的特性是支持UART菊花链级联,多片ADC可以挂同一条总线上。我实际组过8片的网络,每片ADC各自连接附近的传感器,MCU端只用一个串口。软件里配置了一套节点管理逻辑:每片ADC通过命令中的地址信息识别自己是否需要响应,主控按节点号轮询,逐片读取数据。

轮询周期方面,温度本身变化慢,20SPS的数据速率已经足够,8片ADC全部轮询一遍也就是几百毫秒的事。设计时要注意总线上所有ADC必须配置成完全相同的波特率,否则整个网络通信全乱。硬件上每个节点的电源和地要独立滤波,否则远端节点的数字噪声会污染总线,引起偶发乱码。

还有一层是隔离处理。工业现场用RS-485组网时,每个ADC节点通过RS-485收发器接入双绞线,主控端再接另一块RS-485收发器。这样物理层变成了差分信号,抗共模干扰能力大幅提升。ADC节点本身用隔离电源供电时,要保证隔离后的地不与主控地短路,否则隔离失效。

5.3 这套组合还能怎么扩展

温度采集只是这套架构的一个起点。ADS122U04有多个输入通道,只要改一下模拟前端,它还能测小信号压力传感器、称重传感器的毫伏级信号,这对于把温度和压力采集做进同一块板卡很有吸引力。STM32F745ZG的资源也远没有用满,后续往里面加了数据记录、曲线显示、异常告警这些功能,Flash和RAM都很充裕。

通信层面如果后续要对接楼宇自控系统,Modbus RTU已经跑通了,再封装一层BACnet或者MQTT网关,HVAC项目就能直接和上位平台联调。近两年现场的客户越来越想要联网和预测性维护,ADC数据本身就是维护系统的重要输入。我自己倾向于在硬件上预留一路485接口和一路RS-232接口,这样无论是接老式PLC还是接IoT网关,都不用重新改板。

从成本角度说,单颗ADS122U04加一颗STM32F745ZG的成本不低,但当你面对的是多路、分散、远距离的测温场景时,这套组合省下的布局面积、布线条数、调试时间和售后维护成本,远高于芯片本身的差价。这也是为什么我在选型会上坚持用它的原因。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/5 1:04:39

STM32F411RE搭配ADS122U04:24位UART接口ADC实现高精度抗干扰温度采集

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

作者头像 李华
网站建设 2026/11/5 1:04:37

基于ADS122U04与PIC32的工业温度传感器采集方案

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

作者头像 李华
网站建设 2026/11/5 1:04:23

基于ADS122U04与RA4M1的工业及HVAC高精度温度测量方案

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

作者头像 李华
网站建设 2026/11/5 1:04:21

ADS122U04IPWR+STM32L041C6工业温度测量方案解析

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

作者头像 李华
网站建设 2026/11/5 1:03:50

基于ADS122U04与ATmega1280的工业温度采集方案设计

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

作者头像 李华
网站建设 2026/11/5 1:03:38

24位ADC配合STM32实现高精度温度采集:从PT100比例测量到HVAC实战

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

作者头像 李华