4PAM通信仿真手搓指南:从MATLAB脚本到Simulink模型的暴力调试
做数字通信仿真的老哥老姐们应该都有体会手写一个4PAM调制解调在MATLAB脚本里可能半小时就跑通了无非是生成比特、映射符号、加噪声、判决、统计误码率这几步。但哪天你心血来潮准备把这套代码搬到Simulink里做成一个可视化模型好跑完仿真还能直接看星座图和波形各种意想不到的问题就开始冒头了。这篇文章就是我最近“手搓”4PAM从MATLAB代码迁移到Simulink的暴力调试图鉴把我踩过的坑、试错的过程、排查的思路和最终能稳定跑出误码率曲线的完整做法都记录下来。如果你是刚接触通信仿真或者已经在Simulink里被信号维度、采样时间、数据类型折磨过那这篇文章应该对你有用。1. 先把4PAM原理和MATLAB脚本盘清楚为什么标题叫“暴力调试”因为从脚本到模型的迁移不是平滑的“翻译”而是推倒重来式的重构。四个电平、两比特一符号、格雷码映射这些基本概念如果没在代码里验证过直接上Simulink只会越调越乱。1.1 四电平映射与归一化4PAM4-Level Pulse Amplitude Modulation就是把2个比特组合成一个符号映射到四个幅度电平上。最常见的一组映射是格雷码映射相邻电平只差一个比特这样单个符号判决错误时大概率只错1个比特误码率表现会好看不少输入比特十进制索引发送电平未归一化000-3011-111211033注意表里的顺序我特意写成了格雷码顺序00-01-11-10这样相邻电平之间的汉明距离都是1。如果不做格雷码映射比如直接用00-01-10-11误符号率相同但误比特率会略高。这4个电平并不是最终的物理信号。平均符号能量是 (9119)/4 5如果不归一化后面设置Eb/N0时噪声方差要对应改成Es5麻烦且容易算错。我习惯先除以sqrt(5)让平均符号能量等于1这样后面信噪比的所有关系都清爽了。1.2 MATLAB脚本形态这是最基本的无脉冲成形的MATLAB发送端代码。实际动手之前我建议先在脚本里验证好整个链路Simulink只是换一种实现方式。M 4; numBits 1e6; % 测试到1e-4的BER至少1e6比特 numSymbols numBits / log2(M); bitsTx randi([0 1], 1, numBits); % 比特配对并转换为十进制索引 symIdx bi2de(reshape(bitsTx, 2, [])., left-msb) 1; % 格雷码电平表 lut [-3 -1 1 3]; symbols lut(symIdx); symbols symbols / sqrt(mean(symbols.^2)); % 归一化平均能量为1 % AWGN信道根据EbN0dB换算噪声方差 EbN0dB 8; EbN0 10^(EbN0dB/10); EsN0 EbN0 * log2(M); % Es/N0 Eb/N0 * log2(M) N0 1 / EsN0; % 因为归一化Es1 noise sqrt(N0/2) * randn(1, numSymbols); rx symbols noise; % 接收端最小欧氏距离判决 table lut / sqrt(5); % 归一化后的判决电平 [~, rxIdx] min(abs(rx. - table), [], 2); rxIdx rxIdx. - 1; % 索引转回比特统计误码率 bitsRx de2bi(rxIdx, 2, left-msb).; bitsRx bitsRx(:).; ber sum(bitsRx ~ bitsTx) / numBits;我在写这篇文章前又把这段代码跑了一遍EbN08dB、1e6比特时得到BER在1e-3量级左右跟理论M-PAM误码率曲线基本吻合。这里有个关键点噪声方差为什么是 sqrt(N0/2) 而不是 sqrt(N0)因为基带AWGN复信号模型的实部和虚部各有N0/2的功率但我们只用了实数信道所以只用实部这一支方差就是N0/2。这个细节如果没搞清仿真和理论会系统性偏差3dB。1.3 待仿真参数先定下来动手搭模型前先定三件事符号数、过采样倍数、要测的Eb/N0范围。符号数决定置信度。想测BER到1e-4至少要跑1e6比特才能数到100个错误比特误差才勉强可接受。1e6比特在Simulink里若用Sample-based全链路跑可能要等上几分钟所以我建议先用1e5符号快速试通链路再做完整参数扫描。过采样倍数samples per symbolsps同样影响耗时。sps1时每个符号一个采样点模型最简单星座图上的点就是干净的四个点sps4时每个符号有4个采样波形更像真实信号但要额外考虑下采样和定时。我建议第一版用sps1把逻辑全跑通后再加成形滤波。Eb/N0扫描范围4PAM在AWGN下BER为1e-3大约在8~9dB附近为展示完整曲线建议扫0~14dB每2dB一个点。手动改参数太痛苦后面第4章会介绍用脚本驱动模型自动扫描。2. 从脚本到Simulink暴力迁移的模块化方案2.1 映射关系与模块选型大部分人在“代码转模型”这一步犹豫太久想找最优雅的模块组合。我的建议是第一版直接用 MATLAB Function 块承担所有算法逻辑Simulink只负责提供信号流和可视化这样迁移成本最低调试也最快。等跑通了再拆模块也不迟。模块对照表MATLAB脚本功能Simulink方案随机比特生成Random Integer GeneratorM-ary number4输出0~3比特-符号映射MATLAB Function内部查表符号归一化Gain模块乘1/sqrt(5)或直接写进MATLAB Function加噪声AWGN Channel模块配置Es/N0或Eb/N0符号判决MATLAB Function符号-比特映射MATLAB Function或DemuxROI操作误码率统计Error Rate Calculation模块这里有个容易误导新手的点Random Integer Generator 直接输出的是十进制符号索引0~3而不是比特所以“比特生成-配对-映射”在脚本里两步做的事在Simulink里一个模块就完成了。发送比特要想拿来做误码率统计就得从符号索引反推出“参考比特”或者像我一样在MATLAB Function里同时输出符号和对应的参考比特。如果你用的是比较新的MATLAB版本这些模块在Communications Toolbox路径下都能搜到模块名字有细微差别也很正常直接搜模块名即可。2.2 采样时间的安排Simulink里所有离散模块都必须有明确的采样时间Sample Time。sps1时符号周期 Ts1 秒所有模块的采样时间都设成1。AWGN Channel 模块里的符号周期Symbol period也要设1而且输入信号功率Input signal power设置为1因为我们做了归一化。如果模型里混杂了连续模块比如某些滤波器自带Continuous sample time它们会强制求解器使用变步长最后Scope里的波形会出现“锯齿”一样的双向线看起来像抖动其实是因为离散信号和连续信号混着显示。遇到这种情况先检查每个模块的采样时间是不是一致。可以通过菜单 Debug - Sample Time - All 显示采样时间图例红色点位一眼就能看出哪些模块采样时间不统一。2.3 第一个能跑的模型怎么搭我建议按“发送 - 信道 - 接收 - 统计”四段式搭每搭完一段就先跑一次发送段Random Integer Generator MATLAB Function映射归一化。开环查看把发送端输出先直接接一个 Scope确认四个电平正确。加信道接 AWGN Channel把 Scope 接到信道输出看噪声污染后的波形。接收段接 MATLAB Function判决反映射再接 Error Rate Calculation。Error Rate Calculation 模块有四个输入Tx、Rx、Enable、Clock后两个可空置。Tx和Rx都需要是比特序列。如果你用 Random Integer Generator 输出0~3想拿它当参考比特需要先把它转成2比特的序列。最简单的方式是在发送端加一个 MATLAB Function输入符号索引、输出2比特数组。但Sample-based的模式下MATLAB Function每次只处理一个标量输出没法直接输出1x2的向量除非你设置输出为2维。这也是Simulink通信仿真的日常一切都得按“每个时刻一个样本”来思考。实际我更推荐的做法发送端和接收端都在MATLAB Function内部完成索引-比特转换参考比特也由发送端MATLAB Function输出。因为Random Integer Generator本身就产生符号索引所以仿真期间参考比特在模型内部是现成的不需要额外产生随机比特流。3. 暴力调试图鉴那些翻车现场这一章是本文的核心。以下每个案例都是我在实测中真实遇到的按排查顺序写出来。3.1 翻车一MATLAB Function块的维度认知陷阱现象模型能跑但 Symbol 波形永远只有几个值符号索引传到 MATLAB Function 后报错“Attempt to execute SCRIPT as a function” 或者 “Index exceeds the number of array elements”。原因Simulink 中 MATLAB Function 块的输入默认被视为标量。如果函数体内部写成table(u)而 u 是传入的符号索引标量没问题但如果你不小心把u当成了向量或者调用了length(u)、u(1)这类代码就会出问题。反过来如果 Random Integer Generator 设置成了 Frame-based默认是Sample-based那输入就是 Mx1 的帧函数内部必须按向量写。排查思路先右键 MATLAB Function 的输入端口打开 Ports and Data Manager看 Size 项。Sample-based 输入应为 1如果显示 -1继承或 M代表可能接收了向量。设置成1并在函数内部用assert(isscalar(u))或者coder.extrinsic之类的断言保证后续不会对输入维度产生误判。3.2 翻车二数据类型战争——double、boolean和uint8现象Error Rate Calculation 模块报错Expected input data type boolean but double found或者误码率结果永远为0、永远为0.5。原因Random Integer Generator 默认输出 doubleMATLAB Function 里bitsTx、bitsRx如果直接拿 double 比较Error Rate Calculation 也能处理但如果中间经过了某些转换模块比如 Convert 转成 uint8或者 RelationalOperator 输出 boolean类型不匹配就报错。误码率结果永远为0.5则意味着比较对象完全错位多半是数据类型不一致导致判断逻辑错误。我最后采取的统一方案所有比特相关变量在 MATLAB Function 内强制转换function [symOut, bitRef] pam_map(u) % u: 0~3整数索引 lut [-3 -1 1 3]; symOut lut(u 1) / sqrt(5); bitRef de2bi(u, 2, left-msb); % 返回1x2 double end然后在 Error Rate Calculation 前用 Convert 模块把 bitRef 转成 boolean。注意Convert 要选 “Output data type” 为 boolean不要选 “Output as unsigned integer”。3.3 翻车三定时错位导致误码率逼近50%现象无噪声时AWGN Channel 的 SNR 设成很大的值或直接旁路Scope 里发送波形和解调波形从形状看是对上的但 Error Rate Calculation 统计错的比特数恰好约等于总比特数的一半。原因检测时间没对齐。最典型的是 MATLAB Function 块在 Simulink 里默认是“零延迟”还是“一拍延迟”的困惑。实际上如果函数块被配置为输出直接计算它会表现为组合逻辑没有延迟但如果模型里存在 Buffer、Delay、Rate Transition 等模块哪怕只延迟了一个采样周期也会让比较的两组比特错开一位。错开一位后每一对比特都像随机比较BER自然接近0.5。排查链路用 Scope 同时观察发送端参考比特 bitRef 和接收端 bitRx重点看首脉冲对齐情况。打开 Time Scope 的游标数一数两个信号边沿差几拍。在发送端前加一个常数 0 序列做同步头比如前10个符号都为0看它传播到接收端需要几个采样周期然后给错误率统计模块补一个 Delay。也可以直接把 Error Rate Calculation 模块的 Maximum delay 参数调大比如设为1000它会自动搜索最佳对齐延迟。实测这个选项非常好用但要注意它会引入额外的计算开销符号数多时可能拖慢仿真。3.4 翻车四噪声方差的3dB迷惑现象BER曲线和理论曲线在低信噪比段对得上高信噪比段差3dB或者反过来理论是1e-3的地方仿真出1e-2。原因绝大多数情况下是噪声单边/双边功率谱密度混淆。Simulink 的 AWGN Channel 模块同时支持 Es/N0 和 Eb/N0 两种模式。如果你选择 Eb/N0 模式需要正确设置“Input signal power”和“Symbol period”。如果选择 Es/N0 模式就不需要符号周期信息。我在第1章就强调过归一化方便之处输入信号功率1符号周期1直接填 Eb/N0 即可。千万不要在高斯白噪声用 Real 还是 Complex 上搞错模块默认加的是复噪声还是实噪声由输入的信号是实数还是复数决定4PAM基带信号是实数所以只会加实噪声。另一个隐蔽点AWGN Channel 模块在输出端默认会给信号乘以一个增益用于保持归一化功率这个增益跟“Input signal power”相关。如果前面归一化没做这里结果就会偏。3.5 额外提醒Frame-based 与 Buffer 的不归路很多教程喜欢用 Buffer 模块把多个采样拼成一帧然后用帧模式处理。但在4PAM这种简单链路里我强烈不建议第一版就这么干。Frame-based 一旦启用Scope、Error Rate Calculation、星座图模块的显示方式全变而且定时问题会成倍放大。我之前有一版模型就是加了 Buffer 想模拟sps4结果解调端要手动控制帧边界排查了两天才发现是 Buffer 的“ports”设置导致数据帧首尾颠倒。如果你不是特别需要脉冲成形和匹配滤波第一版老老实实用sps1每个符号一个采样直接跳过 Buffer。4. 验证闭环从波形到误码率曲线4.1 无噪声链路先行验证搭好模型后第一个测试永远是“关掉噪声、对比误码率是否为0”。我习惯在 AWGN Channel 前加一个手动开关手动SwitchConstant或者直接把 SNR 设置成很大的数比如100dB跑一小段数据确认 BER0。这一步能滤掉前面3.3这种定时问题和映射问题。4.2 用脚本驱动参数扫描单独在Simulink界面上改 Eb/N0 然后点 Run一次两次还行要扫7个点且每个点统计几百个错误比特纯手动基本不可行。我的做法是写一个MATLAB控制脚本用 sim 函数循环跑EbN0dBDigital 0:2:14; berSim zeros(size(EbN0dBDigital)); for k 1:length(EbN0dBDigital) set_param(pam_demo/AWGN Channel, EbN0, ... num2str(EbN0dBDigital(k))); simOut sim(pam_demo, StopTime, 1000); berSim(k) simOut.ber(end); end注意几个坑set_param修改 Eb/N0 前模型必须已load否则找不到路径。每次 sim 会重新初始化随机种子除非在模型里显式设置了种子值。一般Random Integer Generator默认固定种子强行跑多次扫描反而可能每次都拿同一段数据测不同信噪比结果曲线不平滑。建议在循环里给符号生成模块不同的种子偏移。用 simOut.ber 导出 Error Rate Calculation 的输出到工作区时模型里对应的模块需要在参数面板里勾选“Output data”并设置Workspace变量名不然simOut拿不到数据。4.3 三路对照判断模型对不对拿到仿真BER后我会做三路对照理论公式。M-PAM在AWGN下的误符号率近似为2*(M-1)/M * qfunc(sqrt(6*log2(M)*EbN0/(M^2-1)))误比特率在格雷码下约等于误符号率除以2。把这和脚本BER、Simulink BER画在一起看趋势。星座图。在接收端判决前接一个 Constellation Diagram 模块观察四个点簇是否对称、是否以0为中心。如果点簇有偏置说明归一化或直流分量不对。直方图。把判决前的接收信号用 To Workspace 导回MATLAB画直方图检查四个峰的位置和宽度理论上方差为N0/2。我个人经验只要前两步通过BER曲线基本就不会差太远第3步在排查“噪声方差设错”这种问题时尤其好用。5. 沉淀下来手搓4PAM的两个通用套路5.1 从脚本到模型先把算法注进MATLAB Function我见过很多人一上来就用 Simulink 的模块去搭理想通信系统结果卡在模块参数配置上连算法本身的问题都还没碰到。而“暴力迁移法”是脚本逻辑直接搬到MATLAB Function里Simulink只当信号流壳子等算法验证完再逐步把MATLAB Function拆成更基础的模块。这样做的好处是调试时你能真正聚焦在算法和仿真参数上而不是被模块配置拌住脚。5.2 用Sample Time Legend时刻盯着采样时间只要采样时间不一致信号流就会出现周期性的“捣乱”。养成两个习惯一是每次新增模块后按 Debug - Sample Time - All二是给所有离散模块统一设置采样时间不要有的继承-1有的显式设1。继承设置在某些模块里默认是常量容易让模型混杂多种速率排查起来很费劲。5.3 后续扩展方向这篇文章做的还是最朴素的4PAM传输。后续你可以往三个方向扩展一是加根升余弦成形滤波和匹配滤波这时sps要设为4以上接收端补一个定时同步二是把接收端的MATLAB Function换成一般通信系统常用的“均衡器软判决译码”这时误码率曲线会更漂亮三是用Simulink的C代码生成工具把验证好的4PAM模型移植到FPGA或DSP上做硬件在环测试这才是Simulink模型的最终价值。我在实际帮别人排查这类模型时发现90%的问题都出在“把矩阵思维硬套到流式信号”上。MATLAB脚本里你可以优雅地写symbols lut(symIdx)整条序列一次算完Simulink却只能一个时刻一个符号地往前走。一旦你接受这种思维切换4PAM这种级别的手搓项目不会消耗你超过一个周末。最后再送一个实用小技巧调试时把 Error Rate Calculation 的 Maximum delay 设大然后直接看它自动计算出的对齐延迟这个值往往能告诉你模型里哪个环节偷走了几个采样周期比拿Scope一格一格数快多了。

相关新闻

dblp配合Zotero自动梳理参考文献:从抓取入库到踩坑排查

dblp配合Zotero自动梳理参考文献:从抓取入库到踩坑排查

搞科研的人应该都懂,写论文最烦的往往不是想 idea,而是整理参考文献。我帮导师核对过一份四十多篇文献的参考文献表,光是逐篇比对作者全名、卷期页码和年份,就耗掉了整整两个下午,还发现好几处年份和页码对不上。后来我…

2026/10/11 8:11:17 阅读更多 →
用树莓派DIY可视门铃:远程监控、移动侦测与自动录像完整方案

用树莓派DIY可视门铃:远程监控、移动侦测与自动录像完整方案

朋友家那台带屏幕的可视门铃用了不到一年就罢工了,开机卡死在LOGO画面,售后说要寄修,来回折腾了一个多星期。我劝他先别急,正好桌上一块吃灰的树莓派4B,还有一块当年拆下来没舍得扔的OV5647摄像头模块,周末…

2026/10/11 8:11:17 阅读更多 →
我的等离子表面处理设备周度保养折腾记录

我的等离子表面处理设备周度保养折腾记录

每周五下午,我都会花十几分钟给实验室那台等离子表面处理设备做一次点检。坚持了一段时间,发现设备报警少了,实验重复性也好了。记录一下我的周度保养流程,给同样用等离子表面处理设备的朋友参考。第一步,排冷凝水。 气…

2026/10/11 8:11:17 阅读更多 →

最新新闻

2026软件测试面试指南:从Linux到AI测试的全栈质量保障

2026软件测试面试指南:从Linux到AI测试的全栈质量保障

1. 2026年软件测试面试到底在面什么做了这么多年软件测试,也面试过不少候选人,我越来越觉得现在的面试早就不是背几套题就能过关的时代了。前两天跟一个刚跳槽去大厂的兄弟聊天,他说现在的软件测试面试题已经卷到“既要懂八股、又要能落地、还…

2026/10/11 8:50:40 阅读更多 →
GET请求知识详解

GET请求知识详解

一、GET 请求是什么GET 是 HTTP 协议里最基础的一种请求方法。一句话理解:从服务器「获取 / 查询」数据,不修改服务器上的数据。 就像你在浏览器地址栏输入网址敲回车,本质就是发送 GET 请求,向服务器拿网页内容。核心特点&#x…

2026/10/11 8:50:40 阅读更多 →
AgentScope Java 2.x 系列【45】 2.0.4 版本更新:支持 Responses API、个人微信......

AgentScope Java 2.x 系列【45】 2.0.4 版本更新:支持 Responses API、个人微信......

文章目录1. 更新速览1.1 ✨ 新增1.1.1 核心 / 模型1.1.2 Harness / 工具 / 存储1.2.3 Service / Channel1.2 🔄 变更1.3 🛠️ 修复1.3.1 核心 / 状态 / 并发1.3.2 模型提供商1.3.3 Harness / 沙箱 / 集成1.4 📖 文档更新2. 重要更新2.1 OpenA…

2026/10/11 8:50:40 阅读更多 →
96% 氧化铝陶瓷怎么切?脆性材料的水刀工艺与参数边界

96% 氧化铝陶瓷怎么切?脆性材料的水刀工艺与参数边界

结论先行:氧化铝陶瓷(尤其 96% 含量)硬度高、脆性大、还导电性差。硬、脆、不导电三条凑一起,传统切割方式基本都别扭:刀具磨不动,激光有热应力、容易崩裂,线切割又不导电切不了。陶瓷为什么难切…

2026/10/11 8:50:40 阅读更多 →
风光出力联合建模:Matlab中Weibull与Beta分布及Copula耦合实现

风光出力联合建模:Matlab中Weibull与Beta分布及Copula耦合实现

风电的出力随机性有多难搞,做过新能源并网仿真的人都懂:风速忽大忽小,光照一阵一阵,你要是拿个正态分布去套,风功率曲线尾巴根本对不上。圈里早就形成了一套经验——风速用两参数Weibull分布去拟合,光照辐照…

2026/10/11 8:50:40 阅读更多 →
车载空调建模与控制算法实战:从数学推导到图纸落地

车载空调建模与控制算法实战:从数学推导到图纸落地

兄弟们,聊个接地气的话题。前阵子我把一个车载空调控制器的算法模型从零到一完整落地了一版,从最初的数学推导、仿真验证,到最后的控制算法写进控制器、再到结构图纸冻结,整个流程走完,感触挺深的。这事看起来是个传统…

2026/10/11 8:49:40 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →