
1. 从“中断”到“事件”MSPM0定时器响应机制的范式转变在嵌入式开发领域尤其是基于ARM Cortex-M内核的微控制器应用中我们通常对“中断”这个概念非常熟悉。当外设需要CPU介入处理时它会拉起一根中断线NVIC嵌套向量中断控制器会暂停当前任务跳转到对应的中断服务程序ISR去执行。这个过程虽然高效但本质上是一种“中心化”的响应模式——一切都需要CPU这个“大脑”来裁决和处理。然而随着应用复杂度的提升特别是对实时性、功耗和系统效率要求极高的场景如电机控制、数字电源、高速数据采集这种将所有事件都汇聚到CPU的模式开始显现出瓶颈。中断响应有延迟从触发到ISR第一条指令执行通常需要几十到上百个时钟周期频繁的中断也会消耗宝贵的CPU带宽增加功耗。这时一种更优雅、更高效的机制——“事件”系统Event System就显得尤为重要。MSPM0系列微控制器的TIMx定时器模块其中断与事件支持Interrupt and Event Support架构正是这种设计思想的杰出体现。它不仅仅提供了传统的CPU中断路径更构建了一个灵活的、去中心化的硬件事件网络。简单来说你可以把事件理解为一种“硬件级别的中断”。它不需要CPU介入就能直接在外设之间传递信号、触发动作。比如定时器的比较匹配事件可以直接“通知”ADC开始一次转换或者“命令”另一个定时器开始计数整个过程完全在硬件层面完成零延迟、零CPU开销。这种机制的技术价值在于它将系统从“事事请示CPU”的集中式管理转向了“硬件自治、协同工作”的分布式处理。对于需要精确定时、快速响应的应用这不仅仅是性能的提升更是系统架构的革新。它能将CPU从繁琐的周期性任务中解放出来专注于更复杂的逻辑和决策同时还能实现更低的系统功耗。2. MSPM0 TIMx事件管理架构深度解析要玩转MSPM0定时器的事件系统我们必须先吃透它的整体架构。根据技术手册TIMx模块内部的事件管理可以概括为“三发两订”模型。2.1 核心角色发布者与订阅者整个事件系统的运作基于“发布-订阅”模型这和我们熟悉的软件设计模式如出一辙只不过这次是在硬件里实现的。事件发布者Event Publisher 事件的产生源。在TIMx模块里有三个发布者“席位”CPU_INT 专用于向CPU子系统发布中断请求IRQ。这是一个静态路由意味着它的目的地固定是CPU的NVIC不可更改。当定时器的零事件Z、加载事件L、比较匹配事件CCUx/CCDx等发生时可以通过这个通道向CPU申请中断。GEN_EVENT0和GEN_EVENT1 两个通用的发布者。它们产生的事件不走固定的CPU中断线而是通过通用路由Generic Route通道广播出去。任何配置为监听该通道的其他外设订阅者都能接收到这个事件。事件订阅者Event Subscriber 事件的接收和处理方。TIMx模块有两个订阅者端口FSUB_0和FSUB_1 这两个端口允许TIMx模块“订阅”来自其他外设如GPIO、比较器COMP、ADC等产生的事件。当订阅的事件发生时可以触发TIMx内部的特定动作例如复位计数器、启动/停止计数、触发捕获等。这个架构的精妙之处在于其双向性和灵活性。TIMx既可以作为“指挥者”用GEN_EVENTx发布事件去驱动其他外设例如定时器周期到触发ADC采样也可以作为“执行者”通过FSUB_x订阅其他外设的事件来改变自身行为例如比较器输出跳变立即复位定时器生成特定宽度的PWM死区。2.2 事件路由静态与通用理解了角色再看它们如何通信静态路由Static Route 专线专用。CPU_INT到 CPU 的这条路是芯片设计时固化好的用户只能选择让哪些事件通过IMASK寄存器走这条线去申请中断但不能改变它的目的地。配置简单直接延迟确定。通用路由Generic Route 硬件“总线”。芯片内部会提供多个例如16个通用的、可配置的事件通道EVENT_CH0 ~ EVENT_CH15。GEN_EVENT0/1和FSUB_0/1都可以通过配置各自的FPUB_x和FSUB_x寄存器中的CHANID字段连接到任意一个空闲的通道上。关键配置类比 你可以把通用事件通道想象成会议室里的多个电话分机号1-15。TIMx的FPUB_1寄存器设置为5就等于它用“分机5”对外广播。ADC的FSUB_0寄存器也设置为5就等于它接听了“分机5”。这样TIMx一“喊话”ADC就能“听到”。这个连接完全由软件配置实现了硬件外设间的任意互联。2.3 事件类型全景图TIMx能产生或响应的具体事件有哪些手册中的Table 28-23和Table 28-24/28-25给出了详细清单。为了更直观我将核心事件分类整理如下事件类型事件名称说明典型应用场景计数器事件Z (Zero)计数器值递减到0时产生。周期性中断PWM周期结束标志。L (Load)计数器值加载LOAD寄存器值时产生。在中心对称PWM或特定相位控制时有用。比较/捕获事件CCUx (x0~5)计数器向上计数时与CCx寄存器匹配。产生PWM上升沿输入捕获的计时点。CCDx (x0~5)计数器向下计数时与CCx寄存器匹配。产生PWM下降沿。高级功能事件F (Fault)故障输入信号有效时产生。用于电机驱动、电源中的硬件保护快速关断PWM。TOV (Trigger Overflow)触发溢出事件。复杂定时器级联或同步时使用。REPC (Repeat Counter Zero)重复计数器归零。用于降低中断频率实现“每N个周期中断一次”。DC / QEIERR正交编码器QEI方向改变或错误。电机位置/速度检测。一个重要的细节CCUx/CCDx事件中的x最大到5但并非所有TIMx实例都支持全部6个通道。例如基础定时器TIMG可能只支持CC0-CC3而高级定时器TIMA才支持CC4-CC5。配置前务必查阅具体型号的数据手册。3. 核心模块配置与实操指南理论清晰后我们进入实战环节。配置MSPM0定时器的事件功能本质上就是操作几组关键的寄存器。3.1 CPU中断CPU_INT的配置流程这是最常用的模式让定时器事件触发CPU中断。我们以配置一个1ms的周期性中断为例。步骤1选择并配置时钟源首先确保TIMx的时钟已经使能通过系统时钟控制寄存器。假设我们使用32MHz的系统时钟SYSCLK希望产生1ms中断。定时器通常有时钟预分频器通过CPS寄存器我们先进行分频计算。// 假设目标定时器频率为 1kHz (1ms周期) // 输入时钟 32MHz 所需分频系数 32MHz / 1kHz 32000 // 由于分频器为 (PCNT1)所以 PCNT 31999 TIMx-CPS 31999; // 设置预分频器定时器时钟变为 1kHz步骤2设置计数模式与重载值我们使用递减计数模式从LOAD值减到0产生中断。TIMx-LOAD 999; // 计数器从999开始递减计1000个数0~999为一个周期 // 周期时间 (PCNT1) * (LOAD1) / SYSCLK 32000 * 1000 / 32MHz 1秒等等这里错了注意这里是一个经典的易错点计算必须清晰预分频器将输入时钟分频产生的是定时器的计数时钟TIMCLK。TIMCLK SYSCLK / (PCNT1) 32MHz / 32000 1kHz。计数器每个TIMCLK周期计一次数。我们要的1ms中断意味着计数器需要计数1ms / (1/TIMCLK) 1ms / 1ms 1次这显然不对因为1kHz的TIMCLK本身周期就是1ms。正确的计算逻辑应该是我们希望定时器每隔1ms产生一次中断。定时器计数一次的时间是1 / TIMCLK。若TIMCLK 32MHz 计数一次时间为 31.25ns。要计满1ms需要1ms / 31.25ns 32000次计数。因此LOAD值应设为32000 - 1 31999。如果觉得32MHz计数太快想降低定时器时钟以减少计数器的位数压力可以启用预分频器。例如设置PCNT 31则TIMCLK 32MHz / 32 1MHz。此时1ms需要计数1ms / 1us 1000次。LOAD值设为999。我们采用后一种方案预分频后TIMCLK为1MHzTIMx-CPS 31; // 预分频32 TIMCLK 1MHz TIMx-LOAD 999; // 计数1000次周期为 1000 * (1/1MHz) 1ms TIMx-CTRCTL (0 4) | (0 1) | (1 0); // CM0(递减), REPEAT0(单次), EN1(使能) // CVAE0 使能时计数器加载LOAD值步骤3使能CPU中断事件我们需要告诉定时器当“零事件”Z发生时通过CPU_INT通道去申请中断。// 1. 在IMASK寄存器中解除Z事件的屏蔽即允许其触发中断 TIMx-CPU_INT.IMASK | (1 0); // 设置Z位为1允许Zero事件中断 // 2. 可选但推荐清除可能存在的旧中断标志 TIMx-CPU_INT.ICLR | (1 0); // 向ICLR寄存器的Z位写1清除中断标志 // 3. 在NVIC中使能该定时器的中断此步骤属于系统中断配置与TIMx寄存器无关 // NVIC_EnableIRQ(TIMx_IRQn); // 例如 TIMG0_IRQn步骤4编写中断服务程序ISR在中断函数中必须清除中断标志位否则会连续触发中断。void TIMx_IRQHandler(void) { // 读取IIDX可以自动清除最高优先级待处理中断的标志位 uint8_t int_idx TIMx-CPU_INT.IIDX; // 或者通过查询MIS或RIS寄存器并使用ICLR手动清除 if (TIMx-CPU_INT.MIS (1 0)) { // 检查Zero事件中断是否被屏蔽且发生 // 执行1ms周期任务... TIMx-CPU_INT.ICLR | (1 0); // 手动清除Z中断标志 } // ... 处理其他可能的中断源 }3.2 通用事件GEN_EVENT的配置实战通用事件的威力在于外设联动。我们实现一个经典场景用定时器比较匹配事件自动触发ADC开始转换完全无需CPU干预。场景TIMG0的CC0匹配事件触发ADC0的序列转换。步骤1配置发布者TIMG0我们让TIMG0在CC0比较匹配向上计数匹配时通过GEN_EVENT0发布一个事件。// 1. 配置TIMG0为比较模式产生CCU0事件 TIMG0-CCCTL_01[0].COC 0; // CC0作为比较器 TIMG0-CC_01[0] 500; // 比较值 TIMG0-CTRCTL (2 4) | (1 1) | (1 0); // CM2(递增), REPEAT1(自动重载), EN1 // 2. 配置GEN_EVENT0选择事件源为CCU0 // 查表28-25CCU0的IIDX是0x09。我们需要将这个索引配置到GEN_EVENT0的IMASK不对。 // 注意GEN_EVENT0本身是一个“事件通道”它需要关联到一个具体的事件源。 // 实际上对于发布者我们通常配置的是 FPUB_0 寄存器选择通道号。 // 但首先需要确保该事件能路由到GEN_EVENT0。这通常由EVT_MODE寄存器或类似机制全局控制。 // 更常见的做法是在事件管理器Event Manager的配置中将TIMG0的CCU0事件映射到其FPUB_0端口。 // 假设我们使用通道5作为通用事件通道。 TIMG0-FPUB_0 5; // 将TIMG0的发布者端口0连接到系统事件通道5 // 如何将CCU0事件链接到FPUB_0这通常不是直接设置而是通过“事件选择器”实现。 // 在MSPM0中需要配置事件管理器的路由表。但手册指出对于TIMxGEN_EVENT0/1对应的事件源选择是固定的见Table 28-25。 // 这意味着只要TIMG0的CCU0事件发生它就会自动出现在GEN_EVENT0的“待发布事件池”中。 // 我们的任务只是打开这个事件的“发布开关”并将其指向一个具体的通道。 // 这需要配置 TIMx-GEN_EVENT0.IMASK 寄存器使能CCU0事件并可能配置其他路由寄存器。 // 由于手册片段未给出完整的事件管理器全局配置寄存器以下为基于常见逻辑的推断代码 TIMG0-GEN_EVENT0.IMASK | (1 8); // 使能CCU0事件作为通用事件源 (CCU0在IMASK bit8) // 同时需要确保EVT_MODE寄存器中对应的事件线模式是使能的非0。 TIMG0-EVT_MODE (0x2 0); // 假设EVT0_CFG对应CPU_INT EVT1_CFG对应GEN_EVENT0... // 更准确的配置需要参考Event Manager章节(7.2.5)。这里示意关键思路。步骤2配置订阅者ADC0让ADC0订阅系统事件通道5上的事件作为其转换触发源。// 1. 配置ADC0的触发源为事件管理器 ADC0-CTL.TRIGSEL 0x...; // 选择触发源为“事件”具体值查ADC章节 // 2. 配置ADC0的订阅者端口例如FSUB_0连接到同一个通道5 ADC0-FSUB_0 5; // 将ADC0的订阅者端口0连接到系统事件通道5 // 3. 使能ADC的触发转换模式 ADC0-CTL.TRIGEN 1;步骤3联动结果当TIMG0计数器递增到500时硬件自动产生CCU0事件。该事件通过TIMG0的FPUB_0端口发布到系统事件通道5。ADC0的FSUB_0正监听通道5一旦检测到事件立即启动一次ADC转换。整个过程在一个时钟周期内完成CPU完全不知情可以安心休眠或处理其他任务。3.3 订阅者模式配置以外部信号触发定时器动作现在反转角色配置TIMx作为订阅者。例如用比较器COMP的输出上升沿来复位定时器用于实现周期精确的脉冲宽度测量或保护。场景COMP0输出高电平时立即复位TIMG0的计数器。步骤1配置发布者COMP0设置COMP0在输出高电平时通过其FPUB_1发布事件。// 配置COMP0使其输出有效时发布事件到通道3 COMP0-FPUB_1 3; // 发布者端口1连接到通道3 // 需要在COMP模块中使能对应的事件生成通常在其GEN_EVENTx.IMASK中 COMP0-GEN_EVENT0.IMASK | (1 x); // x为COMP输出事件对应的位需查COMP章节步骤2配置订阅者TIMG0让TIMG0订阅通道3的事件并配置该事件触发计数器加载复位。// 1. 配置TIMG0的订阅者端口0连接到通道3 TIMG0-FSUB_0 3; // 2. 配置输入控制选择订阅的事件作为触发源 // 假设使用CC0的输入通道来响应这个事件 TIMG0-IFCTL_01[0].ISEL 5; // 选择输入源为 FSUB0 (事件订阅者端口0) // 3. 配置计数器控制使能外部触发作为加载条件 TIMG0-CTRCTL.LCOND 1; // 例如设置LCOND1表示在所选输入源CC0的上升沿产生加载事件 // 或者更常见的是通过TSEL寄存器选择触发源并启用触发功能 TIMG0-TSEL.ETSEL 0x10; // 选择FSUB0作为外部触发源 (根据Table 28-84) TIMG0-TSEL.TE 1; // 使能触发功能 // 然后设置CTRCTL.LCOND 1 表示在触发边沿产生加载事件 TIMG0-CTRCTL | (1 8); // 设置LCOND字段为1上升沿触发加载完成上述配置后当COMP0输出变高事件通过通道3传递到TIMG0TIMG0会立即将计数器重置为LOAD寄存器的值实现硬件同步复位。4. 关键寄存器详解与避坑指南手册中列出了大量寄存器这里聚焦于事件管理最核心的几个并分享实际配置中的“坑”。4.1 事件模式寄存器EVT_MODE这个寄存器决定了事件线的工作模式非常关键但易被忽略。typedef struct { uint32_t EVT0_CFG : 2; // CPU_INT 事件线模式 uint32_t EVT1_CFG : 2; // GEN_EVENT0 事件线模式 uint32_t EVT2_CFG : 2; // GEN_EVENT1 事件线模式 uint32_t reserved : 26; } EVT_MODE_BITS;模式0禁用该事件线完全关闭。即使事件发生也不会产生任何动作。模式1软件模式事件发生时相应的RIS原始中断状态位会被置位但必须由软件写ICLR寄存器来清除。这是最常用的模式用于需要CPU介入处理的中断。模式2硬件模式事件发生时RIS位会被置位但硬件会在事件被其他模块消费后自动清除它。这种模式用于纯硬件联动如触发DMA如果配置为此模式但CPU去读IIDX或检查RIS标志位可能在你看到之前就消失了导致CPU无法感知事件。避坑指南1 如果你希望用CPU中断处理定时器事件EVT0_CFG对应CPU_INT必须设置为模式1软件模式。如果你配置了通用事件GEN_EVENT0/1并希望它触发CPU中断通过事件管理器路由到CPU的通用中断线那么对应的EVT1_CFG或EVT2_CFG也应设置为模式1。如果仅用于外设间硬件触发则可设置为模式2。4.2 中断索引寄存器IIDX与状态寄存器RIS, MIS, IMASK这是中断处理的核心寄存器组理解它们的关系至关重要。RIS (Raw Interrupt Status)原始中断状态。只要事件发生无论是否被屏蔽对应的位就会置1。它是硬件状态最真实的反映。IMASK (Interrupt Mask)中断屏蔽。某位为1表示允许该事件产生中断或通用事件为0则屏蔽。它像一个开关控制事件是否能继续向下传递。MIS (Masked Interrupt Status)被屏蔽后的中断状态。MIS RIS IMASK。只有被允许未屏蔽且已发生的事件才会在这里显示为1。CPU中断逻辑和通用事件发布逻辑通常看的是MIS的状态。IIDX (Interrupt Index)最高优先级待处理中断索引。这是一个非常聪明的设计。它返回的是当前所有在MIS中置位的、等待处理的事件中优先级最高的那一个的编号如0x01代表Z事件。读取这个寄存器会自动清除该事件在RIS和MIS中的标志位。这为编写高效的、单入口的多事件中断服务程序提供了便利。中断处理的标准流程进入中断服务程序。读取IIDX值获取最高优先级事件编号。根据编号switch-case跳转到对应的处理代码段。在该段代码末尾通常不需要手动清除中断标志因为读IIDX时硬件已经清除了。但是如果该事件源在中断处理期间又发生了重入RIS会再次置位IIDX也会更新。为了安全可以在处理完关键任务后再读取一次IIDX或直接写ICLR清除特定标志。如果使用查询法非中断则应轮询RIS或MIS寄存器并在处理完成后写ICLR清除对应位。避坑指南2IIDX的“自动清除”特性。IIDX的自动清除功能非常方便但要注意它只清除当前IIDX读出的那个最高优先级事件标志。如果同时有多个事件 pending你需要循环读取IIDX直到其返回0以确保所有待处理事件都被处理并清除。否则低优先级事件可能会被“饿死”。void TIMx_IRQHandler(void) { uint8_t int_idx; while ((int_idx TIMx-CPU_INT.IIDX) ! 0) { switch (int_idx) { case 0x01: // Z事件 // 处理周期到 break; case 0x09: // CCU0事件 // 处理比较匹配0 // 如果需要可以在这里手动清除以防万一TIMx-CPU_INT.ICLR | (1 8); break; // ... 处理其他事件 default: // 未知中断清除所有标志位 TIMx-CPU_INT.ICLR 0xFFFFFFFF; break; } } }4.3 发布者/订阅者端口寄存器FPUB_x, FSUB_x这两个寄存器的配置相对简单核心就是CHANID字段。FPUB_x (Publisher Port) 当TIMx内部事件如CCU0发生时如果该事件在对应的GEN_EVENTx.IMASK中被使能且EVT_MODE配置正确则该事件会被发送到FPUB_x寄存器所指定的通道号CHANID上。FSUB_x (Subscriber Port) TIMx会监听该寄存器指定的通道号CHANID。当该通道上有事件发生时TIMx会接收到这个事件并根据IFCTL_xy.ISEL等寄存器的配置将其用作触发、捕获等操作的源。避坑指南3通道冲突与规划。系统的事件通道0-15是共享资源。必须确保同一个通道号在同一时间只被一个发布者使用但可以被多个订阅者监听即一对多广播。在项目初始化时应该规划好各个外设间的事件连接分配唯一的通道号给每个发布者避免冲突。一个实用的方法是定义一个头文件来管理这些通道号常量。// event_channel.h #define EVT_CHAN_TIMG0_TO_ADC0 5 #define EVT_CHAN_COMP0_TO_TIMG0 3 #define EVT_CHAN_ADC0_EOC_TO_DMA 7 // 在配置外设时使用 TIMG0-FPUB_0 EVT_CHAN_TIMG0_TO_ADC0; ADC0-FSUB_0 EVT_CHAN_TIMG0_TO_ADC0;5. 高级应用与调试技巧5.1 使用重复计数器RC降低中断频率在产生高频PWM时我们可能只需要每N个周期处理一次中断例如更新占空比。频繁进入中断是巨大的开销。这时就要用到重复计数器Repeat Counter。原理RC寄存器配置一个初始值例如N-1。每当使能了REPC中断的事件如Z事件发生时硬件会先检查RC值。如果RC不为0则RC减1并抑制本次事件产生中断。只有当RC减到0时事件才会正常产生中断同时硬件自动将RCLD的值重载到RC中开始下一个循环。配置TIMx-RCLD 99; // 设置重载值为99即每100个周期中断一次 TIMx-RC 99; // 初始化RC TIMx-CPU_INT.IMASK | (1 0); // 使能Z事件中断 // 在CTRCTL中确保SLZERCNEZ位根据需求设置。如果设为1则RC非零时连Z事件本身都抑制。 // 在CCCTL中SCERCNEZ位控制RC非零时是否抑制比较事件。效果 PWM频率为100kHz时周期为10us。如果不使用RCCPU每10us就被中断一次占用率极高。设置RCLD99后中断频率降为1kHzCPU负载降至1%。5.2 调试支持PDBGCTL在进行代码调试时我们通常希望定时器在CPU暂停调试器断点时也能停止以便观察静态状态。但有些场景如PWM驱动电机希望定时器继续运行。PDBGCTL寄存器控制此行为。FREE位 默认为0表示当CPU因调试暂停时定时器也暂停。设为1则定时器忽略CPU调试状态自由运行。SOFT位 与FREE0STOP模式配合使用。为0时调试暂停立即生效可能导致PWM输出停在任意状态半高电平可能损坏外部电路。为1时定时器会等待到达一个“安全边界”如PWM周期结束后再暂停更为安全。调试建议 在开发阶段保持FREE0以便观察定时器寄存器。在测试电机等实际负载时根据情况考虑设置FREE1或SOFT1避免调试操作引入风险。5.3 故障Fault处理与硬件保护高级定时器TIMA支持故障输入用于实现硬件级的快速保护。例如在电机驱动中过流信号通过比较器或GPIO接入故障引脚。配置流程配置故障源 在FSCTL寄存器中使能对应的故障输入如FEX0EN使能外部故障引脚0并设置有效电平FCTL.FSENEXT0。配置滤波 通过FIFCTL寄存器为故障输入添加数字滤波防止噪声误触发。配置故障行为 在CCACT_xy寄存器中设置FENACT故障进入动作和FEXACT故障退出动作。例如可以设置为故障发生时立即将PWM输出强制为低电平或高阻态FENACT4故障解除后自动恢复FEXACT0。使能故障 设置FCTL.FIEN1。中断处理 如果需要CPU通知使能CPU_INT.IMASK中的F位中断。故障保护的反应速度是纳秒级的远快于任何软件中断是保证系统安全的关键。5.4 常见问题排查速查表现象可能原因排查步骤中断无法进入1. NVIC未使能。2.IMASK未使能对应事件。3.EVT_MODE配置为禁用或硬件模式。4. 中断标志未清除导致持续占用。1. 检查NVIC_EnableIRQ。2. 检查TIMx-CPU_INT.IMASK。3. 检查TIMx-EVT_MODE.EVT0_CFG是否为1。4. 在ISR中读取IIDX或写ICLR清除标志。通用事件无法触发外设1. 发布者FPUB_x.CHANID与订阅者FSUB_x.CHANID不匹配。2. 事件未在发布者的GEN_EVENTx.IMASK中使能。3. 订阅者外设未正确配置为事件触发模式。4. 事件通道被其他发布者占用。1. 核对通道号。2. 检查TIMx-GEN_EVENT0.IMASK等。3. 检查ADC/等其他外设的触发源选择寄存器。4. 检查整个系统的事件通道分配。中断处理时间过长或丢失1. 中断频率过高超过CPU处理能力。2. ISR中未及时清除标志导致重复进入。3. 中断优先级配置不当被高优先级中断阻塞。1. 使用重复计数器RC降低中断频率。2. 确保使用IIDX或ICLR清除标志。3. 在NVIC中合理分配中断优先级。定时器动作与事件不同步1. 使用了EVT_MODE的硬件自动清除模式但CPU试图查询标志。2. 事件滤波IFCTL或故障滤波FIFCTL设置过长引入延迟。1. 对于需要CPU查询的事件使用软件模式EVT_MODE1。2. 调整滤波参数FP在抗噪和延迟间权衡。使用IIDX后仍有中断挂起同时发生多个中断IIDX只清除了最高优先级的一个。在ISR中使用while循环读取IIDX直到其为0。深入理解并熟练运用MSPM0定时器的中断与事件机制能够让你设计的嵌入式系统从“够用”跃升到“高效、可靠、优雅”。它不仅仅是功能的堆砌更是硬件资源协同的艺术。花时间梳理清楚事件流的走向规划好通道资源你的系统就能以最少的CPU干预完成最复杂的实时控制任务。