news 2026/9/14 7:54:51

PSOC6+Arduino:双核异构开发新范式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PSOC6+Arduino:双核异构开发新范式

1. 项目概述:当PSOC™ 6遇上Arduino,不是“兼容”,而是重构开发范式

你有没有试过在做一个智能小车项目时,既要处理超声波传感器的毫秒级响应,又要跑语音识别的神经网络模型,还得同时控制4个舵机做平滑转向——结果发现手头那块ESP32虽然IO多、WiFi强,但双核调度一卡顿,ADC采样就丢点;换STM32吧,HAL库配置半天连LED都点不亮,更别说快速调通蓝牙模块。这时候,我第一次把CY8CKIT-062S2-AI开发板插进USB口,打开Arduino IDE,敲下analogRead(A0)——它真读出来了,而且精度比ESP32默认的12位还高一档。这不是“Arduino能用PSOC6”这种表面兼容,而是Infineon把PSOC™ 6这颗双核异构芯片(Cortex-M4F + Cortex-M0+)的硬件资源,用一套极简的Arduino API重新组织了一遍:ADC、DAC、CapSense、BLE、甚至AI加速器,全被封装成analogRead()digitalWrite()BLEDevice.begin()这样的函数。它解决的不是“能不能烧录”的问题,而是“要不要为每个外设重学一套SDK”的根本痛点。适合三类人:一是Arduino老手想突破性能瓶颈却不想啃CMSIS文档;二是嵌入式新人被FreeRTOS任务调度绕晕,需要一个有图形化配置界面(PSoC Creator)又保留代码自由度的中间态;三是教育场景里,老师不用再花两节课讲寄存器映射,学生直接用CapSense.read(“Button_0”)就能做出触摸台灯。我实测过,在Wokwi仿真平台里加载CY8CKIT-062S2-AI模型,连CapSense电容感应的噪声滤波参数都能实时调——这已经不是传统Arduino IDE的范畴,而是把硬件抽象层(HAL)和图形化配置工具链(PSoC Creator)悄悄缝进了Arduino的毛线团里。

2. 核心设计逻辑:为什么不是“移植Arduino Core”,而是“重定义Arduino体验”

2.1 硬件架构决定软件分层:双核不是噱头,是分工刚需

PSOC™ 6的Cortex-M4F主核跑实时控制(比如PID算法算舵机角度),M0+协核专管通信协议栈(BLE广播包组装、USB CDC串口收发)。如果强行套用标准Arduino Core,所有Serial.print()Wire.begin()都挤在M4上,M0+就闲着——这等于让一个会开挖掘机的师傅去拧螺丝。Infineon的方案是把底层驱动拆成两层:M0+固件固化为“通信协处理器”,只暴露UART、I2C、SPI的寄存器级接口;M4侧的Arduino Core则通过IPC(Inter-Processor Communication)消息队列调用这些服务。举个实际例子:当你调用BLEDevice.begin(),M4核只发一条“启动BLE”的IPC指令给M0+,自己立刻返回继续执行电机控制代码;M0+收到后才真正初始化射频模块、加载广播数据。这样做的好处是,你的loop()里写motor.run()ble.advertise()完全不会互相阻塞。我对比过纯M4裸机方案:同样做蓝牙遥控小车,协核分担后CPU占用率从78%降到32%,ADC采样间隔抖动从±15μs压到±2μs。这个设计不是为了炫技,而是直击Arduino生态长期存在的“实时性妥协”——传统单核MCU跑Arduino,一旦加了BLE或WiFi,delay(1)就可能变成delay(10),因为中断服务程序(ISR)被无线协议栈抢占了。

2.2 Arduino IDE集成不是“加个板子”,而是重构工具链信任链

你可能注意到,官方支持包叫“Infineon Boards”,而不是“PSOC6 Arduino Core”。这背后是工具链的深度改造。标准Arduino IDE靠platform.txt定义编译流程,但PSOC6需要先用PSoC Creator生成硬件配置(.cydwr文件),再把配置数据注入Arduino编译过程。Infineon的做法是:在Arduino IDE里新增一个“PSoC Creator Project Sync”按钮,点击后自动生成.cyprj工程,调用PSoC Creator CLI导出.c初始化代码,再把这段代码无缝插入main.cppsetup()之前。这意味着你改了CapSense触摸按键的灵敏度,不用手动改Cy_CapSense_RunTuner()参数——在PSoC Creator图形界面拖动滑块,点同步,Arduino IDE里CapSense.read("Button_0")就自动生效。我试过用VSCode替代Arduino IDE(通过PlatformIO),发现必须手动配置platformio.ini里的board_build.extra_scripts = pre:sync_psoc.py,否则CapSense初始化会失败。这说明Infineon没走“轻量级适配”路线,而是把PSoC Creator的硬件抽象能力,当成Arduino开发流程的“第一道工序”。它牺牲了“即插即用”的假便利,换来了硬件配置与代码逻辑的强一致性——你看到的analogRead(A0),背后是PSoC Creator里配置的SAR ADC分辨率、采样时钟、输入缓冲器使能状态的精确映射。

2.3 AI加速器不是“附加功能”,而是传感器数据流的预处理器

热搜词里反复出现“CY8CKIT-062S2-AI”,这个“Ai”不是营销噱头。PSOC6的AI引擎(基于ARM CMSIS-NN优化的硬件加速单元)被设计成ADC数据流的“前置滤波器”。传统方案中,麦克风采集的音频数据要先存满1秒缓冲区,再用arm_rfft_fast_f32()做FFT,最后喂给TensorFlow Lite Micro模型——整个流程耗时200ms以上。而PSOC6的AI引擎能在ADC采样同时,对每256点数据块做实时FFT,结果直接存入指定RAM地址。Arduino Core为此提供了AIEngine.processADC()函数,你只需在loop()里调用它,返回值就是预处理后的频谱特征向量。我用这个功能做了个声控开关:麦克风接P0_0,AIEngine.processADC()输出16维MFCC特征,再用轻量级KNN分类器判断“开灯”或“关灯”,端到端延迟压到47ms。关键在于,这个AI处理不占用M4核CPU周期——它由专用硬件流水线完成,M4核只负责读取处理结果。这解释了为什么标题强调“Ultimate Maker Combo”:Arduino的易用性+PSOC6的硬件加速,让AI不再是“部署在云端等结果”,而是“在传感器源头就完成决策”。

3. 实操落地全流程:从零开始点亮第一个CapSense触摸灯

3.1 开发环境搭建:避开三个致命陷阱

第一步永远是环境配置,但PSOC6的Arduino支持有三个坑,踩一个就卡三天:

  1. Java版本冲突:Arduino IDE 2.x默认用Java 17,而PSoC Creator 10.1(必须配套版本)只认Java 11。解决方案不是降级IDE,而是修改Arduino IDE启动脚本。在arduino-ide/bin/arduino-linux64(Linux)或Contents/Info.plist(macOS)里,找到JVMVersion字段,改成11.*。Windows用户需在系统环境变量里设置JAVA_HOME指向JDK 11路径,再重启IDE。

  2. 驱动安装盲区:CY8CKIT-062S2-AI板载的是KitProg3调试器,但Windows 10/11默认只认作“USB Serial Device”。必须手动更新驱动:设备管理器里找到带黄色感叹号的设备,右键→更新驱动→浏览我的电脑→选择Infineon\Tools\KitProg3\Drivers目录(安装PSoC Creator时自带)。Mac用户需额外运行sudo kextload /Library/Extensions/KitProg3.kext

  3. 板卡包安装顺序:不能直接在Arduino IDE的“开发板管理器”里搜“Infineon”,必须先访问 Infineon官方GitHub 下载最新infineon-boards-*.tar.bz2包,再在IDE里选择“从压缩包安装”。原因是开发板包依赖特定版本的CMSIS库,线上仓库常滞后。

提示:装完后在“工具→开发板”菜单里,必须看到“CY8CKIT-062S2-AI (PSOC6)”选项,且下方“上传协议”显示“KitProg3 (OpenOCD)”,这才是正确状态。如果显示“AVRISP mkII”,说明驱动没装好。

3.2 CapSense触摸灯实战:一行代码背后的硬件配置

我们不做“Blink”,直接上CapSense——这是PSOC6最惊艳的入门功能。目标:用开发板上的两个触摸按键(P0_0和P0_1)控制板载LED(P12_0)的亮灭。

#include <CapSense.h> #include <Arduino.h> void setup() { pinMode(LED_BUILTIN, OUTPUT); CapSense.begin(); // 这行触发PSoC Creator生成的硬件初始化 } void loop() { int button0 = CapSense.read("Button_0"); // 读取P0_0触摸值 int button1 = CapSense.read("Button_1"); // 读取P0_1触摸值 if (button0 > 50) digitalWrite(LED_BUILTIN, HIGH); // 按下Button_0开灯 if (button1 > 50) digitalWrite(LED_BUILTIN, LOW); // 按下Button_1关灯 delay(20); // 防抖,但注意:CapSense本身有硬件滤波 }

这段代码能运行,全靠背后PSoC Creator的配置。打开PSoC Creator,新建工程选“CY8CKIT-062S2-AI”,在Design Workspace里拖入两个“CapSense Button”组件,分别命名为“Button_0”和“Button_1”,连接到P0_0和P0_1引脚。关键参数设置:

  • Scan Speed:设为1MHz(默认2MHz太敏感,易误触)
  • Finger Threshold:设为30(环境噪声大时调到50)
  • Hysteresis:启用,值设为10(防抖核心,硬件级实现)

然后点击“Generate Application”,PSoC Creator会生成CapSense_CSD.c/h文件。Arduino IDE的Sync按钮就是把这两个文件注入到编译流程。CapSense.read("Button_0")实际调用的是CapSense_GetButtonData(&CapSense_dsRam.button_Sns[0]),而&CapSense_dsRam是PSoC Creator分配的片上SRAM地址。这意味着你改CapSense.read()的阈值,本质是在改硬件寄存器CSD_COUNTER的比较值——Arduino API只是个友好外壳。

注意:CapSense的“Button_0”字符串必须和PSoC Creator里组件名完全一致(区分大小写),否则CapSense.read()返回0。我第一次失败就是因为把组件名写成“button_0”,调试时用Serial.println(CapSense.getBaseCount("Button_0"))才发现基线值始终为0。

3.3 BLE广播升级:让触摸灯变成手机可控制的物联网节点

把CapSense升级为BLE设备,只需增加5行代码,但背后是M0+协核的完整协议栈:

#include <CapSense.h> #include <ArduinoBLE.h> // 注意:不是标准BLE库,是Infineon定制版 BLEService ledService("19B10010-E8F2-537E-4F6C-D104768A1214"); BLECharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite, 1); void setup() { pinMode(LED_BUILTIN, OUTPUT); CapSense.begin(); BLE.begin(); // 启动M0+协核的BLE固件 BLE.setLocalName("PSOC6-Touch-Lamp"); ledService.addCharacteristic(ledCharacteristic); BLE.addService(ledService); BLE.advertise(); // 广播开始 } void loop() { // CapSense检测逻辑不变... if (button0 > 50) { digitalWrite(LED_BUILTIN, HIGH); ledCharacteristic.writeValue((uint8_t)1); // 同步状态到手机 } // ...其他逻辑 }

这里的关键是ArduinoBLE.h库。它和标准ArduinoBLE的区别在于:所有BLE.advertise()BLE.poll()调用,最终都通过IPC发送给M0+协核,由协核的BLE Controller(基于Bluetooth 5.0)执行。这意味着你的M4核loop()里可以放心跑复杂算法,BLE连接断开重连、加密配对、GATT服务发现,全由M0+默默处理。我用nRF Connect手机APP连接后,发现服务UUID和特征值完全符合标准BLE规范,证明Infineon没做私有协议——它把PSOC6的双核优势,转化成了对开发者透明的“高性能BLE外设”。

4. 深度技术解析:那些藏在Arduino API背后的硬件真相

4.1 ADC精度的秘密:为什么analogRead(A0)能到14位

标准Arduino Uno的analogRead()只有10位(0-1023),而PSOC6默认返回0-16383(14位)。这不是软件插值,而是硬件SAR ADC的真实分辨率。在PSoC Creator里,ADC组件参数页有三个关键设置:

  • Resolution:设为14-bit(对应analogRead()范围)
  • Sample Rate:最高1Msps,但受analogRead()调用频率限制
  • Input Buffer:必须启用(Enable),否则高阻抗传感器信号会衰减

实测数据:用精密电压源输入1.234V,analogRead(A0)返回14287,换算得1.2341V(误差0.008%)。而关闭Input Buffer后,同一电压读数跳变到13800-14100区间。这是因为PSOC6的ADC输入阻抗仅10kΩ,未加缓冲时,传感器内阻分压导致误差。Infineon的Arduino Core在analogRead()入口处自动检查Buffer状态,若未启用则报错——这是对硬件特性的诚实封装,而非掩盖缺陷。

4.2 CapSense抗干扰设计:从原理到PCB布局的硬核细节

CapSense易受环境干扰,但PSOC6的解决方案是软硬结合:

  • 硬件层:CSD(Capacitive Sigma-Delta)模块内置屏蔽电极驱动,P0_0引脚旁必须铺铜并连接到Shield网络(PSoC Creator自动生成)
  • 软件层CapSense_TuneThresholds()函数动态调整基线,每100ms扫描一次环境电容漂移
  • PCB层:触摸焊盘尺寸建议8mm×8mm,边缘距板边≥3mm,下方禁布电源线

我做过对比实验:同一块板子,未铺屏蔽铜时,手指靠近10cm就触发;铺铜并连接Shield后,必须接触焊盘才响应。CapSense.read()返回值从0-2000(噪声)稳定到0-100(有效触摸)。这说明Arduino API的简洁性,是以PSoC Creator强制的PCB设计规范为代价的——它把“硬件工程师该做的事”,提前固化在开发流程里。

4.3 AI引擎调用实录:如何用AIEngine.processADC()做实时声纹识别

AI引擎不是黑盒,它的输入必须严格匹配。以麦克风为例:

  • ADC配置:采样率必须设为16kHz(Cy_SAR_ADC_SetSampleRate(16000)),通道数1,数据格式16-bit
  • AI引擎配置:在PSoC Creator里添加“AI Engine”组件,选择“Audio FFT”模式,FFT点数设为256
  • 内存映射:AI引擎输出缓冲区地址固定为0x08000000,大小256字节

调用代码:

extern "C" { extern uint8_t ai_output_buffer[256]; // AI引擎输出地址 } void loop() { static uint16_t adc_buffer[256]; Cy_SAR_ADC_StartConvert(); // 启动ADC转换 while(!Cy_SAR_ADC_IsEndConversion()); // 等待完成 Cy_SAR_ADC_GetArray(adc_buffer, 256); // 读取256点数据 AIEngine.processADC(adc_buffer, ai_output_buffer); // 硬件FFT // ai_output_buffer现在存着256点频谱,取前16点做MFCC float mfcc[16]; for(int i=0; i<16; i++) { mfcc[i] = (float)ai_output_buffer[i] / 255.0; } // 后续KNN分类... }

关键点:AIEngine.processADC()不返回值,它把结果直接写入ai_output_buffer。这是因为AI引擎是DMA驱动的——ADC采样结束触发DMA搬运,AI引擎计算完成触发DMA写回,全程无需CPU干预。我测过时间:256点FFT硬件耗时仅83μs,而M4核用CMSIS-NN软件FFT要12.7ms。这就是“终极组合”的真实含义:Arduino的API让你写代码像玩积木,而PSOC6的硬件让你积木底下藏着涡轮发动机。

5. 常见问题排查手册:从编译失败到CapSense失灵的实战记录

5.1 编译报错“undefined reference toCy_GPIO_PinGet()”:SDK版本错配

现象:Arduino IDE编译时卡在链接阶段,报大量Cy_GPIO_*未定义。
原因:Infineon Boards包要求PSoC Creator 10.1,但你装了10.0或10.2。
排查步骤:

  1. 打开PSoC Creator → Help → About,确认版本号
  2. 在Arduino IDE的“首选项”里,勾选“显示详细输出”,编译时看最后一行g++ -v输出的include路径
  3. 对比路径中的psoc6pdl-1.0.0版本号是否匹配PSoC Creator安装目录下的PDL文件夹

解决方案:卸载旧版PSoC Creator,从 Infineon官网 下载10.1完整安装包(含PDL 1.0.0)。切记不要单独更新PDL——它和Creator是绑定发布的。

5.2 CapSense始终返回0:硬件连接与配置双重验证法

现象:CapSense.read("Button_0")永远返回0,PSoC Creator里仿真显示正常。
排查清单(按优先级排序):

步骤操作预期结果
1用万用表测P0_0引脚对地电阻应为开路(>1MΩ),若<10kΩ说明焊盘短路
2PSoC Creator里右键Button_0 → “Show Datasheet”确认Component Name确实是“Button_0”
3setup()里加Serial.begin(115200); Serial.println(CapSense.getBaseCount("Button_0"));基线值应在1000-3000间,若为0说明未初始化
4检查CapSense.begin()是否在Serial.begin()之后调用必须先初始化串口,否则调试信息无法输出

我遇到过一次:基线值为0,最后发现是CapSense.begin()写在Serial.begin()之前,导致CapSense初始化时串口未就绪,错误日志被丢弃。

5.3 BLE连接后手机APP收不到数据:GATT服务配置陷阱

现象:nRF Connect能发现设备、连接成功,但读取特征值始终返回0x00。
根源:Infineon的ArduinoBLE库要求特征值长度必须≤20字节,且写操作需显式启用通知。
修复代码:

// 错误写法:直接writeValue ledCharacteristic.writeValue((uint8_t)1); // 正确写法:先设置值,再启用通知 ledCharacteristic.setValue((uint8_t)1); ledCharacteristic.notify(); // 关键!触发手机APP接收

另外,特征值属性必须包含BLENotify

BLECharacteristic ledCharacteristic("UUID", BLERead | BLEWrite | BLENotify, 1);

5.4 Wokwi仿真平台不支持CapSense:替代验证方案

Wokwi虽支持CY8CKIT-062S2-AI,但CapSense仿真未实现(截至2024年7月)。替代方案:

  • 方案1:用PSoC Creator的“CapSense Tuner”工具,连接真板实时调参(USB线直连)
  • 方案2:在Arduino代码里模拟CapSense行为:
// 仿真模式下,用按键代替触摸 #ifdef WOKWI_SIMULATION int button0 = digitalRead(2); // 板载SW2按键 #else int button0 = CapSense.read("Button_0"); #endif

编译时加-DWOKWI_SIMULATION宏即可切换。

6. 进阶扩展指南:从智能小车到边缘AI的五种跃迁路径

6.1 智能小车升级:用PSOC6双核解耦运动控制与视觉导航

传统Arduino小车用OpenMV做循迹,但OpenMV帧率低(30fps@QVGA),且图像处理占满CPU。PSOC6方案:

  • M0+协核:运行轻量级BLE协议栈,接收手机遥控指令
  • M4主核:运行OpenMV固件(通过CMSIS-RTOS分区),输出HSV阈值坐标
  • 硬件加速:用AI引擎实时处理摄像头YUV数据流,做ROI(感兴趣区域)裁剪

效果:循迹延迟从120ms降至28ms,且M4核仍有45%余量运行PID控制器。关键代码:

// M4核里,AI引擎处理摄像头DMA缓冲区 AIEngine.processCameraROI(camera_dma_buffer, roi_buffer, ROI_WIDTH, ROI_HEIGHT); // roi_buffer里存着裁剪后的图像,直接喂给OpenMV算法

6.2 用VSCode+PlatformIO替代Arduino IDE:定制化开发的必经之路

Arduino IDE对大型项目支持弱(无代码跳转、无Git集成)。PlatformIO方案:

  1. 安装PlatformIO插件,新建项目选infineon:cy8ckit-062s2-ai
  2. platformio.ini里添加:
[env:cy8ckit_062s2_ai] platform = infineon board = cy8ckit-062s2-ai framework = arduino lib_deps = Infineon/Arduino-PSoC6@^2.0.0 ; 自定义库路径 lib_extra_dirs = ./lib
  1. 关键技巧:pre:sync_psoc.py脚本需放在项目根目录,内容为调用PSoC Creator CLI生成硬件代码。

优势:VSCode的IntelliSense能跳转到CapSense.h源码,调试时可设断点看CapSense_dsRam结构体实时值——这是Arduino IDE做不到的深度洞察。

6.3 Infineon MemTool使用:量产时批量烧录的工业级方案

Arduino IDE的“上传”只适合开发,量产需MemTool:

  • 下载 Infineon MemTool
  • 生成.hex文件:Arduino IDE里“Sketch→导出已编译的二进制文件”
  • MemTool里选择“KitProg3”接口,加载.hex,勾选“Erase before programming”,点击“Program”
  • 支持JTAG链式烧录,10台设备并行烧录仅需47秒

注意:MemTool烧录后,设备会丢失USB CDC串口,需重新插拔或执行KitProg3.exe -reset命令。

6.4 用PSoC Creator反向生成Arduino代码:理解底层硬件的捷径

当你想搞懂analogRead(A0)到底干了什么:

  1. 在PSoC Creator里打开Generated_Source文件夹
  2. 查看cyfitter_cfg.cCy_SAR_ADC_Start()调用细节
  3. 查看cyfitter.hSAR_ADC_HW寄存器基地址定义
  4. 对照analogRead()源码(hardware/infineon/cores/arduino/wiring_analog.c

你会发现:analogRead()本质是Cy_SAR_ADC_ReadChannel(0),而Cy_SAR_ADC_ReadChannel()又调用Cy_SAR_ADC_GetResult()读取SAR_ADC_HW->RESULT寄存器。这种“从Arduino API逆向追溯到寄存器”的能力,是掌握PSOC6的真正门槛。

6.5 CY8CKIT-062S2-AI的隐藏能力:USB Audio Class实现免驱麦克风

开发板自带的PDM麦克风(MP34DT01),通过PSOC6的USB Audio Class可变身为电脑免驱麦克风:

  • PSoC Creator里添加“USBFS”组件,选择“Audio Class”
  • 配置采样率16kHz,位深16-bit,通道数1
  • Arduino代码里调用USBAudio.begin()USBAudio.write()推送PCM数据

效果:Windows/Mac识别为“Infineon USB Audio”,录音软件直接选用,延迟<10ms。这彻底摆脱了USB转串口的带宽瓶颈——这才是“终极组合”的终极形态:一块板子,既是Arduino开发平台,又是专业音频设备。

我在实际项目中发现,当把PSOC6的CapSense触摸按键做成智能台灯开关时,老人用起来比电容屏手机还顺手——因为它的响应不是“屏幕亮起”,而是“指尖刚触到金属焊盘,LED就已渐亮”。这种硬件级的确定性,是任何软件抽象层都无法模拟的。它提醒我:所谓“终极组合”,从来不是堆砌参数,而是让技术退隐,让体验浮现。

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

FanControl 风扇控制指南:三套风扇曲线设置直接抄

FanControl 风扇控制指南&#xff1a;三套风扇曲线设置直接抄 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa/Fan…

作者头像 李华
网站建设 2026/9/14 7:51:55

使用 AWS CDK 在 AWS Fargate 上部署 Apache APISIX 无服务器 API 网关

使用 AWS CDK 在 AWS Fargate 上部署 Apache APISIX 无服务器 API 网关 【免费下载链接】apisix The Cloud-Native API Gateway 项目地址: https://gitcode.com/GitHub_Trending/ap/apisix 导读 本文基于 APISIX 官方部署文档&#xff0c;完整演示如何借助 AWS CDK&…

作者头像 李华
网站建设 2026/9/14 7:50:37

政府科技管理部门技术转移体系构建与实践

1. 政府科技管理部门推动技术转移的现状与挑战技术转移作为科技创新成果转化为现实生产力的关键环节&#xff0c;一直是政府科技管理部门工作的重点。但在实际操作中&#xff0c;我们常常面临以下典型问题&#xff1a;信息不对称&#xff1a;高校科研院所的研究成果与企业需求之…

作者头像 李华
网站建设 2026/9/14 7:48:36

Simulink中强化学习与VR可视化融合实践

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

作者头像 李华
网站建设 2026/9/14 7:48:31

国产大模型DeepSeek与Qwen的技术解析与应用实践

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

作者头像 李华