从MIPS异常处理到PIC32中断实战:原理、模拟与嵌入式开发指南
1. 项目概述从模拟器到硬件的异常中断探索搞嵌入式开发特别是玩过MIPS架构的朋友对“异常”和“中断”这两个词肯定不陌生。它们就像是系统运行中的“紧急呼叫”和“计划外任务”处理得好系统稳定高效处理不好那就是各种死机、跑飞的噩梦源头。我最早接触这个概念是在大学用QtSpim模拟器写汇编看着程序因为除零或者访问非法地址而跳转到某个神秘地址那时只觉得抽象。直到后来真正在Microchip的PIC32系列MCU上做项目需要处理定时器溢出、串口数据到达这些实时事件时才深刻体会到这套机制在硬件层面是如何精密协作的。这个项目就是想把我从软件模拟到硬件实践的这条理解路径梳理出来聊聊在QtSpim里如何观察和验证异常处理程序再到如何在PIC32的C语言环境里实实在在地配置一个中断服务例程。无论你是在校学生通过模拟器学习计算机体系结构还是工程师在嵌入式一线调试棘手的中断冲突问题希望这些踩过的坑和总结的经验都能给你带来些实实在在的参考。2. MIPS异常与中断机制核心原理拆解2.1 什么是异常什么是中断在MIPS的语境里异常是一个总称泛指任何导致CPU正常指令执行流被打断的事件。中断是异常的一个子集特指由CPU外部硬件信号比如定时器、GPIO引脚变化、通信接口引发的异常。而像执行了未定义的指令、算术溢出、尝试访问无效内存地址比如lw指令地址未对齐、系统调用syscall指令等这些由CPU内部在执行指令时检测到的问题则属于异常而非中断。你可以这样理解中断是“外人敲门”异常是“内部出事”。但无论源头如何CPU的应对流程在架构层面是统一的这为我们的学习和实践提供了清晰的框架。MIPS架构为异常处理设计了一套基于固定入口地址的简洁机制。当异常发生时CPU会完成以下几件关键事情冻结现场将当前被打断的指令的地址存入一个特殊的寄存器——EPC中。这是为了异常处理完后能正确返回。切换模式CPU从普通的用户模式切换到更高权限的内核模式以便执行特权操作。跳转执行CPU硬件会自动跳转到一个固定的内存地址去执行异常处理程序。对于大多数MIPS实现包括QtSpim模拟的和PIC32这个地址是0x80000180。这个区域通常位于非缓存、非映射的地址空间确保访问的确定性和速度。原因记录将异常的具体原因是中断是哪号中断还是除零错误记录在Cause寄存器中。2.2 MIPS异常处理的相关寄存器理解这几个寄存器是玩转异常中断的基础Status寄存器这是系统的“总开关”和“状态仪表盘”。其中IEc位是全局中断使能位为0时所有中断都被屏蔽。EXL位是异常级别位一旦发生异常硬件会将其置1此时CPU处于异常处理状态会禁止新的异常某些特定高优先级中断除外并强制使用内核模式。IM域是一个8位字段用于分别使能8个外部中断源。Cause寄存器这是“异常原因报告单”。ExcCode域记录了异常类型代码如4代表地址错误取指5代表地址错误读写8代表系统调用12代表算术溢出等。IP域则反映了8个硬件中断请求线的当前状态无论中断是否被使能只要有请求对应的位就会被置1。EPC寄存器如前所述这是“书签”保存着异常发生后需要返回的地址。对于中断它保存的是下一条即将执行的指令地址对于某些同步异常如syscall它保存的就是syscall指令本身的地址。BadVAddr寄存器当异常与内存访问错误相关时如地址错误或TLB缺失这个寄存器会保存引发错误的虚拟地址。在QtSpim中你可以通过查看这些寄存器的值来调试异常在PIC32上你需要通过配置对应的特殊功能寄存器来设置它们。3. 在QtSpim模拟器中观察与验证异常QtSpim是一个极佳的学习工具它忠实地模拟了MIPS32架构包括异常处理机制。我们可以编写简单的汇编程序来“制造”异常并观察CPU的状态变化。3.1 触发一个简单的算术溢出异常下面这段MIPS汇编代码故意制造一个整数加法溢出.text .globl main main: # 加载最大正数到$t0 li $t0, 0x7FFFFFFF # 加1导致溢出 add $t1, $t0, 1 # 正常退出 (在QtSpim中 syscall 10 表示 exit) li $v0, 10 syscall在QtSpim中运行这段代码程序不会执行到syscall而是会直接跳转。打开“寄存器”窗口你会发现PC变成了0x80000180。EPC寄存器中保存的值是add $t1, $t0, 1这条指令的地址。Cause寄存器的值在QtSpim的“Coproc 1”标签页查看中ExcCode字段应该是12代表算术溢出。Status寄存器的EXL位被置为1。此时CPU已经进入了异常处理入口。但QtSpim默认没有为我们安装异常处理程序所以它会停在那里。这正是一个观察硬件自动行为的好时机。3.2 编写并安装一个简单的异常处理程序为了让程序能继续我们需要在0x80000180处放置自己的处理代码。在QtSpim中可以通过.ktext段来定义内核态代码异常处理程序。.ktext 0x80000180 # 明确指定异常处理程序入口地址 # 异常处理程序开始 mfc0 $k0, $13 # 将Cause寄存器的值读到$k0 srl $k1, $k0, 2 # 右移2位提取ExcCode字段 andi $k1, $k1, 0x1f # 屏蔽高位得到纯异常码 # 简单判断如果是溢出异常ExcCode12我们选择忽略并继续 li $k0, 12 bne $k1, $k0, not_overflow # 是溢出我们简单地将EPC加4跳过引发溢出的指令然后返回 mfc0 $k0, $14 # 读取EPC到$k0 addiu $k0, $k0, 4 # EPC EPC 4 mtc0 $k0, $14 # 写回EPC not_overflow: # 通用返回前清理清除Status寄存器的EXL位 mfc0 $k0, $12 # 读取Status寄存器 andi $k0, $k0, 0xFFFD # 清除EXL位 (位1) mtc0 $k0, $12 # 写回Status eret # 异常返回指令从EPC恢复PC并清除EXL位将这段处理程序与之前的用户代码结合当加法溢出发生时CPU会跳转到0x80000180执行我们的处理程序。处理程序判断是溢出后选择跳过那条惹事的add指令通过修改EPC然后使用eret指令返回。返回后程序会从EPC指向的新地址即li $v0, 10继续执行最终正常退出。注意在真实的操作系统或复杂嵌入式系统中异常处理程序远比这复杂需要保存所有通用寄存器的上下文处理完后还要恢复。这里为了演示原理做了极大简化。eret是异常返回的专用指令它会同时恢复PC和清除Status寄存器的EXL位。3.3 模拟外部中断QtSpim也可以模拟外部中断虽然不如图形化。通常你需要通过修改内存映射的IO地址比如模拟一个定时器控制寄存器来“手动”触发中断请求。然后你需要正确设置Status寄存器的IEc位全局中断使能和IM位中断屏蔽位并确保处理程序能正确读取Cause寄存器的IP位来判断中断源。这个过程更接近硬件但在模拟器中操作略显繁琐主要是理解中断使能、挂起、应答的流程。4. 从模拟到实战PIC32MX系列MCU的中断配置PIC32系列MCU采用MIPS M4K内核其异常/中断机制与标准MIPS一脉相承但通过Microchip的中断向量表和外设库进行了封装和增强使得在C语言环境下配置和使用变得相对直观。4.1 PIC32中断系统架构概览与纯软件模拟不同PIC32的中断源极其丰富定时器、UART、SPI、I2C、ADC、输入捕捉、输出比较、外部引脚变化等等。这些中断被组织成多个中断源每个源有一个唯一的中断向量号。PIC32没有使用单一的0x80000180入口而是使用了多向量中断。发生中断时CPU会根据中断向量号跳转到中断向量表中对应的地址去执行。这个表通常由启动代码预先设置好。关键概念中断控制器管理所有中断源的优先级、使能和状态。中断服务例程就是你用C语言写的处理函数。中断优先级PIC32支持7个软件可配置的优先级1-77最高和一个影子寄存器组高优先级中断可以抢占低优先级的。子优先级在同一主优先级内进一步区分响应顺序。4.2 配置一个定时器中断的完整流程我们以配置Timer1产生周期中断为例展示在MPLAB X IDE中使用Harmony或PLIB旧版库的典型步骤。这里以概念和代码片段说明为主。步骤1初始化定时器首先需要设置定时器的分频、周期并使其工作在所需模式通常是16位或32位周期模式。// 假设使用PLIB库 (概念类似) // 关闭定时器1 CloseTimer1(); // 配置定时器1分频比 1:256 16位周期模式 OpenTimer1(T1_ON | T1_SOURCE_INT | T1_PS_1_256, 0xFFFF); // 计算中断周期假设系统时钟80MHz分频后时钟 80MHz / 256 312.5 kHz // 定时器计数到0xFFFF(65535)溢出中断周期 65536 / 312.5kHz ≈ 0.21秒 // 更常见的做法是设置一个明确的周期值比如 PR1 PR1 31250; // 设置周期寄存器 31250 / 312.5kHz 0.1秒中断一次 TMR1 0; // 清零计数器步骤2配置中断控制器需要设置中断的优先级、子优先级并清除中断标志位。// 设置Timer1中断的优先级为4子优先级为0 INTSetVectorPriority(INT_TIMER_1_VECTOR, INT_PRIORITY_LEVEL_4); INTSetVectorSubPriority(INT_TIMER_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0); // 清除Timer1的中断标志位 mT1ClearIntFlag(); // 使能Timer1中断 mT1IntEnable(1);步骤3编写中断服务例程ISR需要用特定的宏声明并且要记得清除中断标志。// 使用 __ISR 宏声明中断服务程序指定向量号 void __ISR(_TIMER_1_VECTOR, IPL4AUTO) Timer1ISR(void) { // 1. 用户处理代码比如翻转一个LED灯 LATBINV 0x0001; // 假设LED连接在RB0 // 2. 清除中断标志位这是最重要的一步否则会连续触发中断。 mT1ClearIntFlag(); }IPL4AUTO中的AUTO表示编译器会自动生成代码来保存和恢复上下文寄存器这是PIC32工具链的便利之处。步骤4全局中断使能最后别忘了打开总开关。// 使能多向量中断 INTEnableSystemMultiVectoredInt(); // 全局中断使能 INTEnableInterrupts(); // 启动定时器 OpenTimer1(...); // 如果之前没启动的话4.3 中断嵌套与优先级实践PIC32的中断优先级机制非常实用。假设我们有一个高速ADC采样中断优先级6和一个低速串口接收中断优先级2。当CPU正在处理串口中断时ADC中断发生由于ADC优先级更高CPU会自动保存当前串口中断的上下文。立即跳转到ADC的ISR。执行完ADC ISR后恢复上下文继续执行被打断的串口ISR。最后执行串口ISR的返回。配置高优先级中断的步骤与普通中断类似只是将优先级参数设得更高。但需要谨慎使用避免高优先级中断长时间占用CPU导致低优先级任务“饿死”。5. 嵌入式实战中的常见问题与深度调试技巧在PIC32上玩中断光配置正确还不够实际调试中会遇到各种诡异问题。下面分享几个我踩过的坑和解决方法。5.1 中断不触发或只触发一次这是最常见的问题排查思路如下表可能原因排查方法解决方案全局中断未使能检查是否调用了INTEnableInterrupts()或__builtin_enable_interrupts()。在系统初始化最后确保打开全局中断。特定中断源未使能检查对应外设的中断使能位如IEC0bits.T1IE对于Timer1。确认配置代码中已使能该外设中断。中断标志位未清除这是最最最常见的坑ISR中是否清除了对应的中断标志位如IFS0bits.T1IF 0在ISR退出前必须清除标志位。有些外设需要先读状态寄存器再写标志位。中断优先级配置冲突检查中断优先级是否设置为0禁止向量号是否正确确保优先级在1-7之间且向量号与外设匹配。外设本身未正确工作中断由外设事件触发外设配置对吗定时器开了吗UART接收使能了吗先用轮询方式测试外设基本功能是否正常。中断向量表地址错误在自定义启动文件或移植代码时容易发生。检查链接脚本和启动代码确保向量表地址与硬件定义一致。实操心得我习惯在ISR的一开始就用一个GPIO引脚输出高电平在ISR结束时拉低用示波器观察这个引脚可以直观地看到中断是否被触发、触发频率和ISR执行时间。这是最直接的“数字探针”。5.2 中断处理时间过长与系统响应迟缓中断服务例程的设计黄金法则是快进快出。ISR里只做最紧急、必须的事情比如读取数据、清除标志、发送信号量。复杂的处理应该交给主循环或任务。问题在UART接收中断中执行复杂的字符串解析和数据库操作导致其他中断如电机控制PWM更新无法及时响应系统卡顿。解决在UART ISR中只将接收到的字符存入环形缓冲区并设置一个“数据到达”的软件标志。在主循环中检查这个标志并进行后续的解析和处理。volatile uint8_t uart_rx_buffer[256]; volatile uint16_t uart_rx_index_in 0; volatile uint16_t uart_rx_index_out 0; volatile bool uart_data_ready false; void __ISR(_UART1_RX_VECTOR, IPL2AUTO) UART1RxISR(void) { // 快速读取数据 uart_rx_buffer[uart_rx_index_in] U1RXREG; uart_rx_index_in; if(uart_rx_index_in 256) uart_rx_index_in 0; // 设置标志通知主循环 uart_data_ready true; // 清除中断标志 IFS0bits.U1RXIF 0; } // 在主循环中 while(1) { if(uart_data_ready) { uart_data_ready false; // 这里进行耗时的字符串处理不会阻塞其他中断 process_uart_data(); } // ... 其他任务 }5.3 共享数据与临界区保护当ISR和主循环或不同优先级ISR需要访问同一个全局变量如上面的缓冲区索引时就会发生竞态条件。错误示例主循环正在读取uart_rx_index_out此时一个高优先级中断发生并修改了uart_rx_index_in回到主循环后逻辑可能错乱。解决方案使用原子操作对于PIC32某些简单操作可能是原子的但不要依赖于此。最安全的方法是暂时关闭中断。关中断保护在访问共享变量前关闭中断访问后立即打开。// 定义一个安全的读取函数 uint16_t get_rx_buffer_count(void) { uint16_t count; uint32_t status; // 保存当前中断状态并禁止中断 status __builtin_get_isr_state(); __builtin_disable_interrupts(); // 临界区安全计算缓冲区中数据量 if (uart_rx_index_in uart_rx_index_out) { count uart_rx_index_in - uart_rx_index_out; } else { count (256 - uart_rx_index_out) uart_rx_index_in; } // 恢复之前的中断状态 __builtin_set_isr_state(status); return count; }使用__builtin_disable_interrupts()和__builtin_set_isr_state()可以更精细地控制中断状态避免盲目开关。5.4 使用调试器进行中断级调试现代IDE如MPLAB X配合调试器如ICD4提供了强大的中断调试功能中断状态窗口可以实时查看所有中断源的使能、标志、优先级状态。断点可以在ISR内设置断点。注意这可能会改变中断的时序行为用于分析逻辑错误不能用于分析实时性问题。逻辑分析仪/示波器如前所述配合GPIO“探针”是分析中断时序、测量ISR执行时间、发现中断冲突的终极武器。如果发现某个GPIO脉冲意外变宽很可能就是被更高优先级中断打断了。6. 从单周期CPU设计看中断硬件实现网络热词中频繁出现的“单周期MIPS CPU设计”、“多周期MIPS硬布线控制器”等正是理解中断机制硬件根源的绝佳切入点。在Logisim等数字电路仿真软件中设计一个支持中断的MIPS CPU会让你对书本上的概念有刻骨铭心的理解。6.1 中断信号如何融入CPU数据通路在一个基本的单周期MIPS CPU数据通路中添加中断支持需要增加以下硬件中断请求线一个来自外部如定时器模块的输入信号比如叫IntReq。异常检测逻辑与内部的异常检测如溢出、非法指令逻辑一起产生一个统一的Exception信号。控制逻辑修改当Exception有效时控制单元必须将当前PC值对于中断是PC4写入EPC寄存器这需要多路选择器和写使能。强制将PC的下一个值设置为异常入口地址0x80000180而不是正常的PC4或分支跳转地址。这意味着在PC输入的多路选择器前需要增加一个异常入口的输入源。设置Status寄存器的EXL位。CP0寄存器组需要实现Status、Cause、EPC、BadVAddr等寄存器并集成到数据通路中使得软件可以通过mtc0、mfc0指令访问它们。6.2 设计一个支持单级中断的硬布线控制器在硬布线控制器中状态机需要增加一个“异常响应”状态。当指令执行阶段检测到异常或中断请求且全局中断使能时下一个时钟周期不是进入下一条指令的取指而是进入这个特殊状态。在这个状态里控制器发出所有必要的控制信号来完成上述的“冻结现场、跳转入口”操作。这个过程会让你彻底明白中断本质上就是控制单元在特定条件中断请求全局使能下执行了一套与当前指令无关的、预设好的“微程序”或状态转移。eret指令则是另一套特殊的控制序列用于恢复现场。6.3 多周期与中断嵌套的复杂性在多周期CPU中中断可以在指令执行的任何周期被检测。这就带来了一个问题如果一条sw指令在执行到MEM周期时被中断那么EPC应该保存这条sw指令的地址吗中断返回后这条sw指令应该重新执行吗通常MIPS的设计是精确中断即EPC指向导致异常的指令异常处理后重新执行该指令。但对于外部中断由于是异步的EPC指向的是下一条指令。在硬件设计时需要仔细考虑这些细节。而中断嵌套高优先级中断打断低优先级ISR的实现则需要在硬件上支持多套影子寄存器或具备在中断入口自动将关键寄存器压栈的能力这对数据通路和控制逻辑的复杂度是巨大的提升。PIC32等现代MCU通过硬件影子寄存器组和优先级控制器优雅地解决了这个问题但在自己用逻辑门搭CPU时这无疑是一个巨大的挑战。从QtSpim的软件模拟到PIC32的库函数调用再到用Logisim从门电路开始搭建支持中断的CPU这是一个理解层次不断深入的过程。模拟器让你看清架构行为嵌入式实践让你掌握工程方法而自己动手设计硬件则让你洞悉本质。当你再遇到一个中断不响应的问题时你的脑海里浮现的将不再仅仅是某个库函数的参数而是一条从外部引脚电平变化开始经过中断控制器仲裁最终改变CPU数据通路控制信号的完整链条。这种系统性的理解才是解决复杂嵌入式问题的真正底气。

相关新闻

ATA6662 LIN收发器睡眠模式安全切换与死锁规避实战指南

ATA6662 LIN收发器睡眠模式安全切换与死锁规避实战指南

1. 项目概述:深入理解LIN收发器的睡眠管理在汽车电子和工业控制领域,LIN总线因其低成本、高可靠性的特点,被广泛应用于车身控制、传感器和执行器的通信中。Atmel(现为Microchip的一部分)的ATA6662是一款经典的LIN收发器…

2026/6/24 8:33:15阅读更多 →
蒸汽流量表十大品牌|高温高压工业能源计量设备优选榜单

蒸汽流量表十大品牌|高温高压工业能源计量设备优选榜单

蒸汽作为工业生产、集中供热、热电联产的核心能源介质,分为饱和蒸汽与过热蒸汽两大类,普遍具备高温、高压、流速波动频繁、湿汽混杂、工况不稳定等特点,对流量测量设备的耐温耐压性能、抗振能力、温压补偿精度、量程稳定性提出极高要求。行业…

2026/6/24 8:33:15阅读更多 →
基于PIC MCU与蓝牙的智能RGB LED无线调光系统设计与实现

基于PIC MCU与蓝牙的智能RGB LED无线调光系统设计与实现

1. 项目概述与核心价值最近在做一个挺有意思的小项目,核心目标是用蓝牙去无线控制一组RGB LED灯,实现混色调光。听起来好像挺简单,不就是手机发个颜色指令,灯变色嘛?但真做起来,从选型到调试,每…

2026/6/24 8:33:15阅读更多 →
如何用Super IO实现Blender高效导入导出:新手也能掌握的完整指南

如何用Super IO实现Blender高效导入导出:新手也能掌握的完整指南

如何用Super IO实现Blender高效导入导出:新手也能掌握的完整指南 【免费下载链接】super_io blender addon for copy paste import / export 项目地址: https://gitcode.com/gh_mirrors/su/super_io 你是否曾在Blender中为繁琐的文件导入导出而烦恼&#xff…

2026/6/24 9:53:54阅读更多 →
【AISMM Level 1权威解码】:SITS 2026初始级企业必现的5大典型特征与避坑指南

【AISMM Level 1权威解码】:SITS 2026初始级企业必现的5大典型特征与避坑指南

更多请点击: https://kaifayun.com 第一章:AISMM Level 1核心定义与SITS 2026初始级定位逻辑 AISMM(AI System Maturity Model)Level 1 定义为“可运行基础系统”,其核心特征是具备端到端可执行能力,但尚…

2026/6/24 9:53:54阅读更多 →
MapleStory资源编辑革命:Harepacker复活版全面指南

MapleStory资源编辑革命:Harepacker复活版全面指南

MapleStory资源编辑革命:Harepacker复活版全面指南 【免费下载链接】Harepacker-resurrected All in one .wz file/map editor for MapleStory game files 项目地址: https://gitcode.com/gh_mirrors/ha/Harepacker-resurrected 想要彻底改变你的MapleStory游…

2026/6/24 9:53:54阅读更多 →
3步实现网页到Figma设计的无缝转换:HTML转Figma工具深度解析

3步实现网页到Figma设计的无缝转换:HTML转Figma工具深度解析

3步实现网页到Figma设计的无缝转换:HTML转Figma工具深度解析 【免费下载链接】figma-html Convert any website to editable Figma designs 项目地址: https://gitcode.com/gh_mirrors/fi/figma-html 在现代设计工作流中,设计师和开发者经常面临一…

2026/6/24 9:53:54阅读更多 →
音乐解锁全攻略:打破平台限制,让音乐真正属于你

音乐解锁全攻略:打破平台限制,让音乐真正属于你

音乐解锁全攻略:打破平台限制,让音乐真正属于你 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库: 1. https://github.com/unlock-music/unlock-music ;2. https://git.unlock-music.dev/um/web 项目地址: …

2026/6/24 9:53:54阅读更多 →
为什么83%的AI项目ROI测算失真?:深度拆解SITS 2026框架下AISMM价值锚点重构逻辑

为什么83%的AI项目ROI测算失真?:深度拆解SITS 2026框架下AISMM价值锚点重构逻辑

更多请点击: https://intelliparadigm.com 第一章:AISMM价值创造评估:SITS 2026 AI投资回报率测算 在SITS 2026框架下,AISMM(AI Strategy Maturity Model)的价值创造评估聚焦于可量化的ROI测算路径&#x…

2026/6/24 9:48:54阅读更多 →
【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体 一文搞定到底什么是智能体【人工智能】一文搞定到底什么是智能体一. LM,WorkFlow,Agent分别有什么么不同二. Agent的思考过程是怎样的三. Agent的五个核心部分1)LLM2)Prompt3)Me…

2026/6/24 7:33:03阅读更多 →
嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

1. 嵌入式GUI控件:从原理到实战的深度解析在嵌入式系统开发中,图形用户界面(GUI)的设计与实现往往是项目从“能用”到“好用”的关键一跃。不同于资源充沛的PC或移动平台,嵌入式设备的GUI需要在有限的CPU性能、内存空间…

2026/6/24 2:12:09阅读更多 →
Google AI Studio 300美元额度的真相与实战指南

Google AI Studio 300美元额度的真相与实战指南

1. 这300美金不是“送钱”,而是Google埋下的第一道技术门槛 你看到标题里那个醒目的“$300美金”时,第一反应可能是:又一个免费额度?领完就完事?我亲手试过——这300美金根本不是红包,而是一张入场券&…

2026/6/24 7:37:00阅读更多 →
TaskJuggler脚本编程入门:用代码实现自动化项目管理

TaskJuggler脚本编程入门:用代码实现自动化项目管理

TaskJuggler脚本编程入门:用代码实现自动化项目管理 【免费下载链接】TaskJuggler TaskJuggler - Project Management beyond Gantt chart drawing 项目地址: https://gitcode.com/gh_mirrors/ta/TaskJuggler TaskJuggler是一款强大的开源项目管理工具&#…

2026/6/24 0:02:41阅读更多 →
终极教程:使用angular-mobile-nav实现流畅的移动页面过渡效果

终极教程:使用angular-mobile-nav实现流畅的移动页面过渡效果

终极教程:使用angular-mobile-nav实现流畅的移动页面过渡效果 【免费下载链接】angular-mobile-nav An angular navigation service for mobile applications 项目地址: https://gitcode.com/gh_mirrors/an/angular-mobile-nav angular-mobile-nav是一款专为…

2026/6/24 0:02:41阅读更多 →
Wan2.1-Fun-V1.1-1.3B-InP Web UI使用教程:无需代码的AI视频创作

Wan2.1-Fun-V1.1-1.3B-InP Web UI使用教程:无需代码的AI视频创作

Wan2.1-Fun-V1.1-1.3B-InP Web UI使用教程:无需代码的AI视频创作 【免费下载链接】Wan2.1-Fun-V1.1-1.3B-InP 项目地址: https://ai.gitcode.com/hf_mirrors/PAI/Wan2.1-Fun-V1.1-1.3B-InP Wan2.1-Fun-V1.1-1.3B-InP是一款强大的AI视频创作工具,…

2026/6/24 0:02:41阅读更多 →