简介面向操作系统内核研究与驱动开发者的 Ring0 级调试工具源码包围绕 Hyperdbg 这一内核调试器展开适合已具备 x86 保护模式和内核基础知识、希望深入理解调试器实现与系统级问题定位的读者。资源共 93 个文件以 C 头文件、C 源码和 makefile 为主另含汇编、Python 辅助脚本、命令脚本及说明文档压缩包约 212KB整体呈现较完整的工程目录与构建线索。已有 553 人学习说明其在相关学习群体中具有一定参考价值。包内可看到虚拟机监控、内存管理、事件与断点、符号检索、键盘与视频等模块的源码组织也包含构建与配置相关文件便于读者顺着调用关系研究 Ring0 调试的底层机制、断点与内存访问实现并借鉴其工程拆分和编译组织方式。需注意内核调试权限高、操作风险大适合作为机理学习与二次开发参考。1. ring0 调试的真实成本为什么内核里下不了断点用户态下一个 0xCC 就能停住进程同样的招数搬到 ring0往往直接把整机拖进蓝屏——被改写的那条指令位于所有进程共享的地址空间改它的同时也在改所有正在跑的线程。这也是 ring0 内核调试器kernel debugger长期停留在“两台机器加一根串口线”的原因调试机与被调试机物理隔离任何破坏性操作都污染不到宿主。代价是每次断点都要重启、连线、等符号加载一次往返几十秒。真正值得琢磨的不是“怎么把线接上”而是能不能在不改动目标指令一个字节的前提下依然在它执行前拿到控制权虚拟化扩展给出的答案很干脆——把整个操作系统降级成一台被监视的客户机调试器站在它下面一层。2. VM-exit 作为控制点虚拟化为什么能把调试器变成旁观者把操作系统变成客户机听起来像是要把 Windows 或 Linux 整个重写一遍实际上 CPU 已经把这件事的接口准备好了。开启 VMX 之后CPU 多出一个“根模式”和一个“非根模式”操作系统跑在非根模式里调试器跑在根模式里。非根模式执行到某些敏感指令、访问某些敏感资源时CPU 会主动停下来把控制权交给根模式这个动作叫 VM-exit。对客户机来说这次“停下来”是不可观测的寄存器、内存、时间戳看起来都没变只有根模式知道刚才发生了什么。2.1 VMCS 与 exit reasonCPU 什么时候把控制权交出来根模式和非根模式之间的约定全部记在一块叫 VMCS 的内存区域里。它分成几个字段组客户机状态区GUEST_STATE、宿主状态区HOST_STATE、执行控制区VM_EXECUTION_CONTROLS、退出控制区VM_EXIT_CONTROLS、进入控制区VM_ENTRY_CONTROLS。调试器真正关心的是执行控制区那几十个控制位——它们决定了哪些事件会触发 VM-exit比如“拦截 CPUID”“拦截对 CR3 的写入”“拦截 RDMSR”“拦截异常”。每次退出时CPU 会把一个 32 位的退出原因写进 VMCS 的 EXIT_REASON 字段低 16 位是基本原因码。几个常见值值得记牢0 是异常10 是 CPUID18 是 VMCALL28/29/30 是 CR 访问31/32 是 MSR 读写37 是 MTFMonitor Trap Flag48 是 EPT violation。写内核调试器的人大部分时间都在跟 48 和 37 打交道前面那些是辅助。这里有个很容易被忽略的设计取舍拦截不是越多越好。一次 VM-exit 加上根模式处理再 VM-entry开销在几百到几千个时钟周期如果连 RDTSC 都拦客户机的时间会明显走慢某些带超时检测的驱动会直接判定硬件故障。所以成熟的做法是按需拦截——只有用户明确要监控某个 MSR 或某条指令时才打开对应位其余时间保持“几乎不拦”。这也解释了为什么虚拟化型调试器启动后系统几乎无感而一挂上断点就开始卡。提示VMCS 是每核一份的不是全局一份。多核机器上每个逻辑处理器都要独立 VMXON、独立初始化 VMCS否则会出现“某个核上的断点不触发”的玄学现象。2.2 EPT 重定向把 0xCC 换成一次页表违规EPTExtended Page Tables是第二层地址翻译。客户机自己的页表负责“虚拟地址 → 客户机物理地址”EPT 负责“客户机物理地址 → 宿主物理地址”。两层叠起来等于调试器手里多了一张可以随意改写的映射表同一个客户机物理地址可以让它指向真身页框也可以让它指向一份复制出来的替身页框。这个能力是整套机制的地基。传统 0xCC 断点必须修改目标页里的字节遇到只读代码页要先把 CR0.WP 关掉改完再恢复完整性校验一扫就露馅。EPT 方案一个字节都不动客户机以为自己在读原页实际上读的是替身页真身页原样躺在内存里校验和完全一致。更关键的是权限位——替身页可以只给读、不给执行客户机一旦跳过去执行CPU 立刻报 EPT violation原因码 48控制权落到根模式。从客户机视角看它只是执行了一条普通指令中间什么都没发生从根模式视角看这是一次完全可控的“拦路”。这也是为什么基于虚拟化的调试手段在对抗性场景里更耐打——它不依赖任何客户机内的钩子客户机没有任何可被摘除的钩子。3. 断点落在哪一层软件断点、调试寄存器与 EPT 执行断点的分工同样是“在某个地址停住”三种断点实现落在完全不同的层次上能力边界差得很远。搞不清这一点写出来的调试器就会出现“明明地址对就是不触发”或者“一触发就崩”的问题。类型实现层数量上限能否拦读/写是否修改客户机内存客户机可检测性0xCC 软件断点代码字节理论无限否是改写 1 字节高校验和/反汇编可见DR0–DR3 硬件断点调试寄存器4 个是否中MOV DR 可被拦截隐藏EPT 执行断点二级页表受内存限制是页粒度否低页表在根模式MTF 单步VMCS 控制位全局 1 个不适用否低不触发 #DB3.1 0xCC 与 DR0–DR3 的能力边界0xCC 本质上就是 int3 指令靠 #BP 异常把控制权交给调试器。它最大的优势是数量不受限缺点也很硬必须改字节改不了只读页除非临时关写保护而且改完以后任何做代码完整性校验的模块都会发现异常。在内核里还有额外麻烦——被改的那一页可能同时被多个线程执行你没法保证“只在目标线程上停”。DR0–DR3 走的是另一条路CPU 在地址总线上做比较命中就抛 #DB。它不改内存能拦读、写、执行粒度到字节看起来很完美但只有四个槽位而且调试寄存器本身是客户机可见的资源。如果客户机里跑着反调试逻辑一条 MOV DR0 就能读出你设的地址。成熟的实现通常把 MOV DR 访问也纳入 VM-exit 拦截在根模式里伪造一套“干净”的寄存器值返回给客户机。EPT 断点则是页粒度。它不能精确到某一条指令但可以精确到“哪一页被读/写/执行”而且数量只受内存限制还能顺带覆盖整页的访问监控这在追踪数据结构被谁改写时非常有用。三种断点不是替代关系而是分工执行流用 EPT 执行断点加 MTF 单步少量精确地址用硬件断点剩下的兜底用软件断点。3.2 EPT hook 的完整时序违规、重映射、MTF 单步、复位单次 EPT 执行断点的完整生命周期是这样走的第一客户机执行到被 hook 的那一页EPT 权限里没有 X 位CPU 触发 EPT violation退出原因 48同时把出错的客户机物理地址和访问类型写进 VMCS 的退出资格字段。第二根模式的处理函数根据 GPA 找到对应的 hook 条目把这一页的 EPT 映射临时切回真身页并且给足读写执行权限。这一步是必须的——如果不切回去客户机重新执行还是会违规形成死循环。第三打开 MTF 位。MTF 的作用是“执行完下一条指令后立刻 VM-exit”退出原因 37。它和客户机里的 TF 标志完全不同TF 会让客户机收到 #DB 异常客户机自己就能感知到被单步MTF 只在根模式可见客户机毫无察觉。第四MTF 触发的 VM-exit 里把替身页重新挂回去关闭 MTF恢复原来的 EPT 权限一轮闭环完成。整个过程客户机只“真正执行了一条指令”其余时间都在根模式里。开销大约是两次 VM-exit比 0xCC 的异常注入重但对绝大多数调试场景可以接受。注意MTF 是全局单步位不是每核独立语义上的“下一条指令属于谁”。多核并发时如果两个核同时命中 hook会互相踩状态实现里必须用每核独立的待恢复列表。3.3 代码骨架一次 EPT 执行断点的注册与命中下面这段是注册端的骨架把“翻译地址、拆大页、造替身、改映射”四件事串起来。省掉了错误分支和锁只保留主干。// 注册一个执行型 EPT 断点客户机虚拟地址 - 页框 BOOLEAN EptHook_InstallExecuteHook(UINT64 TargetVa, PVOID Handler) { // 1. 用客户机自己的页表(guest CR3)把 VA 翻成 GPA // 注意不能用宿主 CR3否则拿到的是根模式视角的地址 UINT64 Gpa Mmu_GvaToGpa(TargetVa); if (Gpa 0) return FALSE; // 2. 拆大页2MB 页必须先降级成 4KB // 否则同一页里 512 个函数会一起被 hook 掉 if (!Ept_SplitLargePage(Gpa)) return FALSE; // 3. 记录真身页框克隆一份替身 PEPT_HOOK_ENTRY Entry Pool_Alloc(sizeof(EPT_HOOK_ENTRY)); Entry-OriginalPageFrame Ept_GetPageFrame(Gpa); // 真身 Entry-FakePageFrame Ept_ClonePage(Entry-OriginalPageFrame); // 替身 // 4. 替身页去掉执行权限读权限保留 // 客户机读内存完全正常只有跳过去执行才会被拦 Ept_SetPermission(Entry-FakePageFrame, EPT_READ | EPT_WRITE); // 5. 把 GPA 重定向到替身并标记违规时 VM-exit Ept_RemapPage(Gpa, Entry-FakePageFrame, EPT_READ | EPT_WRITE); Entry-Handler Handler; List_Insert(g_EptHookList, Entry); return TRUE; }几个参数值得单独说。TargetVa是客户机虚拟地址必须用客户机 CR3 翻译很多实现翻车就翻在这里——顺手用了当前 CR3结果拿到的是宿主地址映射改到了不相干的地方。Ept_SplitLargePage是必须的前置条件CPU 支持 2MB 甚至 1GB 大页一个大页里塞着几百个函数不拆的话断点范围会大到没法用。Entry-FakePageFrame里的内容是原页的完整拷贝这样客户机读代码、读常量都正常只有在执行这一页时才暴露。命中端对应的处理就短得多VOID VmexitHandler(PGUEST_REGISTERS Guest, PVMEXIT_CONTEXT Ctx) { switch (Ctx-ExitReason) { case EXIT_REASON_EPT_VIOLATION: { // 取违规的 GPA 和访问类型 UINT64 Gpa Ctx-EptViolation.Gpa; PEPT_HOOK_ENTRY Entry EptHook_FindByGpa(Gpa); if (Entry Ctx-EptViolation.ExecutionAttempt) { // 临时切回真身页让这条指令真的能跑 Ept_RemapPage(Gpa, Entry-OriginalPageFrame, EPT_ALL_ACCESS); Entry-PendingRestore TRUE; // 打开 MTF执行完下一条指令再退出一次 Vmx_SetMonitorTrapFlag(TRUE); } break; } case EXIT_REASON_MONITOR_TRAP_FLAG: // 单步结束把替身挂回去形成闭环 Vmx_SetMonitorTrapFlag(FALSE); EptHook_RestoreAllPending(); break; } }Ctx-EptViolation.ExecutionAttempt这个标志很关键同一页的读违规和写违规也会以原因码 48 退出如果不过滤读一次代码页就触发一次单步系统会慢到不可用。PendingRestore是每核独立的不能用全局变量——两个核同时命中不同 hook 时全局标志会让其中一个核的替身页永远回不去。4. 从 hypercall 到命令解析调试器的事件通路怎么搭断点能停住只是第一步停住之后要能把现场送到用户态、要能让用户在用户态下命令、命令还得能安全地落回根模式。这条通路如果设计得糙前面所有机制都会被“一停就卡死”毁掉。4.1 VMCALL 与共享缓冲区用户态、驱动、hypervisor 三段式典型的实现分三段。最下面是根模式里的 hypervisor它只干两件事处理 VM-exit把现场按固定格式塞进环形缓冲区。中间是客户机里的一个内核驱动负责加载/卸载 hypervisor、分配共享缓冲区、响应 IOCTL。最上面是用户态程序负责解析命令、显示界面、跑脚本。为什么不让 hypervisor 直接跟用户态通信因为在根模式里调用客户机内核 API 极度危险IRQL 不确定、可能重入、栈可能是客户机的栈。一旦在 VM-exit 处理过程中触发缺页或者调度整机就挂。所以边界的划法是——hypervisor 只做纯计算和内存拷贝绝不调用客户机任何函数。消息格式通常长这样typedef struct _DEBUGGER_MESSAGE { UINT32 Tag; // 消息类型断点命中 / 日志 / 命令回执 UINT32 Length; // 负载字节数环形缓冲区按它对齐 UINT64 TargetVa; // 触发地址(虚拟) UINT64 TargetPa; // 触发地址(物理) UINT32 ProcessId; // 触发时所属进程 UINT32 CoreIndex; // 哪个逻辑核触发的 UINT8 Payload[1]; // 变长负载寄存器快照、栈回溯等 } DEBUGGER_MESSAGE;Tag决定了上层怎么解释后面的字节Length决定下一条消息从哪开始CoreIndex在多核场景下不能省——同一个断点可能同时被多个核命中丢了核号就没法还原执行序。环形缓冲区必须是单生产者单消费者或者带原子索引的否则高频命中时消息会互相覆盖。4.2 事件化设计为什么把断点写成可注册的回调如果调试器只有“断点命中就停住”这一种行为那它和串口调试没区别甚至更慢。真正让虚拟化型调试器好用的是事件模型把“触发源 条件 动作”三件套注册进去命中后由根模式按动作执行动作可以是记录、可以是修改寄存器、可以是继续执行。事件模型的收益很直接。追踪某个函数被调用了多少次不需要每次都停住等人注册一个“记录并继续”的动作即可性能损耗从“每次几十毫秒”降到“每次几微秒”。追踪是谁在写某个结构体注册一个写型 EPT 断点动作是抓调用栈其余一概不管。代价是状态管理变复杂。一个核上可能同时挂着几十个事件命中时要逐个比对条件事件的注册和注销必须与其他核同步否则会出现“刚装上的断点在另一个核上还没生效”。常见的做法是用一个全局事件表加每核的本地副本注册时先在全局表登记再通过处理器间中断让所有核刷新。4.3 脚本层把复杂条件从内核搬到用户态条件判断放在根模式里做是性能陷阱。假设用户想“只在参数等于特定值时停住”这个判断如果写在 VM-exit 处理里意味着每次命中都要读客户机内存、比较、再决定——读客户机内存本身又可能触发缺页链式反应。更稳的分层是根模式无条件上报原始现场寄存器、栈指针、几个关键内存字条件判断交给用户态的脚本引擎。脚本里写if (rcx 0x1a pid 1234) { ... }这种表达式跑在用户态出错最多是脚本报错不会蓝屏。根模式只负责“抓得快、抓得全”用户态负责“想得复杂”。这也意味着脚本引擎的能力要有边界不能直接读写客户机内存只能读已经上报的快照不能无限循环要有执行步数上限不能阻塞消息队列。把这条边界守住了脚本层反而是整个系统里最安全的部分。5. 常见问题排查内核调试器最容易翻车的五个地方5.1 断点装上去了但从来不触发现象是命令返回成功事件列表里也有这条记录可目标函数被调用了几百次一次都没命中。原因通常有三个地址算错、页没拆、权限位没生效。地址算错最常见——模块基址在客户机里是随机的用静态地址去 hook 必然落空必须先枚举模块拿真实基址再加偏移。页没拆是第二常见目标地址落在 2MB 大页里改的是 4KB 页表项硬件根本不看这一层。权限位没生效则多半是 EPT 缓存EPTP 切换或 INVEPT 没做改了映射表但 CPU 还在用旧的翻译缓存。解决顺序是固定的先打印翻译出来的 GPA 和目标页框确认地址链没断再检查该 GPA 是否属于大页是就先拆最后在改完映射后显式执行一次 INVEPT把 TLB 刷掉。三步走完还不触发再去看 VMCS 的执行控制位是不是被别的模块覆盖了。5.2 命中瞬间整机卡死或蓝屏现象是断点确实触发了但屏幕直接冻住或者蓝屏代码指向内存管理。根因几乎总是“在 VM-exit 处理里干了不该干的事”。比如调用了打印函数、分配了内存、等了锁、访问了可能被换出的页。根模式跑在客户机的地址空间之上任何一次缺页或者调度请求都可能引发不可恢复的嵌套。正确做法是把处理函数压缩到极限只做寄存器保存、内存拷贝、状态位读写全部用预分配的缓冲区绝不调用客户机内核导出函数。日志、格式化、符号解析统统推迟到驱动层或用户态。判断标准很简单——处理函数里不应该出现任何可能阻塞的调用出现一个就砍一个。5.3 加载失败机器上跑着别的虚拟化组件现象是驱动加载返回错误或者加载成功但命令全部无响应。原因是 VMX 是独占资源。客户机里如果已经跑着别的东西在用它再 VMXON 就会失败VMXON 的区域状态是“已占用”。很多系统默认开启基于虚拟化的安全功能会先把根模式占住。排查方法是先读 IA32_FEATURE_CONTROL 确认 VMX 是否被锁再尝试 VMXON 看返回的状态码。如果确实被占用要么在测试环境关掉冲突组件要么调整加载顺序。这不是代码 bug是资源抢占改代码解决不了。5.4 系统跑起来明显变慢计时相关的驱动开始报错现象是挂上调试器后整机变卡某些带超时检测的模块开始误报硬件异常。根因是拦截范围开得太大。每拦一次 MSR 或 TSC 访问就是一次 VM-exit某些系统在空闲循环里高频读时间戳拦截一开每秒几万次退出客户机时间被拉慢超时判断自然失真。解决办法是默认全关只在需要时打开单个拦截位用完立刻关。同时要意识到一个事实只要开启了虚拟化客户机的时间就不可能和裸机完全一致凡是依赖精确计时的场景都应该绕开而不是硬扛。5.5 同一个地址有的核命中有的核不命中现象是多核机器上断点命中次数明显偏少或者只在特定核上触发。原因是 VMCS 和 EPT 都是每核独立的。初始化时只对当前核做了 VMXON 和映射改写其他核还跑在旧的翻译表上。表现就是“调度到某个核上就命中换个核就漏”。解法是初始化阶段遍历所有逻辑处理器逐个执行 VMXON、加载同一份 EPT 指针、刷新各自的 TLB。注册新 hook 时也要通过处理器间中断通知其他核去刷新不能只改自己那一份。6. 设计取舍复杂度该压在 hypervisor 层还是驱动层把调试器拆成三段之后最大的争议是“哪些逻辑放在根模式”。一种思路是把根模式做成薄薄一层只做 VM-exit 分发所有策略都在驱动层另一种是把条件判断、事件匹配全塞进根模式减少往返。前者安全但延迟高后者快但一出错就是整机挂。我倾向于一个中间态根模式负责“捕获与搬运”驱动层负责“判定与派发”用户态负责“表达与展示”。判断依据是这条逻辑“出错时的爆炸半径”——只影响一条日志的放用户态可能让一个核停摆的必须放根模式且写得极其保守介于两者之间的放驱动层并加超时。职责放置位置理由地址翻译、页表改写根模式只有它能碰 EPTVM-exit 分发根模式硬件入口绕不开现场快照拷贝根模式纯内存操作可控断点条件匹配驱动层可加超时与限流符号解析、栈回溯用户态开销大失败无副作用脚本执行用户态不可信输入必须隔离另一个取舍是断点的“停”与“不停”。停住最直观但停住意味着根模式要等用户态下命令期间客户机整机暂停任何带看门狗的系统都会炸。所以真正可用的实现必须默认“不停”把命中当成一次采样事件只在用户明确要求时才进入暂停态。这个设计反过来影响了整个消息通路——缓冲区要够大、要能丢消息、要能标记“这条是采样不是停点”。验证这套东西是否可靠我用的办法很土写一个每秒触发一万次的目标函数挂上 hook 跑十分钟看三件事——目标函数的总调用次数是否和未挂 hook 时一致防漏命中、客户机时间漂移是否在可接受范围防过度拦截、内存占用是否线性增长防缓冲区泄漏。这三项过了再去做单点功能验证翻车概率会低很多。从那以后我每次挂 EPT 断点前都强制走一遍“翻译地址、检查大页、刷 INVEPT”三步不管多简单的场景都不跳过——省下的那两分钟往往要用一次蓝屏和半小时间接损失换回来。这份资料把根模式、驱动层、用户态三段拆开写事件模型和脚本层也有完整实现想自己动手改一版的话从它起步能少踩不少坑希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
解决IntelliJ IDEA中Spring Boot项目命令行过长问题 1. 问题现象与背景解析最近在IntelliJ IDEA中运行一个Spring Boot项目时,突然遇到了"Command line is too long"的错误提示。这个报错通常发生在Windows系统下,当项目的类路径(classpath)过长时,IDEA生成的命令行参数超过了Windows… · 2026/11/2 19:13:49
MFC单机记忆翻牌游戏:消息映射、状态机与GDI双缓冲实战 简介:这是一份面向C与Windows编程初学者的单机记忆翻牌游戏完整源码工程,基于MFC对话框框架实现,适合用来练习界面布局、消息映射、计时器、位图加载与资源管理等知识点。压缩包共419个文件,以384个bmp图像资源为主,配… · 2026/11/2 19:13:49
C++实现简单酒店管理系统 前言
酒店管理系统的核心是房间状态与客人信息的对应关系:哪些房间空着、哪些被预订、哪些已入住、每位客人住几晚、退房时该收多少钱。把这几件事建模清楚,控制台版本用标准库就能实现;建模不清楚,堆再多界面也只是把混乱藏起来。… · 2026/11/2 19:12:48
Buzz技术解析:从信号干扰到消息触达的工程实践 我无法根据当前输入生成符合要求的博文。原因在于:您提供的输入内容中,项目标题仅为“buzz”,且后续所有字段(项目正文、关键词、摘要描述)均为空或仅包含占位符(如“最新网络热词:”后无实际内… · 2026/11/3 5:39:08
Paperclip协议解析:AI工具链的语义桥接器与HTTP流式代理 1. 项目概述:Paperclip 不是回形针,而是一个被严重误读的 AI 工具链枢纽“Paperclip”这个词在中文技术社区里,最近半年几乎成了一个高频误用的代名词。你搜“paperclip node.js”,出来的全是 OpenClaw、Claude Code、React Agent… · 2026/11/3 5:39:08
用AI+Prompt生成Echarts可视化看板:5分钟实现数据大屏 先说个结论:单纯做一张可用的数据可视化,我现在基本都是先把需求扔给AI,让它生成代码,我再花两分钟调样式和数据。整个过程很少超过5分钟,尤其像亚运会这种赛事数据的临时看板,非常吃这个流程。传统做法是打… · 2026/11/3 5:39:08
Paperclip协议:OpenClaw生态中的AI工具链通信契约 1. 项目概述:Paperclip 不是回形针,而是一个被严重误读的 AI 工具链枢纽最近在多个技术社区和开发者群聊里,“paperclip”这个词频繁跳出来,夹在 Node.js 安装教程、React 面试题、OpenClaw 本地部署和 Claude Code 配置指南之间&… · 2026/11/3 5:39:08
Hindsight:LLM API 全链路观测代理层 1. 项目概述:Hindsight 不是“事后诸葛亮”,而是一套可落地的 LLM 应用观测与调试基础设施你有没有遇到过这样的场景:一个基于 OpenAI API 的问答服务突然返回 401 Unauthorized,但日志里只有一行unexpected status 401 unauthori… · 2026/11/3 5:39:08
100万Token单次输出上限:工程代价、适用场景与避坑指南 上周把一个二十多万行的老旧业务仓库丢给模型做整体梳理,输出到第四万多字的时候被拦腰截断,返回里明晃晃写着finish_reason: length。那一刻我才真切意识到,单次输出上限这个参数,比上下文窗口更早地卡住了很多人的脖子。最近某头… · 2026/11/3 5:38:07
双极步进电机控制实战: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/2 4:42:45
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/2 5:17:18
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* 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 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* 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 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* 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 1:01:59
双极步进电机控制实战: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/2 4:42:45
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/2 5:17:18