简介N76E003单片机看门狗复位方法是一份面向8位MCU开发初学者与嵌入式调试人员的专题文档围绕WDT定时器模式、CONFIG4配置、WDCON中断设置及喂狗流程展开帮助读者理解如何把看门狗从普通定时用途切换为异常复位保护。包内共1个docx文件压缩包约338KB篇幅集中便于按寄存器配置、中断服务例程和烧录器设置几个环节快速查阅。内容结合代码片段说明WDT_ISR中断处理、clr_WDTF与set_WDCLR操作、1.638秒中断时间设置以及通过编程器修改CONFIG4的实践思路并提醒合理喂狗与过度依赖看门狗可能影响调试。已有1210人学习适合需要排查死机复位、完善系统可靠性的读者作为配置参考与排错线索。1. 一批控制器半年后陆续死机N76E003 看门狗复位卡在哪一层某公司做的小控制器出货半年陆续回来几台现场反馈死机的断电重启就好接串口什么也看不到。拆开看主控是 N76E003代码里 WDT 初始化写了set_WDTR调了EA 1也没漏就是不复位。翻到 CONFIG4 那一栏才发现问题出厂值 0xFFWDT 在这颗片子上此刻只是纯定时器溢出只置个标志位硬件复位那条路根本没打开。这就是 N76E003 看门狗复位最反直觉的地方——它不是代码里一个开关而是两层东西一层是烧在芯片配置区的字节一层是运行时的寄存器。这篇就把这两层拆开从 CONFIG4 到 WDCON、从 ISR 到烧录器上的配置流程讲清楚怎么让它真复位、怎么验证、以及怎么改成能长期维护的形态。2. 配置字与寄存器WDT 的两层身份和工程骨架动手改代码之前先把看门狗为什么不动这件事的层次理清楚。N76E003 的 WDT 之所以让不少人踩坑是因为它的行为由两个完全不同生命周期的东西共同决定一个是 CONFIG4 配置字跟着烧录走、上电时被芯片读进内部、运行期间改起来极其别扭另一个是 WDCON 这一组 SFR程序想什么时候写就什么时候写。很多人只改了后者前者还是 0xFF于是就出现了代码看着全对、现场就是不复位的局面。我一般把这个模块按三层来组织后面所有的代码和操作都挂在这三层上层次载体什么时候生效改错后的表现配置字层CONFIG4配置区烧录时固化上电加载溢出不复位、只置标志外设寄存器层TA、WDCON程序运行时写入时基不对、计数不启动中断层IE 里的 EWDT、EA、ISR运行时溢出进中断喂狗永不复位看懂这张表后面所有现象都能往里套。2.1 CONFIG4 那一个字节决定了 WDT 是定时器还是复位源CONFIG4 的默认值是 0xFF在这个值下 WDT 被当作普通定时器使用它照样递减、照样溢出、照样置标志位但溢出这件事不会被送到复位电路上去芯片该跑跑、该卡卡。要让溢出产生异常复位需要把 CONFIG4 改成非 0xFF 的值项目里常用的是 0x5F。把 0x5F 按位摊开是0101_11110xFF 是1111_1111中间差的几位就是开关所在。具体每一位叫什么名字我不在这里凭记忆写死芯片手册的 CONFIG4 表上有完整定义照着对一遍比记我的转述靠谱。要抓住的是这个判断逻辑只要 CONFIG4 还是 0xFF你在代码里把 WDCON 配出花来也不会产生复位。这一条是排查所有 WDT 问题的第一道闸门先确认它再往下看。配置字和寄存器分离带来的一个直接后果是它不属于代码版本管理的一部分。代码提交到仓库配置字留在某个工程师的烧录器里人一走、烧录器一换这个项目就变成了在我这儿是好的。所以我在工程里习惯放一个头文件把期望的配置字写成常量/* wdt_cfg.h —— 配置字期望值集中管理和寄存器配置分开 */ #ifndef __WDT_CFG_H__ #define __WDT_CFG_H__ /* CONFIG4 期望值0x5F 表示 WDT 溢出走复位路径不是纯定时器。 * 注意这个宏不能写进芯片它只是工程内的契约值 * 真正的固化动作在烧录器上位机里完成这里用于回读校验和交接。 */ #define WDT_CONFIG4_EXPECT 0x5F /* WDCON 低三位时基字段0x07 对应 1.638 s 这一档 */ #define WDT_TIME_BASE_1P638S 0x07 #endif这段代码本身不产生任何硬件动作价值在于把我们这版固件要求 CONFIG4 是多少这件事写进了仓库。产线回读、售后排查、新人接手都拿这个宏去比对比翻聊天记录可靠得多。参数上只有两个WDT_CONFIG4_EXPECT必须和烧录器里实际配置的值一致改一处就要改另一处WDT_TIME_BASE_1P638S跟着最终选定的时基走别让它变成一个没人敢动的魔法数。2.2 工程骨架几个文件各管一段配置字这层铺完之后代码侧的结构其实很轻。一个能长期维护的 WDT 模块不需要多复杂我一般拆成三个文件各管一段职责不重叠project/ ├── inc/ │ ├── wdt_cfg.h 配置字期望值、时基档位宏 │ └── wdt.h WDT_Init / WDT_Feed / WDT_GetResetFlag 声明 ├── src/ │ ├── wdt.c WDCON、TA、EWDT 的具体配置与喂狗实现 │ ├── isr.c 中断向量集中放这里WDT_ISR interrupt 10 在末尾 │ └── main.c 主循环与喂狗点布置 └── tool/ └── burn.md 烧录器 CONFIG4 配置步骤与回读记录wdt.c只负责和寄存器打交道别的模块不允许直接写 WDCONisr.c集中放中断服务避免有人在新文件里又定义一遍向量号 10 导致重复main.c决定喂狗点放在业务流程的哪个位置这是唯一需要跟着业务改的地方。burn.md看着不起眼但它把配置字不是代码这个事实落到纸面上产线换人时少吵很多架。编译链路上8051 这一套常见做法还是 Keil C51 加一个烧录器上位机编译器负责出 hex烧录器负责把 hex 和配置字一起写进芯片。这里有个容易忽略的先后关系配置字是烧录器写进去的不是 hex 文件里带的所以我重新编译了一遍怎么还是不复位这类问题答案往往在烧录器界面的那一栏而不在编译器输出窗口里。3. 寄存器级配置拆解从 TA 解锁到 ISR 里该不该喂狗配置字解决允许不允许复位寄存器解决多久复位一次、溢出之后走哪条路。这一段是整件事里代码量最少、但最容易写错的部分因为 8051 的寄存器保护机制和中断语义叠在一起写法上差一行行为就完全反过来。3.1 TA 两拍解锁与 WDCON0x07 的位分工N76E003 的 WDCON 属于受保护寄存器写之前要先往 TA 里连续写两个特定值把门打开。这个机制在 8051 系里很常见目的不是加密是防跑飞程序一旦跳飞到不该去的地方很难恰好连续执行写 0xAA、写 0x55、写 WDCON这三条指令误改的概率就被压下去了。/* WDT 初始化先解锁再写时基最后分别打开运行与中断 */ void WDT_Init(void) { TA 0xAA; /* 解锁第一拍 */ TA 0x55; /* 解锁第二拍两拍顺序不能反、中间不能插别的写 */ WDCON WDT_TIME_BASE_1P638S; /* 0x07只动低三位时基字段 1.638 s */ set_WDTR; /* WDT run计数器开始跑 */ set_WDCLR; /* 清一次计数保证从满值开始倒 */ set_EWDT; /* 允许 WDT 中断这一位要不要开见 3.2 */ EA 1; /* 开总中断 */ }逐段说。TA 0xAA; TA 0x55;这两拍必须紧挨着中间插一句无关的赋值解锁就失效后面写 WDCON 会被直接丢弃——而且不会报错芯片安安静静地不理你这是最难查的一类失败。WDCON 0x07里 0x07 是0000_0111实际只动了低三位的时基选择字段对应 1.638 秒这一档运行位和中断允许位没有在这一句里一起写而是留给后面的set_WDTR和set_EWDT单独置位。这样写的好处是配置意图一眼能看出来坏处是多两条指令——在 WDT 初始化这种只跑一次的地方这点开销完全不值得计较。注意set_WDCLR的位置。它在set_WDTR之后、set_EWDT之前作用是让计数器从满值重新开始倒。如果漏了这一句计数器的初值是不确定的第一次溢出的时间可能远短于 1.638 秒表现出来就是上电没一会儿就复位一次很容易被误判成电源问题。3.2 WDT_ISR interrupt 10这段代码到底在干什么软件参考里给的现成中断服务是这样的/* 向量号 10 对应 WDT 中断 */ void WDT_ISR(void) interrupt 10 { clr_WDTF; /* 清溢出标志不清的话中断会反复进 */ set_WDCLR; /* 重装计数器——注意这一句的语义 */ }这两行代码在把 WDT 当定时器用的场景下完全正确溢出、进中断、清标志、重装然后老老实实返回下一个 1.638 秒再来一次等于一个周期性的心跳。但如果你要的是程序卡死了就把芯片复位这段代码就是致命的——溢出瞬间进中断中断里把计数器重装了硬件复位那条路永远等不到条件成立设备于是带着故障一直跑下去。这就是我在第 1 章说的那种情况代码看起来我把看门狗中断也配了实际上配出来的东西和不配看门狗在可靠性上没什么区别。所以set_EWDT这一位开不开取决于你到底想要哪种行为三者的取舍我列在下面目标EWDTISR 里是否 set_WDCLRCONFIG4周期性唤醒 / 心跳节拍开是0xFF 即可纯异常复位关ISR 不参与必须 0x5F先记录现场再复位开否只置故障标志必须 0x5F第三行是我在需要留证据的项目里常用的形态中断里不动计数器只把故障标志、当前任务号、几个关键变量快照存到不受复位影响的 RAM 区里然后让计数器继续倒倒完自然复位。下次上电读出来就知道是死在哪个环节。代价是故障发生后还要等最多一个时基才复位1.638 秒的延迟在绝大多数场景下可以接受。3.3 喂狗点布置主循环末尾一个点还是关键任务汇总喂狗的位置比喂狗的频率重要得多。最省事的写法是在主循环开头无脑set_WDCLR但这样等于只监控了主循环还在转这一件事某个任务内部死等一个永远不来的标志时主循环照样转、狗照样喂故障照旧藏住。我一般用任务标志汇总的方式把喂狗做成一个带条件的动作/* 主循环骨架只有关键任务都跑过一轮才允许喂狗 */ void main(void) { WDT_Init(); Sys_Init(); while (1) { Task_Sample(); /* 采样内部置 flag_sample */ Task_Comm(); /* 通信内部置 flag_comm */ Task_Output(); /* 输出内部置 flag_output */ /* 三个标志都到齐才喂缺一个就不喂让 WDT 到点复位 */ if (flag_sample flag_comm flag_output) { flag_sample 0; flag_comm 0; flag_output 0; set_WDCLR; /* 唯一的喂狗点 */ } } }逻辑上的关键点是喂狗这个动作被绑定到了所有关键任务都完成过一轮这个条件上而不是绑定到主循环转了一圈。任何一个任务卡住不置标志计数器就不再被重装一个时基之后芯片复位问题暴露在上电那一刻而不是在现场跑三天之后。参数上要注意时基的选择——1.638 秒是这段示例里的档位实际项目里要拿最长的那条业务路径去比如果某个任务单次执行就要 2 秒比如一次完整的 Flash 擦写或者长距离串口握手这个时基一定不够用得往上调档或者把长任务拆成几段、段间喂一次。4. 烧录器侧的 CONFIG4 落地为什么运行时改不靠谱到这一步代码侧的事情基本齐了剩下的是把 0x5F 真正写进芯片。这一步是整个流程里最非代码的环节也是最容易在交接中丢失的环节。4.1 运行时改 CONFIG4 的麻烦在哪有人会想既然 WDCON 能在代码里配CONFIG4 是不是也能在main里改一下能改但麻烦而且麻烦得不值得。CONFIG4 位于芯片的配置区不是普通 SFR。写它要走配置区的擦写流程通常伴随着整片擦除、特定时序、以及写入后要重新上电才加载这一系列约束。更麻烦的是它和代码烧录之间存在覆盖关系你在运行时代码里改了一次下次用烧录器重新下载固件配置区又被烧录器的设置覆盖回默认值于是同一个问题在不同批次的产品上表现不一致查起来非常难受。反过来如果配置区有写保护运行时改还可能直接失败且不报错。所以我的做法是把这件事彻底推给烧录环节代码里只保留WDT_CONFIG4_EXPECT这个契约值配置动作在上位机里点一次点好、写进工艺文件、每批都按这个来。4.2 烧录器上的配置流程与回读校验不同厂商的上位机界面长得不一样但流程是一致的按这个顺序走不会漏上位机里选对芯片型号型号选错的话配置项名字都会不一样。加载编译出来的 hex 或 bin注意加载的是最新一次编译产物。打开 CONFIG 配置页找到 CONFIG4 这一项把默认的 0xFF 改成 0x5F。把配置和固件一起写入脱机烧录器如果是脱机烧录的方案。目标板接上烧录等待完成提示。回读校验切到读取/校验功能把芯片里的 CONFIG4 读回来确认是 0x5F 而不是 0xFF。把这次用的配置值、上位机版本、烧录器编号记到工艺文件里。第 6 步是很多人省掉的一步也是我吃过亏的一步。烧录器显示成功只代表通信成功不代表配置区真的写进去了有些情况下配置区被保护、或者上位机里改的是待写入值而没勾选写入配置结果固件更新了、配置没动表现出来就是新固件在老配置下跑怎么看都不对。如果想在固件里加一道自检可以在启动阶段读回配置字并与契约值比对不一致就停在故障态/* 上电自检配置字不对就不进正常业务避免带病运行 */ void Config_SelfCheck(void) { uint8_t cfg4 ISP_ReadConfig(CONFIG4_ADDR); /* 读配置区命令字以手册为准 */ if (cfg4 ! WDT_CONFIG4_EXPECT) { Fault_Led_On(); /* 故障灯常亮现场一眼能看出来 */ while (1) { set_WDCLR; /* 注意故障态里必须喂狗否则会无限复位看不到灯 */ } } }这段的取舍值得说一句停在故障态意味着设备不工作但它把配置没烧对这个事实摆在了现场比带着一个不生效的看门狗跑上半年要好。while (1)里那句set_WDCLR不是多余的——如果不喂芯片会以 1.638 秒的周期反复复位故障灯一闪一闪反而看不出是常亮的故障指示。5. 避坑与排查五类典型翻车现场这一节按现象倒推都是我或者周围人在 N76E003 上真遇到过的。5.1 配置与烧录相关的三类现象一代码全对就是不复位溢出标志位倒是能看到置起来。原因基本可以锁定在 CONFIG4 还是 0xFFWDT 处于纯定时器模式溢出只置标志不进复位链路。解决按 4.2 的流程在烧录器上改成 0x5F改完务必回读确认。判断依据很简单——如果WDTF能读到置位、芯片却活得好好的那就是配置字的问题不用再翻代码。现象二改完配置这一批好了下一批又不行。原因是配置字没进工艺文件换了个烧录器或者换了个人操作又回到默认值。解决把 CONFIG4 的值写进烧录作业指导书并且把WDT_CONFIG4_EXPECT放进代码仓库两边对得上才算完。我见过更隐蔽的版本是同一台烧录器上存了两套配置产线按错按钮前一百台是对的、后一百台是错的。现象三烧录器提示成功回读却是 0xFF。原因通常是配置区写保护没解除或者上位机里改的是显示值、没有真正勾选写入配置项。解决先确认写保护状态再确认上位机的写入选项最后靠回读这一动作兜底。这一步没有捷径只能读回来看。5.2 代码与调试相关的两类现象四设备每隔 1.6 秒左右重启一次节奏非常规律。这是最典型的喂狗点不够或者某段阻塞超时。原因有两类一是主循环里有个长延时或者一次完整 Flash 操作超过了时基二是喂狗点放在了某个条件分支里正常路径根本走不到。解决先把喂狗点临时挪到主循环最外层看复位是否消失以此判断是没喂还是喂不到确认之后再按 3.3 的任务标志法重新布置同时拿最长的业务路径去核对时基档位。1.638 秒这个数在很多项目里偏紧需要往更长档调。现象五仿真器一暂停程序就复位单步调试根本没法做。原因是 WDT 的计数不随 CPU halt 而停止仿真器停住的时候它照跑。这不是 bug是看门狗的本职工作。解决调试版本里把set_WDTR注释掉或者把 CONFIG4 临时配回 0xFF用宏把调试版和发布版分开编译千万不要为了让调试能跑就在 ISR 里加一句set_WDCLR图省事那一句会跟着发布版一起出去等于把看门狗废掉。6. 二次开发把看门狗做成能留下证据的可靠性模块前面讲的都是让它能复位真正放到产品里还要再往前一步复位之后要知道为什么复位。N76E003 的 WDT 溢出会留下标志上电时读一次、判断是不是看门狗干的比现场猜有用得多。/* 上电早期调用判定本次复位来源写入不掉电 RAM 供后续读取 */ void Reset_Reason_Capture(void) { if (WDTF) /* WDT 溢出标志还留着说明上次是看门狗复位 */ { g_reset_reason RESET_BY_WDT; clr_WDTF; /* 判完就清避免下次误判 */ } else { g_reset_reason RESET_BY_POWERON; /* 其余情况按上电/外部复位处理 */ } }这段要在WDT_Init之前跑因为初始化里的set_WDCLR和清标志动作会把证据抹掉。判断顺序也不能反先读标志、再清标志、最后才初始化看门狗。配合 3.2 里说的中断只记快照不喂狗一次复位之后能拿到的东西就相当完整了——是哪个任务没置标志、当时几个关键变量是什么值、复位是不是看门狗造成的。这套东西不复杂但它把现场反馈死机、我们猜变成了回读一下就知道。要提醒的是别在这条路上走过头。我见过把喂狗点铺得满代码都是的写法每个函数入口来一句set_WDCLR看着覆盖率很高实际上等于没有监控——任何一处卡死都还有别处在喂。喂狗点越少越好最好只有一个位置固定在所有关键任务都完成过一轮那个判断后面。最后说个我自己的习惯。从那以后我每次开新项目第一版代码里WDT_Init和Reset_Reason_Capture一定是先写的而且会刻意把 CONFIG4 故意留成 0xFF 跑一次确认配置没改时确实不复位再改成 0x5F 跑一次确认配置改了确实复位。两次对比跑通这个模块才算在项目里立住了后面谁接手都不会再在同一个坑里摔一遍。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
专科生必学8大AI工具:2026就业竞争力提升指南 1. 专科生如何应对AI时代的就业挑战2026年毕业的专科生们正面临着一个前所未有的就业环境。人工智能技术的迅猛发展正在重塑各行各业,许多传统岗位正在被自动化系统取代。根据最新就业市场调研数据显示,到2026年,约40%的现有工作岗位将受到AI… · 2026/11/3 21:44:49
reverse-skill:工程化逆向认知能力模型 1. “reverse-skill”不是玄学,是可拆解、可训练、可复用的底层能力系统“reverse-skill”这个词最近在安全圈、AI工程组和逆向研究社区里频繁出现,但它既不是某个新开源工具的名字,也不是某家厂商刚注册的商标——它指的是一套以逆向思维为内… · 2026/11/3 21:44:49
TensorFlow工业级落地:从环境配置到Serving服务化全链路 1. 这不是“又一个深度学习框架”——TensorFlow 是怎么从实验室走向工业产线的你搜“tensorflow”,页面上跳出来的不是教程,而是“安装失败”“CUDA版本不匹配”“pip install卡住”“No module named ‘tensorflow’”。这很真实——我第一次在客户现场… · 2026/11/3 21:44:49
uniapp海外游戏分发工程:PG电子集成与Switch卡带区域适配 简介:这是一套面向海外游戏业务开发者的全栈前端解决方案,基于UniApp框架实现跨平台兼容,专为构建海外游戏交易平台、手游下载站及Switch游戏卡带销售系统设计。资源包含完整可二次开发的前端源码(非编译后产物)&#… · 2026/11/4 0:00:17
Qoder NEXT:智能代码补全工具的技术解析与应用 1. 项目概述Qoder NEXT作为新一代智能编程辅助工具,其核心突破在于通过深度优化代码补全算法,将AI生成代码的开发者采纳率提升了65%。这个数字背后代表着编程效率的实质性飞跃——开发者不再需要花费大量时间在重复性代码编写和机械性调试上,… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
AI辅助技术栈评估:提升研发决策效率60% 1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年… · 2026/11/4 0:00:17
从生成Token到直接决策:Jev如何重塑AI Agent工程实践 1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你… · 2026/11/4 0:00:17
32G统一内存跑大模型:内存账、TPS实测与端云分流 想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统… · 2026/11/4 0:00:17
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46