手头正好在做一个小型室内空气质量监测盒子核心板选了STM32传感器用了红外原理的PM2.5模块。这个组合在DIY圈子里很常见但真正把它调稳、调准坑比想象中多。网上关于激光PM2.5传感器的教程一抓一大把反而红外传感器的细节很少有人讲透很多朋友照着激光传感器的思路接红外模块数据飘得没法看回头还以为是传感器坏了。这篇就把我自己的完整做法和踩坑记录整理出来从选型理由、硬件接线、PWM驱动时序到ADC采样和软件滤波全部摊开讲。咱不搞那种复制粘贴的教程只聊我实际验证过的东西。1. 方案选型为什么用红外传感器又为什么选STM321.1 红外PM2.5传感器到底是个什么原理PM2.5传感器的主流方案有两种红外散射和激光散射。红外传感器的核心结构其实很简单里面有一个红外发光二极管和一个光电二极管空气从中间的通道流过当颗粒物经过红外光束时会把光散射到光电二极管上颗粒物浓度越高散射光就越强输出信号就越明显。很多朋友一听红外就觉得低端这个观念要纠正一下。红外方案测的是相对浓度精度确实不如激光但它的优势是成本极低、功耗小、寿命长用在室内空气质量趋势监测、新风系统联动、净化器滤芯寿命提醒这类场景完全够用。激光传感器动不动就上百块红外模块十几块钱就能拿到手做产品原型验证或者学生项目红外方案是性价比最高的起点。我用的这颗是典型的模拟输出型红外灰尘传感器工作电压5V静态功耗只有20mA上下。它有两个关键引脚一个LED驱动控制脚一个模拟信号输出脚。前者必须由MCU输出PWM脉冲来驱动内部红外LED后者输出和粉尘浓度成正比的模拟电压也就是需要STM32的ADC去读取。1.2 为什么控制核心选了STM32说到控制核心用STM32来处理这颗传感器有几个实在的理由。首先这颗红外传感器需要PWM驱动而且对脉冲时序有严格要求——不是随便给个PWM就行这个时序要求会在后面专门讲。STM32的定时器PWM输出加ADC定时采样这套组合在单片机阵营里是教科书级的组合拳资料多、例子全出问题排查起来省力。其次STM32的ADC是12位的分辨率比Arduino的10位高出一截。红外传感器的输出电压范围大概在0.5V到3.6V之间对应粉尘浓度0到500微克每立方米如果用10位ADC分辨率大概是4.9毫伏每单位换算成浓度大约能分辨出每立方米5微克的差异。换成STM32的12位ADC参考电压3.3V理论分辨率能做到0.8毫伏浓度分辨能力大概在每立方米1微克上下虽然传感器自身噪声达不到这么理想的水平但采样电路的底子打好总没坏处。再就是STM32的资源扩展性。空气质量监测一般不是单独一个传感器就行温度、湿度、OLED显示、串口上传、风扇控制这些外围设备都会陆续加上去STM32的引脚和外设资源足够兜底后续扩展不用换主控。我自己就是从单传感器开始逐步加了SHT30温湿度、OLED屏和ESP8266联网整套系统还运行在同一颗STM32F103上这在Arduino上就稍显捉襟见肘了。1.3 模拟输出和串口输出的传感器怎么选市面上红外PM2.5传感器模块大致分两类模拟输出和串口输出。模拟输出的代表就是经典的GP2Y1010AU系列需要接ADC。串口输出的模块往往内置了MCU把电压换算成浓度后直接按协议发出来比模拟版省心。但串口版有个问题很多模块的换算参数和校准系数是固化在模块里的你没法根据自己的应用场景调整。而且串口模块内部用的传感器探头和模拟版其实是一样的精度并没有本质提升价格倒是贵了一截。我建议学生项目或者想深入理解传感器原理的朋友直接用模拟输出的版本。自己掌握换算关系数据出了异常也能定位是哪一段的问题。我自己做产品原型时也是从模拟版开始后面有量产需求再评估串口版省软件开发工时。2. 硬件接线与采样电路设计2.1 引脚定义与接线表以我手里这颗GP2Y1010AU风格的模块为例标准引脚是6个VCC5V、LED引脚PWM驱动、LED-GND、GND、OUT模拟电压输出、还有一个空脚。有些厂家做的兼容模块引脚排列略有差异接线前一定先看模块背面的丝印。接线逻辑其实很清晰5V供电是硬要求因为红外LED需要5V驱动才能保证光强稳定LED引脚接STM32的定时器PWM输出通道OUT引脚接STM32的ADC输入引脚同时做好滤波和电平匹配。我用的参考接线是传感器引脚接STM32引脚备注VCC5V必须5V不能接3.3V光强会不足LEDPA1TIM2_CH2PWM输出频率100Hz占空比约0.32%LED-GNDGND和控制GND共地GNDGND共地必须接好否则读数噪声很大OUTPA4ADC1_IN4模拟输出接ADC串一个1k电阻保护这里有个容易忽略的细节LED引脚和LED-GND是两个独立的引脚不能直接合并接到GND或者VCC上必须通过PWM脉冲来控制LED的导通。部分模块把LED-GND和GND在内部已经连通了但保险起见还是分开接。2.2 模拟输出的电平匹配问题传感器OUT引脚的输出电压范围可能在0.5V到4.5V之间而STM32的ADC参考电压最高到3.3V取决于具体型号F103一般是3.3V。直接对接的话浓度高的时候输出电压超过3.3VADC直接削顶数据永远是满量程。解决方式有两种。一种是我用的电阻分压法两个电阻把输出电压按比例衰减。传感器最大输出电压按4.5V估计要衰减到3.3V以内选择R110k传感器输出端到ADC端R25.6kADC端到GND分压系数大概是5.6/(105.6)约等于0.36这样即使传感器输出4.5V到ADC也只有1.6V左右留了充足的裕量。注意分压比例定了之后后续做电压到浓度的换算时公式里的电压是ADC引脚电压要先还原成传感器原始输出电压再计算浓度这一步很多人会忘记。还有另一种方案是直接用运放做电平转换和缓冲对采样精度要求高的场景更合适。但普通室内监测场景电阻分压完全够用我用万用表实测过分压后的电压几乎不损失精度传感器的噪声本身就比分压电阻的误差大得多。2.3 关于ADC引脚的电容滤波ADC引脚要在硬件上做一下简单滤波。我直接在ADC引脚对地并联了一个0.1微法陶瓷电容滤除高频噪声。这个电容不是随便乱加的红外传感器的输出阻抗比较高加上STM32的ADC是开关电容结构采样瞬间会从外部电路抽取电荷如果没有电容储能采样值会偏低且不稳定。但电容也不能太大否则输出的建立时间变长PWM采样模式下会读到上一次的残余值。实测下来0.1微法在100Hz的采样节奏下表现最稳。如果你用的是连续采样模式可以考虑降到10nF具体以自己示波器看到的波形为准。3. 软件实现PWM驱动、ADC采样与数据处理3.1 红外传感器为什么必须用PWM脉冲驱动这个知识点是最多人在第一步就犯迷糊的地方。红外传感器的LED不能一直亮着必须在脉冲电流下工作典型时序是10毫秒的周期内LED导通0.32毫秒左右大约在脉冲开始后0.28毫秒时输出信号达到稳定值此时ADC采样窗口应该落在信号稳定区间内。换句话说整个采样节奏必须和PWM脉冲严格同步。传感器输出信号是一个随时间变化的模拟波形LED没亮的时候输出的是低电平基准LED亮起来的瞬间输出快速上升随后进入平台期这个平台期的电压值才是和粉尘浓度相关的有效信号。如果用连续采样模式去乱读可能采到峰值前的不稳区或者采到LED熄灭后的低电平区两种情况下数据都是错的而且错误模式还不是固定的这会让软件校准完全没法做。所以必须用STM32的定时器产生精确的PWM同时让ADC在特定时刻触发采样。3.2 STM32定时器PWM配置我用的芯片是STM32F103C8T6标准外设库定时器用TIM2PWM输出到PA1通道。配置步骤分成几部分时钟使能、GPIO配置、定时器时基、输出比较模式、PWM占空比。直接上代码详细注释都写在里面了void PWM_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; // 使能TIM2和GPIOA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // PA1配置为复用推挽输出用于TIM2_CH2 GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 定时器时基配置72MHz分频后得到0.1MHz计数频率 TIM_TimeBaseStructure.TIM_Period 1000 - 1; // 自动重装载值1000个计数周期 TIM_TimeBaseStructure.TIM_Prescaler 720 - 1; // 预分频72MHz/720100kHz TIM_TimeBaseStructure.TIM_ClockDivision TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode TIM_CounterMode_Up; TIM_TimeBaseInit(TIM2, TIM_TimeBaseStructure); // PWM模式配置输出比较模式1计数小于比较值时输出有效电平 TIM_OCInitStructure.TIM_OCMode TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse 320; // 占空比320/1000 0.32% TIM_OCInitStructure.TIM_OCPolarity TIM_OCPolarity_High; TIM_OC2Init(TIM2, TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); TIM_ARRPreloadConfig(TIM2, ENABLE); TIM_Cmd(TIM2, ENABLE); }这里几个关键数值说一下。预分频720分频是因为STM32F103的系统时钟是72MHz720分频后计数频率是100kHz也就是每个计数周期10微秒。自动重装载值设为1000所以整个PWM周期是1000个计数周期也就是10毫秒正好对应100Hz的PWM频率符合传感器数据手册的要求。Pulse值设为320意味着在1000个计数周期里高电平持续320个计数周期即3.2毫秒。等一下这里要仔细核一下我实际用的传感器数据手册给的是0.32毫秒脉宽也就是32个计数周期Pulse应该设为32不是320。上面代码里如果Pulse320脉宽就到3.2毫秒了超了十倍传感器虽然不会烧因为还有内部限流但采样时序就乱了。实际应该设为Pulse 32对应320微秒脉宽。这点必须提醒我在调试时踩过这个坑把Pulse从32调到320试过一次数据倒是也能采出来但校准曲线整个偏移最后查数据手册才发现脉宽超了。3.3 ADC采样时序与触发设置PWM配置好了只解决驱动LED按正确时序闪烁的问题接下来是在正确的时间点采样。这段是红外传感器项目里最核心的时序设计。传感器输出电压在LED开启后约0.28毫秒进入稳定区而整个脉冲周期是10毫秒也就是在PWM上升沿后要等280微秒再采样。用STM32自带的定时器触发ADC功能可以实现精确同步但有个更简单的方案直接用定时器更新事件触发中断在中断里延时280微秒后再启动ADC转换。我最终用的就是这么干的代码如下void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) ! RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 延时约280us等待传感器输出进入稳定区 Delay_us(280); // 启动ADC转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); } }中断每次触发时STM32会暂停主循环里其他任务约280微秒这个时间非常短对温湿度读取、OLED刷新这类低速外设没有明显影响。如果你在主循环里还要做复杂的浮点运算或者跑实时系统那就建议换用定时器触发ADC的硬件链路让ADC自己定时启动完全不占CPU。但对F103级别的裸机应用来说中断延时采样是最简单可靠的方案。ADC配置代码标准库写法void ADC_InitConfig(void) { GPIO_InitTypeDef GPIO_InitStructure; ADC_InitTypeDef ADC_InitStructure; // PA4作为模拟输入 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AIN; GPIO_Init(GPIOA, GPIO_InitStructure); ADC_InitStructure.ADC_Mode ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode DISABLE; ADC_InitStructure.ADC_ContinuousConvMode DISABLE; ADC_InitStructure.ADC_ExternalTrigConv ADC_ExternalTrigConv_None; // 软件触发 ADC_InitStructure.ADC_DataAlign ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel 1; ADC_Init(ADC1, ADC_InitStructure); // 采样时间设置为55.5周期对应约771ns足够让传感器输出信号稳定 ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_55Cycles5); ADC_Cmd(ADC1, ENABLE); // 校准ADC ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); }其中采样周期选55.5个ADC时钟周期。ADC时钟由APB2时钟分频而来F103上是12MHz55.5周期换算下来大约4.6微秒的采样时间对于输出阻抗较高的传感器信号来说这个采样时间能保证内部采样电容充分充电。如果用的是更快的采样周期如1.5周期结果可能会偏低几个LSB测试时反复对比过55.5周期是最稳的。3.4 电压值换算成PM2.5浓度数据手册给的换算关系是线性近似的输出电压0.5V对应0微克每立方米电压每升高0.5V浓度增加约100微克每立方米。但注意这个近似只适用于中低浓度区间浓度超过300微克每立方米后传感器响应会明显变缓实际读数和线性公式的偏差会越来越大。我的处理方式是区分两段做线性转换。ADC读到的原始值是12位先换算成ADC引脚实际电压float adc_value ADC_GetConversionValue(ADC1); float volt_at_pin adc_value * 3.3f / 4096.0f;然后还原传感器真实输出电压因为前面做了分压分压系数是0.36所以真实电压为volt_sensor volt_at_pin / 0.36。最后再用两段线性公式float concentration; float volt_sensor volt_at_pin / 0.36f; if (volt_sensor 1.0f) { concentration (volt_sensor - 0.5f) * 200.0f; } else { concentration (volt_sensor - 0.9f) * 250.0f; }这个分段公式是我自己根据手里这颗传感器的实测曲线拟合的不同厂家、不同批次会有差异。这里提醒一句千万别迷信网上找的任何现成公式一定要用标准粉尘源或者和可信的参考传感器做对比确认自己手里这颗的实际响应特性。最简单的对比方法放一台激光PM2.5检测仪在旁边同时测量同一个环境通过串口把两组数据打出来一点点修正你自己的换算系数。3.5 软件滤波为什么红外传感器数据必须做滤波红外传感器最让人头疼的就是信号噪声。因为颗粒物的散射本质上是随机事件落在光电二极管上的光强会有明显的随机波动直接读出来的瞬时浓度值上蹿下跳大的时候上下能差到三四十微克每立方米。解决办法是软件滤波。我用的是滑动平均中值滤波的组合方式。中值滤波先去掉异常值滑动平均再做平滑。具体实现思路每100毫秒采集一次有效电压值10Hz采样率缓存最近10个数据点先取中位数剔除离群值再对中位数序列做5点滑动平均。代码示意#define FILTER_BUFFER_SIZE 10 float filter_buffer[FILTER_BUFFER_SIZE]; uint8_t filter_index 0; float MedianFilter(float new_value) { float temp[FILTER_BUFFER_SIZE]; float sorted[FILTER_BUFFER_SIZE]; uint8_t i, j; filter_buffer[filter_index] new_value; filter_index (filter_index 1) % FILTER_BUFFER_SIZE; // 拷贝到临时数组排序 for (i 0; i FILTER_BUFFER_SIZE; i) { temp[i] filter_buffer[i]; } for (i 0; i FILTER_BUFFER_SIZE - 1; i) { for (j i 1; j FILTER_BUFFER_SIZE; j) { if (temp[i] temp[j]) { float t temp[i]; temp[i] temp[j]; temp[j] t; } } } return temp[FILTER_BUFFER_SIZE / 2]; }采样频率的选择也要说一下。采样太快两次采样之间浓度几乎没变化滤波效果不明显还白白占用CPU采样太慢响应速度跟不上PM2.5浓度突然升高时读数反应迟钝。10Hz是个折中的选择既保证1秒能刷新5次显示数据又不会让主循环卡顿。滤波后的数据再滚动更新一个1秒平均值作为最终显示数据。实际测试下来最终读数在室外稳定环境下波动能控制在正负5微克每立方米以内效果很理想。4. 串口输出与数据可视化4.1 串口打印与上位机显示调试阶段数据要能直观地看我用的是USART1PA9和PA10波特率115200。STM32F103没有USB收发器必须通过USB转TTL模块接到电脑。串口输出格式我用的是JSON风格方便调试助手直接解析显示printf({\pm25\:%.1f,\raw\:%.3f,\volt\:%.2f}\r\n, filtered_pm25, raw_adc_value, volt_sensor);注意STM32用printf必须先重定向fputc函数否则输出全跑到奇怪的死循环里去了。这里是我经常看到新手卡壳的地方重定向时注意保留原函数声明别把项目里其他地方用到printf的代码给连累挂掉。串口助手选什么不重要能显示文本波形都行。如果想更直观直接把串口数据接到Python脚本里用matplotlib实时画曲线也是个非常顺手的调试方式。数据格式固定了之后上位机怎么写都有同样的解析逻辑。4.2 数据波形观察与调参技巧在调试滤波参数的时候手里有个可视化的曲线图能省一大半时间。我是这样做的串口发出来的数据用Python的pyserial库读取然后matplotlib实时画曲线一张图上同时画原始值和滤波后的值。肉眼观察曲线的意义在于能很快判断滤波强度是否合适。滤波太强曲线像一条直直的线外界浓度突变后好几秒才反应表现为迟钝滤波太弱曲线毛刺多根本看不清趋势。调滑动窗口大小时我的经验是从小到大试直到噪声幅度被压到可接受范围又保留明显突变响应为止。这个可接受范围对室内监测设备来说目标通常是不超过正负10微克每立方米。还有个小技巧观察滤波后的曲线如果出现周期性尖峰大概率不是传感器噪声而是电源上叠加了周期性纹波。这时候查查是不是PWM驱动线太长和模拟输出线并行走线引入了串扰或者5V电源本身有开关纹波。我用稳压模块单独给传感器供电后尖峰立刻消失了。5. 常见问题与排查技巧5.1 读数一直很高/很低先排除接线问题。LED引脚如果没接PWM而是直接接了高电平传感器会过流或者输出异常读数通常飙升到满量程如果OUT引脚悬空ADC读到的是不确定值可能高也可能低。排除接线后用万用表测LED引脚应该有100Hz方波幅值接近3.3V。如果没有方波查定时器是否真的启动了很多人的问题是只调用了初始化函数没有调用TIM_Cmd使能定时器。再不然就是分压电路的问题。分压电阻虚焊、用错阻值或者接到了3.3V而不是5V供电都会导致读数偏小。先测量分压后的电压正常情况下呼吸一口烟对着传感器电压应该有明显变化。5.2 数据波动特别大这个大概率是滤波没上或者采样时序没对齐。如果在PWM脉冲不稳定区间采样噪声大得离谱。确认中断里延时280微秒是否生效我用逻辑分析仪看过延时不精确会导致采样点落在信号上升沿数据从低到高乱跳。另一个容易忽略的问题是共地。传感器和STM32如果不共地OUT引脚的电压参考点和ADC的参考点不在同一电位读数就会随电位差漂移。检查传感器GND和STM32 GND是否在同一根线上尤其当电源是两路输出时必须确保共地。5.3 很多项目能用但数据不可信最隐蔽的问题是很多人做到有数据就收工了。红外传感器不做校准的话它反映的是颗粒物浓度的相对变化而不是绝对数值。自己实验练手可以但如果你要做一期比较严肃的测量对比或者毕设数据建议至少要有一台参考设备做交叉验证。我自己的做法是借用朋友的一台激光PM2.5检测仪同时测试数据通过线性回归修正系数修正后两组数据的相关系数能到0.95以上。另外红外传感器在湿度很高的环境比如浴室、雾天会受到水汽散射的干扰数据明显偏高。这是我调试时的一个意外发现后来查资料确认了水汽对红外光的散射效应比可见光更明显。如果设备可能在高湿环境下使用需要加湿度补偿或者干脆在数据处理时屏蔽掉湿度超过阈值的读数。5.4 快速自查速查表把排查过程整理成一张速查表放到调试现场对照能少走不少弯路现象可能原因排查与解决ADC读数一直是0OUT引脚没接对、ADC使能没开测引脚电平检查ADC_Cmd函数是否调用读数接近满量程分压电阻问题、LED直通高电平先查LED引脚是否有PWM再查分压点电压数据剧烈乱跳采样时序不对、滤波缺失用逻辑分析仪查采样点位置确认280us延时数据周期性尖峰电源纹波、PWM串扰传感器单独供电模拟线远离PWM线读数长期偏低供电不足、分压系数计算错误万用表实测5V是否达到复核分压比响应特别慢滑动窗口太大缩小滑动窗或者提高采样频率写在最后的小经验踩过几次坑之后我对这种工程细节的体会是红外PM2.5传感器本身不复杂难度全在时序和采样这两件小事上。把PWM脉宽算准采样时机调对滤波做扎实这套方案做出来的数据其实相当能打。我后来在STM32F103上把这套传感器跑进了空气质量监测小盒子配合OLED屏滚动显示效果稳定功耗也低。如果你手里正好有吃灰的STM32最小系统板花十几块钱买个红外粉尘模块按这个思路搭建一遍应该会有不少收获。
企业数字化 ERP 产品动态
相关推荐
为DeepSeek Harness集成持久化代码记忆层 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:44:55
企业战略思维重构与数据驱动决策实践 1. 专知智库:企业战略思维的破局者在成都高新区的一栋写字楼里,每周都有来自全国各地的企业家带着相似的困惑走进专知智库的会议室:"我们投入了大量资源,为什么增长依然乏力?"、"市场变化太快ÿ… · 2026/9/25 4:44:49
传统车企数字化转型:核心战场与实施策略 1. 传统车企数字化转型的必然选择十年前走进汽车工厂,你会看到流水线上密密麻麻的工人手持工具装配零件;如今再到现代化车间,机械臂的舞蹈取代了人工作业,数据看板实时跳动着生产指标。这种转变背后,是传统制造业正在经… · 2026/9/25 4:44:49
cube-ui Input 输入框组件完整指南:v-model 双向绑定、清空按钮与密码眼睛实战解析 前端UI组件移动开发 【免费下载链接】cube-ui :large_orange_diamond: A fantastic mobile ui lib implement by Vue 项目地址: https://gitcode.com/gh_mirrors/cu/cube-ui 点击查看 免费下载 导读
本文基于 cube-ui 官方中文文档 input.md 并结合仓库源码&#… · 2026/9/25 5:17:57
ESP32-S3麦克风阵列实战:波束成形与回声消除全解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 5:17:51
GraphQL Java 后端接入 MongoDB:Connectors 连接器实战与 N+1 查询优化 【免费下载链接】howtographql The Fullstack Tutorial for GraphQL 项目地址: https://gitcode.com/gh_mirrors/ho/howtographql 点击查看 免费下载 本篇指南基于 HowToGraphQL 开源仓库中的 graphql-java 教程 连接器章节 展开,讲解如何为基于 graph… · 2026/9/25 5:17:44
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37