1. 从寄存器手册到实战代码:Tiva C系列PWM中断与装载机制深度剖析
如果你正在用Tiva C系列(比如TM4C123GH6ZRB)做电机控制、LED调光或者开关电源,那你肯定绕不开它的PWM模块。数据手册里关于PWMnRIS、PWMnISC、PWMnLOAD这些寄存器的描述,密密麻麻,看懂了每个位的意思,但一到写代码,还是不知道怎么把它们串起来,实现一个既稳定又能及时响应中断的PWM输出。我当年调一个无刷电机驱动,就在中断状态清除的时序上栽过跟头,明明逻辑都对,可中断就是偶尔会丢,或者响应延迟飘忽不定。后来把手册里那几行关于“PWM时钟分频器值越大,清除中断的系统延迟越长”的小字注释,结合实际的寄存器操作顺序反复琢磨,才彻底搞明白。今天,我就把这些从手册字里行间抠出来、又经过实际项目验证的经验,掰开揉碎了讲给你听。我们不止看寄存器定义,更要弄懂它们如何在PWM发生器的计数循环中协同工作,以及你在写驱动时,该如何正确、高效地配置和使用它们,避开那些新手容易踩的坑。
2. PWM中断状态寄存器组:事件捕捉与状态管理核心
在Tiva C的PWM模块中,中断管理不是由一个寄存器完成的,而是一组寄存器精密协作的结果。理解这组寄存器的层次关系,是写出可靠中断服务程序(ISR)的第一步。很多人只关心PWMnISC,因为它直接关联到CPU中断,但如果不清楚PWMnRIS和PWMnINTEN的作用,调试时会非常头疼。
2.1 PWMnRIS:最原始的事件“传感器”
PWMnRIS(Raw Interrupt Status)寄存器,我习惯把它叫做“原始中断状态寄存器”。它的角色非常纯粹:一个只读的、实时反映硬件事件是否发生的状态传感器。无论你是否使能了中断,只要PWM发生器内部发生了特定事件(比如计数器归零、匹配了比较值),对应的位就会被硬件自动置1。
以PWM0为例,其PWM0RIS寄存器在内存映射中的基址是0x4002.8000,偏移量是0x048。它的低6位(bit 0 - bit 5)分别对应6个关键事件:
- INTCNTZERO (Bit 0): 计数器值等于0。这是每个PWM周期结束的标志。
- INTCNTLOAD (Bit 1): 计数器值等于装载值(
PWMnLOAD)。在递增-递减计数模式下,这是计数达到峰值的点。 - INTCMPAU (Bit 2): 在计数器递增过程中,其值等于比较器A的值(
PWMnCMPA)。 - INTCMPAD (Bit 3): 在计数器递减过程中,其值等于比较器A的值。
- INTCMPBU (Bit 4): 在计数器递增过程中,其值等于比较器B的值(
PWMnCMPB)。 - INTCMPBD (Bit 5): 在计数器递减过程中,其值等于比较器B的值。
这里有一个至关重要的细节:PWMnRIS的位不能通过直接向该寄存器写入来清除。手册里明确写着,需要通过向PWMnISC寄存器的对应位写1来间接清除。这设计初看有点绕,但其实是为了防止软件在状态采样时发生竞态条件。你可以把PWMnRIS想象成一个不断被硬件置位的“事件发生标志”,而PWMnISC是管理“是否向上汇报”以及“清除标志”的开关。
实操心得:在调试初期,我强烈建议你定期读取
PWMnRIS的值(比如在main loop里打印出来),而不是只依赖中断。这能帮你直观地确认硬件事件是否按预期发生。例如,如果你配置了比较匹配中断但一直没触发,先查PWMnRIS对应位有没有变成1。如果没有,问题出在PWM发生器配置(比如计数器模式、比较值大于装载值等);如果PWMnRIS位已经是1但没进中断,那问题就在中断使能或状态清除环节。
2.2 PWMnISC:中断控制器的“门卫”与状态清除器
PWMnISC(Interrupt Status and Clear)寄存器,我称之为“中断状态与清除寄存器”。它的地址紧挨着PWMnRIS(偏移0x04C),功能上则承上启下。这个寄存器有双重身份:
- 中断状态指示:它显示已经发生且已被使能、并已提交到嵌套向量中断控制器(NVIC)的中断事件状态。换句话说,一个事件要在这里置位,必须同时满足:
PWMnRIS中对应位为1(事件发生),且PWMnINTEN中对应中断使能位为1(允许上报)。 - 中断状态清除:这是一个
R/W1C(Read/Write-1-to-Clear)类型的寄存器。向某个位写1,会同时完成两件事:清除PWMnISC自身的该状态位,并且联动清除PWMnRIS寄存器中的对应位。这是清除中断pending状态的唯一正确方式。
PWMnISC的位定义与PWMnRIS完全一致。当你进入PWM中断服务程序后,第一件事通常就是读取PWMnISC(或PWMnRIS)来判断是哪个事件触发的中断,然后向PWMnISC的对应位写1来清除中断标志。
这里隐藏着一个极其关键的时序陷阱,手册用“注意”小字标出,却足以让你的系统变得不稳定:“中断状态只能在发生中断后一个PWM时钟周期进行清除。”并且,PWMCC寄存器中的PWMDIV分频值越大,这个可安全清除的窗口就越长。这意味着,如果你在中断发生后立即(在同一个PWM时钟周期内)尝试清除标志,操作可能无效,导致中断不断重复触发,仿佛“锁死”在中断里。安全的做法是在ISR开始时,稍作延迟(例如插入几条NOP指令),或者更稳妥的是,先读取一次状态,再进行清除操作。
2.3 PWMnINTEN:中断事件的“使能开关”
PWMnINTEN(Interrupt Enable)寄存器虽然没有在提供的材料中详细列出,但它是中断链路中不可或缺的一环。它决定了PWMnRIS中的哪些事件被允许提交到中断控制器。它的位布局与前两个寄存器类似,但类型是R/W。你需要先在这里使能特定事件的中断(例如使能INTCMPAU),之后当该事件发生且PWMnRIS置位时,PWMnISC才会置位,并最终向NVIC发出中断请求。
中断信号产生与清除的全流程:
- 事件发生:PWM计数器运行,匹配了
LOAD、CMPA或0。硬件自动将PWMnRIS对应位置1。 - 条件判断:硬件检查
PWMnINTEN中对应位是否为1。 - 中断上报:如果使能,硬件将
PWMnISC对应位置1,并向NVIC发出中断请求。 - CPU响应:若NVIC和全局中断已使能,CPU跳转至ISR。
- 状态清除(在ISR内): a. 读取
PWMnISC或PWMnRIS确定中断源。 b.等待至少一个PWM时钟周期(重要!)。 c. 向PWMnISC的对应位写1。此操作将同时清除PWMnISC和PWMnRIS的该位。 d. 必要时,向NVIC相关寄存器写1清除中断pending位。 - 中断返回:中断标志已清除,CPU退出ISR,等待下一次事件。
3. PWM装载与计数寄存器:波形周期的基石
PWM信号的频率(或周期)是由计数器的计数范围决定的,而PWMnLOAD和PWMnCOUNT这对寄存器正是控制这个范围的核心。
3.1 PWMnLOAD:定义计数周期的“天花板”
PWMnLOAD寄存器存放着一个16位的装载值。这个值决定了PWM计数器的计数上限,是计算PWM频率的公式中的关键变量。它的工作模式与PWMnCTL寄存器中的MODE位密切相关:
- 递减计数模式(MODE = 0):计数器从
LOAD值开始递减,减到0后,自动重载LOAD值,开始下一个周期。此时,PWM周期 = (LOAD+ 1) * PWM时钟周期。 - 递增-递减计数模式(MODE = 1):计数器从0开始递增,达到
LOAD值后转为递减,回到0后开始下一个周期。此时,PWM周期 = 2 *LOAD* PWM时钟周期。
装载值更新机制是另一个需要精细控制的点,由PWMnCTL的LOADUPD位域控制:
- 立即更新(Immediate Update):新写入
PWMnLOAD的值立即生效。这可能导致当前周期长度突变,产生非对称或毛刺波形,通常不推荐在PWM输出使能时使用。 - 局部同步更新(Local Synchronous Update):新写入的值会被缓存,在当前计数器下一次到达0时才真正加载生效。这能保证PWM周期在边界处平滑切换,是动态调整频率时的常用模式。
- 全局同步更新(Global Synchronous Update):多个PWM发生器需要严格同步更新时使用。新值写入后,需要向
PWMCTL(主控制寄存器)的SYNC位写1发出同步信号,所有配置为全局同步的PWM发生器会在各自的下一个计数器归零点统一更新。
注意事项:
PWMnLOAD寄存器必须大于PWMnCMPA和PWMnCMPB的值,否则比较匹配事件永远不会发生,相应的中断和输出动作也会失效。在初始化时,应先配置LOAD,再配置CMPA/CMPB。在运行时动态修改占空比(即修改CMPx)和频率(修改LOAD)时,要特别注意更新模式的选择和时序,避免产生意外的脉冲。
3.2 PWMnCOUNT:计数器的实时“快照”
PWMnCOUNT是一个只读寄存器,让你能随时读取PWM计数器当前的瞬时值。这在调试和某些高级应用(如电流环控制中获取精确的采样时刻)中非常有用。手册里特别提醒了一点:通过清零PWMnCTL的ENABLE位来禁用PWM发生器,并不会清零PWMnCOUNT寄存器。计数器会保持在被禁用时的值。如果你希望计数器从0开始重新计数,必须在重新使能(ENABLE=1)前,通过系统控制模块的SRPWM(软件复位PWM)寄存器对整个PWM模块进行复位,或者确保在使能前配置为从0开始计数的模式(如递增-递减模式)。
装载与计数寄存器协同工作流程示例(递减模式):
- 初始化:设置
PWMnLOAD = 999,PWMnCMPA = 300。 - 使能计数器:计数器从999开始递减。
- 计数过程:
- 计数器值从999变化到301:无事件。
- 计数器值变为300:匹配
CMPA,若中断使能则PWMnRIS.INTCMPAD置位。 - 计数器继续递减到1:无事件。
- 计数器值变为0:匹配
Zero,PWMnRIS.INTCNTZERO置位,同时计数器自动重载999,开始新周期。
- 动态调整:若想将占空比从30%改为50%,可在某个周期内(通常是在中断服务程序中)将
PWMnCMPA改为500。根据更新模式,新值会在下一个合适的时间点生效。
4. 比较寄存器与发生器控制:塑造PWM波形细节
PWMnCMPA/B和PWMnGENA/B寄存器共同决定了PWM输出引脚(pwmA, pwmB)上具体波形的高低电平时序,也就是占空比和相位。
4.1 PWMnCMPA/B:设定波形翻转的“时间点”
PWMnCMPA和PWMnCMPB是两个独立的16位比较寄存器。它们的值会与运行中的计数器值进行实时比较。当匹配发生时,会产生一个内部的“比较匹配脉冲”。这个脉冲本身不会直接改变输出引脚,它需要被PWMnGENA或PWMnGENB寄存器“翻译”成具体的动作(如翻转电平、拉高、拉低)。
和PWMnLOAD一样,CMPA/B也支持立即、局部同步、全局同步三种更新模式,由PWMnCTL中的CMPAUPD和CMPBUPD位控制。动态调整占空比的核心就是安全地更新这两个寄存器。局部同步模式是最常用的,它能确保在新的PWM周期开始时应用新的比较值,避免在当前周期中间产生毛刺。
占空比计算公式:
- 递减模式:占空比 = (
LOAD-CMPA+ 1) / (LOAD+ 1) 例如,LOAD=999,CMPA=300,则高电平时间对应计数器从999到300(共700个时钟),占空比 ≈ 700/1000 = 70%。注意,具体输出是高电平有效还是低电平有效,还需由发生器控制寄存器决定。 - 递增-递减模式:波形通常对称。输出动作可能在递增和递减阶段各发生一次,形成中心对齐的PWM,常用于电机控制和音频应用,能减少谐波干扰。
4.2 PWMnGENA/B:波形生成的“动作翻译官”
这是PWM模块最灵活也最核心的部分。PWMnGENA控制pwmA输出引脚,PWMnGENB控制pwmB输出引脚。它们定义了当6个特定事件(CNT=0,CNT=LOAD,CMPA递增匹配,CMPA递减匹配,CMPB递增匹配,CMPB递减匹配)中的任何一个发生时,输出引脚应该执行什么动作。
每个事件对应一个2位的动作域(ACTZERO,ACTLOAD,ACTCMPAU,ACTCMPAD,ACTCMPBU,ACTCMPBD),可以配置为:
0x0: 不动作。0x1: 翻转(Toggle)输出电平。0x2: 驱动输出为低电平。0x3: 驱动输出为高电平。
通过精心配置这些动作,你可以生成非常复杂的PWM波形。例如,要产生一个简单的边沿对齐PWM(递减模式,高电平有效):
- 当
CNT=LOAD(周期开始)时:设置ACTLOAD = 0x3(驱动为高)。 - 当
CNT=CMPA(匹配比较值)时:设置ACTCMPAD = 0x2(驱动为低)。 - 当
CNT=0时:可以不动作或设置为其他,因为在下个周期开始时ACTLOAD会再次将其拉高。
对于递增-递减模式,要产生中心对齐PWM:
- 当
CNT=0时:设置ACTZERO = 0x3(驱动为高)。 - 当递增计数匹配
CMPA(INTCMPAU)时:设置ACTCMPAU = 0x2(驱动为低)。 - 当递减计数再次匹配
CMPA(INTCMPAD)时:设置ACTCMPAD = 0x3(驱动为高)。
事件优先级规则:手册明确指出了事件冲突时的处理规则,这在配置复杂波形时必须牢记:
- 如果“零事件”或“装载事件”与某个“比较事件”发生在同一时刻,则执行零或装载动作,比较动作被忽略。
- 如果“比较器A事件”与“比较器B事件”发生在同一时刻,则执行比较器A动作,比较器B动作被忽略。 这意味着,你不能指望在计数器等于
LOAD的同一个时钟周期,又因为等于CMPA而触发另一个不同的动作。硬件会优先执行LOAD或ZERO动作。
5. 实战配置与代码示例:从寄存器到可运行的PWM
理解了原理,我们来看如何用代码配置一个完整的、带中断的PWM通道。以下以TM4C123GH6ZRB的PWM0发生器0,输出PWM0A(PF2引脚)为例,配置为递减计数模式,频率1kHz,初始占空比50%,并在每个周期结束时(CNT=0)触发中断。
5.1 系统与引脚初始化
首先,需要启用外设时钟并配置引脚功能。
#include <stdint.h> #include "tm4c123gh6pm.h" // 包含寄存器定义的头文件 void PWM0_Init(void) { // 1. 启用PWM0和GPIOF外设时钟 SYSCTL->RCGCPWM |= 0x01; // 启用PWM0模块时钟 SYSCTL->RCGCGPIO |= 0x20; // 启用GPIOF端口时钟 while((SYSCTL->PRGPIO & 0x20) == 0) {}; // 等待GPIOF就绪 // 2. 配置PF2引脚为PWM0A功能 GPIOF->AFSEL |= 0x04; // 启用PF2的备用功能 GPIOF->PCTL = (GPIOF->PCTL & 0xFFFFF0FF) | (0x5 << 8); // PF2配置为PWM0A GPIOF->DEN |= 0x04; // 使能PF2数字功能 GPIOF->AMSEL &= ~0x04; // 禁用模拟功能(如果使能了)5.2 PWM发生器配置
接下来,配置PWM发生器0的工作模式、时钟分频和周期。
// 3. 配置PWM时钟分频(假设系统时钟为80MHz,目标PWM时钟为10MHz) // PWM时钟 = 系统时钟 / (PWM分频因子 * 2)。PWMDIV = 0x4 代表分频因子为8。 SYSCTL->RCC &= ~SYSCTL_RCC_USEPWMDIV; // 先禁用分频器更新 SYSCTL->RCC |= SYSCTL_RCC_PWMDIV_8; // 设置分频为8 SYSCTL->RCC |= SYSCTL_RCC_USEPWMDIV; // 启用新的分频设置 // 此时PWM时钟 = 80MHz / (8*2) = 5MHz // 4. 禁用PWM0发生器0,以便安全配置 PWM0->_0_CTL &= ~PWM_0_CTL_ENABLE; // 5. 配置为递减计数模式,装载值更新模式为局部同步 PWM0->_0_CTL = (PWM0->_0_CTL & ~PWM_0_CTL_MODE) | (0 << 0); // MODE=0, 递减模式 PWM0->_0_CTL = (PWM0->_0_CTL & ~PWM_0_CTL_LOADUPD) | (0x1 << 2); // LOADUPD=01, 局部同步 // 6. 设置PWM周期(装载值) // 目标频率1kHz,PWM时钟5MHz。递减模式周期 = (LOAD + 1) / PWM_CLK。 // LOAD = (PWM_CLK / Freq) - 1 = (5,000,000 / 1000) - 1 = 4999 PWM0->_0_LOAD = 4999; // 设置周期 // 7. 设置初始占空比(比较器A值) // 占空比 = (LOAD - CMPA + 1) / (LOAD + 1)。50%占空比 => CMPA = LOAD / 2 = 2500 (约) // 更精确计算:高电平时间 = (LOAD - CMPA + 1)个时钟。设占空比D=0.5,则 CMPA = LOAD + 1 - D*(LOAD+1) // CMPA = 5000 - 0.5*5000 = 2500 PWM0->_0_CMPA = 2500; // 8. 配置发生器A动作(产生PWM0A波形) // 递减模式,高电平有效:CNT=LOAD时拉高,CNT=CMPA时拉低。 PWM0->_0_GENA = (PWM0->_0_GENA & ~(PWM_0_GENA_ACTLOAD_M | PWM_0_GENA_ACTCMPAD_M)) | (PWM_0_GENA_ACTLOAD_HIGH << PWM_0_GENA_ACTLOAD_S) // LOAD时驱动为高 | (PWM_0_GENA_ACTCMPAD_LOW << PWM_0_GENA_ACTCMPAD_S); // CMPA递减匹配时驱动为低5.3 中断配置与使能
最后,配置中断,并使能PWM输出。
// 9. 使能计数器归零中断 PWM0->_0_INTEN |= PWM_INTEN_INTCNTZERO; // 使能CNT=0中断 // 10. 清除可能存在的原始中断标志(PWMnRIS)和中断状态(PWMnISC) // 先读一次PWM0RIS,然后向PWM0ISC对应位写1清除。 volatile uint32_t dummy = PWM0->_0_RIS; // 读取原始状态,可忽略结果 PWM0->_0_ISC |= PWM_ISC_INTCNTZERO; // 写1清除CNT=0中断状态 // 11. 在NVIC中使能PWM0中断(中断号PWM0_0,需查数据手册或头文件) // 假设PWM0发生器0的中断向量号为PWM0_0_IRQn NVIC_EnableIRQ(PWM0_0_IRQn); NVIC_SetPriority(PWM0_0_IRQn, 2); // 设置中断优先级 // 12. 使能PWM0发生器0,开始输出 PWM0->_0_CTL |= PWM_0_CTL_ENABLE; // 13. 使能PWM0的PWM0A输出 PWM0->ENABLE |= PWM_ENABLE_PWM0EN; }5.4 中断服务程序(ISR)实现
ISR中必须安全地清除中断标志。
void PWM0_0_IRQHandler(void) { // 1. 读取中断状态寄存器,判断中断源(这里我们只使能了INTCNTZERO) uint32_t status = PWM0->_0_RIS; // 或读取PWM0->_0_ISC if (status & PWM_RIS_INTCNTZERO) { // 2. 执行你的周期任务,例如更新比较值以动态调整占空比 // static uint16_t newCmpA = 1000; // PWM0->_0_CMPA = newCmpA; // 局部同步模式,下个周期生效 // newCmpA = (newCmpA + 100) % 5000; // 示例:动态变化 // 3. 关键:等待至少一个PWM时钟周期后再清除标志 // 简单方法:插入一个短暂延时或执行几条无关指令。 __asm(" NOP\n NOP\n NOP\n NOP\n"); // 插入几个空指令,提供延迟 // 4. 清除中断标志(向PWM0ISC对应位写1) PWM0->_0_ISC |= PWM_ISC_INTCNTZERO; // 此操作会同时清除PWM0ISC和PWM0RIS的对应位 } // 注意:如果使能了多个中断源,需要检查并清除所有触发的中断标志。 }6. 高级应用与疑难问题排查
掌握了基础配置后,面对更复杂的应用场景和调试时的“灵异”现象,你需要更深入的理解和排查手段。
6.1 双通道互补PWM与死区插入
在电机驱动(如H桥)中,常需生成一对互补的PWM信号(PWM0A和PWM0B),并插入死区时间防止上下桥臂直通。Tiva PWM模块的“死区发生器”功能可以自动实现。
- 配置互补输出:将PWM0A和PWM0B配置为互补模式(通过
PWMnCTL寄存器相关位设置)。 - 使能死区发生器:在
PWM0DBCTL寄存器中使能死区功能。 - 设置死区时间:通过
PWM0DBRISE(上升沿延迟)和PWM0DBFALL(下降沿延迟)寄存器设置死区时钟周期数。死区时间 = 设置值 * PWM时钟周期。 - 发生器配置:此时,你通常只需配置
PWM0_GENA来定义PWM0A的波形,PWM0B会自动生成互补信号,并由硬件插入死区。中断配置和之前类似,但要注意死区的插入可能会略微影响你基于比较值计算的精确导通时间。
6.2 中断丢失与响应延迟问题排查
这是调试PWM中断时最常见的问题。
- 现象:中断根本进不去
- 检查NVIC配置:确认
NVIC_EnableIRQ已调用,且中断优先级设置正确。 - 检查全局中断:确认在
main函数中调用了__enable_irq()或类似函数开启了全局中断。 - 检查PWMnINTEN:确认你希望触发中断的事件(如
INTCNTZERO)已在该寄存器中使能。 - 检查PWMnRIS:在main loop中打印该寄存器值,看硬件事件是否真的发生。如果没发生,检查
LOAD、CMPA、计数器模式配置是否正确。
- 检查NVIC配置:确认
- 现象:中断只进入一次,之后不再触发
- 中断标志未清除:这是最可能的原因。确保在ISR中清除了
PWMnISC(不是PWMnRIS)的对应位。 - 清除时序问题:你很可能踩中了“中断后需等待一个PWM时钟周期才能清除”的坑。确保在ISR中清除标志前有足够延迟(如前述的NOP指令)。一个更稳健的做法是,在ISR中先读取一次
PWMnISC的值(这个读取操作本身会引入微小延迟),然后再进行清除操作。 - PWM时钟分频过大:如果
PWMDIV设置得很大(比如分频值64),PWM时钟很慢,那么从事件发生到允许清除标志的延迟窗口会很长。在低速PWM下,需要在ISR中等待更久,或者考虑使用其他同步方式(如查询PWMnRIS)代替中断。
- 中断标志未清除:这是最可能的原因。确保在ISR中清除了
- 现象:中断响应时间不稳定(抖动)
- 中断优先级:确保PWM中断的优先级足够高,不会被其他长时间中断阻塞。
- 系统负载:检查是否有其他高优先级中断或任务频繁关中断。
- 缓存与内存访问:对PWM寄存器的访问速度也会影响响应。确保代码运行在零等待状态的存储器上。
6.3 动态调整频率与占空比的同步策略
在运行中改变PWM频率(LOAD)或占空比(CMPA/CMPB)时,必须考虑同步,否则会导致输出波形出现毛刺或短脉冲。
- 仅调整占空比(CMPA/CMPB):使用局部同步更新模式(
CMPAUPD/CMPBUPD = 0x1)是最安全、最常用的。新写入的比较值会在当前计数器下一次归零时加载,从而在完整的PWM周期边界切换,保证波形连续。 - 调整频率(LOAD):也必须使用局部同步更新模式(
LOADUPD = 0x1)。同样,新LOAD值在下一个计数器归零时生效。需要注意的是,改变LOAD的同时,可能需要按比例调整CMPA/CMPB以保持相同的占空比,且必须确保新的CMPx值小于新的LOAD值。 - 多通道同步调整:如果需要同时改变多个PWM发生器的参数并保持严格同步,应使用全局同步更新模式。将所有相关发生器的更新模式设置为全局同步,然后修改它们的
LOAD/CMPx值,最后向PWMCTL寄存器的SYNC位写1。所有发生器会在各自的下一个计数器归零点统一应用新值。
一个常见的错误是:在中断服务程序中直接写入新的比较值,而没有考虑更新模式。如果配置为立即更新,且写入发生在计数器值接近比较值的时刻,可能导致当前周期输出异常。因此,在中断中动态调整参数��强烈推荐使用局部同步模式。
6.4 使用PWM触发ADC采样
Tiva PWM模块可以生成精确的触发信号来启动ADC转换,这对于电源环路控制等需要定时采样的应用非常有用。
- 配置ADC触发源:在
PWM0INTEN或PWM1INTEN等寄存器中,不仅有中断使能位,还有ADC触发使能位(如INTCNTZERO对应的ADCEN位)。使能你希望作为触发源的事件(例如,每次PWM周期开始CNT=LOAD时触发)。 - 配置ADC模块:将ADC配置为外部触发模式,并选择对应的PWM发生器作为触发源(例如,
ADC0_PSSI寄存器中配置触发源为PWM)。 - 同步时序:PWM事件产生的触发脉冲会启动ADC转换。你需要计算从触发到ADC采样完成的时间,以确保采样点位于你期望的模拟信号稳定阶段(例如,在PWM驱动MOSFET的中点或末端进行电流采样)。
通过将PWM中断、ADC采样和软件计算(如PID)结合起来,就能构建一个完整的数字闭环控制系统。这时,PWM中断的及时性和确定性就显得至关重要,这也是为什么我们必须透彻理解其中断状态寄存器的运作和清除机制。