1. 项目概述:为什么我们需要高分辨率PWM?
在数字电源和电机驱动的世界里,PWM信号的精度直接决定了系统的效率和性能天花板。传统的PWM,其时间分辨率被限制在系统时钟(TBCLK)的一个周期内。举个例子,如果你的系统时钟是100MHz(周期10ns),那么你所能控制的最小时间单位就是10ns。对于追求极致效率的开关电源,或者需要高信噪比的PWM型数模转换器(DAC)来说,这个“颗粒度”就太粗糙了。
想象一下,你要用一把最小刻度是1厘米的尺子去测量一张纸的厚度,这显然力不从心。传统PWM在控制占空比或死区时间时,就面临着类似的窘境。你只能以10ns为步进来调整,这可能导致:
- 开关损耗增加:在硬开关拓扑中,无法精确地将开关时刻对准电压或电流的谷底/零点,造成额外的开关损耗和电磁干扰。
- 控制精度受限:在精密控制中,例如生成一个非常精确的模拟电压,10ns的步进会引入可观的量化误差,限制系统的动态范围和线性度。
- 死区控制不理想:死区时间是为了防止桥臂直通而设置的,但过大的死区会降低输出电压基波,增加谐波;过小的死区则有直通风险。传统PWM很难设置一个“刚刚好”的死区。
高分辨率脉宽调制(HRPWM)技术,就是为了打破这个分辨率壁垒而生的。它的核心思想,是在不改变系统主时钟频率的前提下,通过一种名为微边沿定位器(MEP)的硬件模块,在每一个标准的PWM时钟周期(EPWMCLK)内,再插入多达255个更精细的时间步进。每个MEP步进的大小通常在150皮秒(ps)量级,这相当于将我们的“尺子”的最小刻度从10纳米(对应10ns)提升到了0.15纳米,分辨率提升了两个数量级以上。
这项技术对于使用TI C2000系列微控制器的工程师来说,是实现高性能数字功率转换、伺服驱动和信号生成不可或缺的工具。它让你能以皮秒级的精度“雕刻”PWM波的边沿,从而实现对功率器件开关行为的极致优化。
2. HRPWM核心原理与MEP工作机制拆解
要玩转HRPWM,必须吃透它的心脏——微边沿定位器(MEP)。很多人看了手册还是一头雾水,觉得它很神秘,其实它的工作原理可以用一个简单的类比来理解。
2.1 MEP:你的皮秒级“雕刻刀”
把传统的PWM周期(比如10ns)想象成一根标准长度的“木条”。传统PWM只能在这根木条的起点或终点进行“切割”,决定信号的高低电平。而MEP的作用,是让你能在这根木条上,以极高的精度标记一个“切割点”。
MEP是如何工作的?MEP模块内部有一套精密的延迟链或插值电路。它接收来自ePWM模块的比较匹配(CMPA/CMPB)或周期(TBPRD)等事件,但这个事件的时间点不再是“立刻生效”,而是被MEP进行“微调”。
- 粗调步进(Coarse Step):这就是传统的PWM时钟周期(TBCLK/EPWMCLK),比如10ns。它决定了边沿移动的“大格子”。
- 微调步进(MEP Step):在每个“大格子”内部,MEP可以产生最多255个均匀的、更小的时间间隔。每个MEP Step的大小就是MEP步进尺寸(MEP Step Size),典型值如150ps。
所以,你最终输出的PWM边沿位置 =粗调步进数 × 粗调步进周期 + 微调步进数 × MEP步进尺寸。
2.2 核心寄存器:CMPAHR与HRCNFG
理解了原理,我们来看如何控制它。HRPWM功能主要通过扩展已有的ePWM寄存器来实现,其中最关键的两个是:
CMPAHR (高分辨率比较寄存器):这是一个24位的寄存器(对于某些型号是16位),它通常与标准的CMPA寄存器配对使用。你可以把它理解为CMPA的“小数部分”。
- 标准CMPA:存放整数部分的粗调步进数。
- CMPAHR:存放小数部分的微调步进数。软件需要根据所需的精确时间,计算出对应的数值并写入。
HRCNFG (高分辨率配置寄存器):这个寄存器决定了HRPWM的工作模式。
EDGMODE:控制哪个边沿使用高分辨率。可以是上升沿(HR_REP)、下降沿(HR_FEP)或双边沿(HR_BEP)。CTLMODE:选择由哪个寄存器来控制高分辨率边沿。通常是HR_CMP,即由CMPAHR/CMPBHR控制。HRLOAD:选择高分辨率寄存器的装载时机,例如在计数器为零时(HR_CTR_ZERO)。AUTOCONV(自动转换位):这是一个极其重要的位。当它置1时,硬件会自动帮你完成从“期望的分数时间”到“CMPAHR寄存器值”的转换。你只需要提供分数值,剩下的MEP步进计算由硬件完成。这大大简化了软件设计。
2.3 MEP比例因子(MEP_ScaleFactor)的挑战
这里出现了一个关键问题:MEP步进尺寸(MEP Step Size)不是固定不变的。它会随着芯片的制造工艺、工作温度(V)和核心电压(V)的变化而漂移。数据手册给出的150ps是一个典型值,实际可能在几十皮秒到几百皮秒之间变化。
这意味着,如果你在软件中写死一个基于150ps的计算系数,当温度从-40°C升到125°C,或者电压波动时,你实际输出的PWM边沿位置就会偏离预期,HRPWM的精度优势将荡然无存。
这就引出了TI提供的解决方案:SFO库。
3. SFO库:让HRPWM精度“稳如泰山”
SFO(Scale Factor Optimizer)库是TI提供的一个软件函数库,它的唯一使命就是:动态地、实时地测量出当前芯片在当前工作条件下的准确MEP_ScaleFactor值。
3.1 SFO库的工作原理与调用
SFO库的核心函数是int SFO()。它内部利用了HRPWM模块内置的自检和诊断逻辑,这个逻辑独立于所有ePWM通道运行。当你调用SFO()时,它会启动一个校准过程:
- 诊断运行:硬件诊断逻辑会测量在当前的温度、电压和工艺条件下,一个EPWMCLK周期内最多能容纳多少个MEP步进。
- 计算比例因子:将这个测量值作为新的
MEP_ScaleFactor更新到HRMSTEP寄存器,并作为函数返回值更新到你定义的全局变量中。 - 状态返回:函数返回一个状态值。
0:校准正在进行中,尚未完成。1:校准完成,新的MEP_ScaleFactor已就绪。2:错误。测量到的MEP步进数超过了255(即一个EPWMCLK周期放不下),这通常发生在EPWMCLK频率过低(低于50MHz)或极端环境条件下。
> 注意:SFO()函数执行一次完整的校准需要大约130,000个EPWMCLK周期。在100MHz系统时钟下,这大约是1.3ms。因此,它不适合在极高频率的中断中调用,而应作为后台任务周期性执行。
3.2 集成SFO库到你的工程:四步法
根据手册,将SFO库集成到你的C2000项目非常标准化:
步骤1:添加头文件在你的主源文件或HRPWM相关模块中,包含必要的头文件。SFO_V8.h是必须的,它包含了函数声明和必要的类型定义。
#include "F28003x_Device.h" // 设备特定头文件 #include "F28003x_EPwm_defines.h" // ePWM寄存器位定义 #include "SFO_V8.h" // SFO库函数步骤2:声明全局变量你需要声明一个全局整型变量来存储SFO计算出的比例因子。
int MEP_ScaleFactor = 0; // SFO函数将更新此变量 // 通常还需要一个ePWM模块的指针数组,用于SFO内部索引(具体取决于库版本和你的使用方式)步骤3:初始化时获取初始比例因子在系统初始化、ePWM模块配置完成后,进入主循环前,调用SFO()获取第一个可用的比例因子。
// 等待SFO完成首次校准 while(SFO() == 0) { // 可以在这里添加超时处理,防止死循环 } // 循环退出时,MEP_ScaleFactor 已经包含了有效的初始值步骤4:在后台任务中周期性更新由于环境会变化,你需要在主循环或一个低速定时器中断中,周期性地调用SFO()来更新比例因子。
void main(void) { // ... 系统初始化 ... int sfo_status; while(1) { // ... 主应用逻辑 ... // 在后台慢速循环中调用SFO sfo_status = SFO(); if(sfo_status == 1) { // 成功更新了MEP_ScaleFactor,可以记录或用于其他计算 } else if(sfo_status == 2) { // 发生错误,比例因子超限。应进入安全处理,例如停止PWM输出 ESTOP0; // 触发调试断点 } // 如果返回0,说明校准还在进行,忽略即可,下次循环再检查 // 控制SFO的调用频率,例如每1秒或每100ms调用一次 DELAY_US(1000000); // 示例:延时1秒 } }> 实操心得:在实际项目中,我通常会将SFO()函数放在一个1Hz或10Hz的低优先级定时器中断服务程序(ISR)中。这样既能保证比例因子得到定期更新(应对缓慢的温度变化),又不会对高实时性的控制环路(如电流环、速度环)产生干扰。切记,不要在PWM周期中断等高频ISR中调用SFO()。
4. 实战解析一:基于HRPWM的Buck变换器实现
让我们把手册里的例子“翻译”成工程师能直接上手的实操指南。这个例子实现了一个1MHz开关频率的Buck变换器PWM信号生成。
4.1 需求分析与配置规划
- 目标:生成1MHz(周期1000ns),占空比可高精度调节的PWM波(EPWM1A),用于控制Buck开关管。
- 关键参数:
- 系统时钟 SYSCLKOUT = 100MHz
- EPWMCLK = SYSCLKOUT = 100MHz (周期10ns)
- TBPRD = 100 (对应 100 * 10ns = 1000ns = 1MHz)
- 期望分辨率:12.7位。怎么来的?传统PWM分辨率 = log2(100) ≈ 6.64位。HRPWM在每个粗调步进内提供最多255个微步进,相当于将分辨率提高了log2(255) ≈ 7.96位。理论总分辨率 ≈ 6.64 + 7.96 = 14.6位。但受限于MEP非线性等因素,手册保守估计为12.7位,这已经远超传统模式。
- 模式选择:采用非对称向上计数模式(Up-Count)。我们选择控制下降沿(
HR_FEP)来实现高分辨率占空比控制。为什么是下降沿?在Up-Count模式下,通过清除(CLEAR)事件产生下降沿,用CMPA值控制该事件发生的时刻,逻辑上更直观。
4.2 初始化代码详解(C语言部分)
手册中的初始化函数HrBuckDrvCnf(void)是经典配置,我们逐行解读其设计意图:
void HrBuckDrvCnf(void) { // ---------------- 第一部分:配置常规PWM参数 ---------------- EPwm1Regs.TBCTL.bit.PRDLD = TB_IMMEDIATE; // 周期寄存器立即装载模式 // 解释:避免影子寄存器带来的延迟,让TBPRD的修改立刻生效,简化初始配置。 EPwm1Regs.TBPRD = 100; // 设置周期值,对应1MHz // 注意:这里定义了一个全局变量 `hrbuck_period = 200;` 用于后续Q15格式转换,为什么是200?因为占空比计算时可能用到不同的缩放基准。 EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // 向上计数模式 EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // 禁止相位同步,本模块作为主模块 EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // 高速时钟预分频 = 1 EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // 时钟预分频 = 1 // 解释:不分频,让时基时钟TBCLK直接等于系统时钟,获得最高时间基准。 // 动作限定器配置:决定PWM波形如何产生 EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // CMPA在CTR=0时从影子寄存器装载到活动寄存器 EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // CMPA使用影子寄存器 // 解释:使用影子寄存器可以避免在计数器运行中途修改比较值导致毛刺。在CTR=0时同步更新,确保每个PWM周期的一致性。 EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // 当CTR=0时,将EPWMxA输出置高 EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // 当CTR=CMPA时(向上计数),将EPWMxA输出清零 // 解释:这就是产生一个上升沿在周期起点,下降沿由CMPA控制的PWM波的标准配置。 // ---------------- 第二部分:配置HRPWM资源 ---------------- EALLOW; // 允许写入受保护的寄存器 EPwm1Regs.HRCNFG.all = 0x0; // 先清空配置寄存器 EPwm1Regs.HRCNFG.bit.EDGMODE = HR_FEP; // 高分辨率控制下降沿位置 EPwm1Regs.HRCNFG.bit.CTLMODE = HR_CMP; // 由CMPAHR寄存器控制MEP(即控制占空比) EPwm1Regs.HRCNFG.bit.HRLOAD = HR_CTR_ZERO; // 高分辨率寄存器在CTR=0时装载 // 解释:`HRLOAD` 必须与上面CMPA的 `LOADAMODE` 同步,确保整数部分和小数部分同时更新。 EDIS; // 禁止写入受保护的寄存器 // 初始化MEP比例因子,使用一个典型值。实际应用中应由SFO()函数动态更新。 MEP_ScaleFactor = 66 * 256; // 对于100MHz和150ps MEP步长,典型值约为66步/周期 }> 注意事项:代码中MEP_ScaleFactor = 66 * 256;这一行,其中的* 256是因为在自动转换模式下(AUTOCONV=1),硬件期望CMPAHR寄存器中的值是分数部分 * 256。这个预乘的256操作,在手动计算模式下也需要在软件中完成。这里赋初值是为了让PWM能先跑起来,后续必须被SFO()的返回值覆盖。
4.3 运行时占空比更新代码详解(汇编部分)
手册提供了汇编代码,这对于理解底层操作和追求极致效率很有帮助。我们将其转换为更易理解的C语言伪代码逻辑:
// 假设:hrbuck_period = 200, MEP_ScaleFactor 已由SFO()更新 // 输入:Duty_Q15 是一个16位有符号整数(Q15格式,0x0000对应0%,0x7FFF对应100%) void UpdateBuckDutyCycle(int16_t Duty_Q15) { uint32_t temp32; uint16_t cmp_hr; // 1. 将Q15格式的占空比转换为对应于TBPRD的整数值 // 公式:CMPA_integer = (Duty_Q15 * TBPRD) >> 15 // 因为hrbuck_period可能为200(用于缩放),这里假设进行了类似计算得到 cmp_val int32_t cmp_val = ((int32_t)Duty_Q15 * hrbuck_period) >> 15; // 得到整数部分 // 2. 计算高分辨率部分(小数部分) // 思路:获取占空比的小数部分,乘以MEP_ScaleFactor,并做舍入调整 // 在自动转换模式下(AUTOCONV=1),硬件期望的操作是: // CMPAHR = fraction(Duty * TBPRD) << 8; // 其中 fraction(x) 表示取x的小数部分。 // 假设我们通过计算得到了占空比对应的小数部分 frac (范围0.0 ~ 1.0) float frac = ...; // 根据Duty_Q15和TBPRD计算得出 // 关键步骤:将小数部分转换为HRPWM硬件需要的格式 // 如果 AUTOCONV = 1: cmp_hr = (uint16_t)(frac * 256.0); // 左移8位等价于乘以256 // 然后将 (cmp_val << 8) | cmp_hr 组合成一个32位数写入CMPA:CMPAHR temp32 = ((uint32_t)cmp_val << 8) | cmp_hr; EPwm1Regs.CMPA.all = temp32; // 同时写入整数和小数部分 // 如果 AUTOCONV = 0(手动模式,不推荐): // 则需要软件完成 frac * MEP_ScaleFactor 的计算,并加上舍入偏移量0x80 // cmp_hr = (uint16_t)(frac * MEP_ScaleFactor + 0.5); // temp32 = ((uint32_t)cmp_val << 8) | cmp_hr; // EPwm1Regs.CMPA.all = temp32; }> 实操心得:在实际工程中,我强烈建���启用HRCNFG.bit.AUTOCONV = 1(自动转换模式)。这样,你只需要关心“我想要多少占空比”这个分数值,并将其左移8位后写入CMPAHR。硬件会自动利用HRMSTEP寄存器(由SFO更新)中的MEP_ScaleFactor来完成最终的微步进计算。这避免了在软件中进行浮点或定点乘法,减少了计算开销和潜在误差,也使代码更简洁、更易维护。
5. 实战解析二:基于HRPWM的PWM DAC实现
利用PWM加一个简单的RC低通滤波器(LPF)来实现DAC,是一种低成本、高隔离度的数模转换方案。但其精度和纹波受限于PWM的分辨率和频率。HRPWM能极大提升这项技术的性能。
5.1 PWM DAC原理与HRPWM的优势
一个N位传统PWM DAC的理论信噪比(SNR)约为6.02N + 1.76dB。如果PWM频率是400kHz,周期为2.5µs,在100MHz时钟下,传统PWM的分辨率是log2(250) ≈ 7.96位,SNR约50dB。这用于音频或精密基准电压是远远不够的。
启用HRPWM后,我们在每个2.5µs的周期内,不仅可以用250个粗步进来定位边沿,还能在每个粗步进内用最多255个微步进来“微调”。这使得有效分辨率大幅提升。手册中这个例子实现了14位的分辨率,其SNR理论上可达6.02*14 + 1.76 ≈ 86dB,这对于许多中高精度应用来说已经非常可观。
5.2 代码实现对比与要点
PWM DAC的初始化代码与Buck变换器示例非常相似,主要区别在于:
- 周期设置:
TBPRD = 250(对应400kHz)。 - 应用变量:
hrDAC_period = 250,用于占空比换算。 - 运行时计算:DAC应用可能需要双极性输出(例如输出正负电压)。在运行时汇编代码中,可以看到一句
ADD ACC, @_HrDAC_period<<15。这是一条关键的偏移注入指令。
为什么需要加偏移?对于单极性PWM(0%到100%占空比对应0V到Vdd),我们直接使用占空比即可。但对于双极性DAC,我们希望50%占空比对应0V,0%和100%占空比分别对应负满量程和正满量程。这就需要将输入的信号(假设是Q15格式,0x0000对应-1.0,0x7FFF对应+1.0)进行转换:DAC占空比 = 0.5 + 0.5 * 输入信号。 手册中的ADD ACC, @_HrDAC_period<<15正是在做这件事。_HrDAC_period左移15位(在Q15格式中相当于乘以1),然后加到ACC中,就实现了给原始输入信号加上一个0.5(即50%占空比)的直流偏置,将双极性信号转换到了单极性PWM占空比范围内。
> 注意事项:在实现PWM DAC时,滤波器的设计至关重要。PWM频率(400kHz)应远高于你希望输出的模拟信号最高频率(通常至少20倍以上)。RC滤波器的截止频率需要仔细计算,在抑制PWM开关纹波和保持目标信号带宽之间取得平衡。HRPWM的高分辨率主要改善的是DC精度和低频段的线性度,对高频纹波的抑制仍需依靠模拟滤波器。
6. 高级话题:HRPWM死区控制的高分辨率实现
这是手册中一个容易让人困惑但非常重要的部分。传统死区控制通过DBRED和DBFED寄存器设置上升沿和下降沿的延迟,其分辨率同样受限于TBCLK。
6.1 高分辨率死区的限制与配置
手册明确指出:在向上计数模式(Up-Count)下,当任何高分辨率模式被启用时,死区模块不可用。这句话让很多人以为HRPWM和死区不能共存。其实不完全对。它的准确含义是:你不能同时使用HRPWM控制的主PWM边沿和传统的死区模块。
解决方案是:使用HRPWM来直接生成带有精确延迟的互补PWM对,从而“手动”实现死区功能。具体来说,你可以:
- 配置一个ePWM模块的A通道为高分辨率模式。
- 使用另一个ePWM模块的B通道(或另一个模块的A通道),通过高分辨率方式生成一个与A通道互补但边沿有精确延迟的信号。
- 通过精确设置两个通道的比较值(CMPAHR)来间接实现纳秒甚至皮秒级精度的“死区”。
手册20.15.1.6节给出的例子,实际上是教你如何为已经由HRPWM生成的信号,计算其高分辨率死区延迟值。它假设你通过其他方式(如上述方法)生成了互补信号,现在需要计算一个通道的上升沿延迟(DBRED)的高分辨率部分。
6.2 高分辨率死区计算实例拆解
假设系统条件:TBCLK = 10ns, PWM频率1.33MHz(周期750ns), 期望的上升沿延迟为占空比周期的5%。
计算目标延迟时间:
- 半周期(因为死区通常在半周期模式下计算) = 750ns / 2 = 375ns。
- 所需上升沿延迟 = 5% * 375ns = 18.75ns。
转换为粗调步进数:
- 每个TBCLK周期为10ns,但在半周期时钟模式下,死区延迟的基本单位是
TBCLK/2 = 5ns。 - 所需粗调步进数
DBRED = int(18.75ns / 5ns) = int(3.75) = 3。 - 这个
3会写入DBRED寄存器(整数部分)。
- 每个TBCLK周期为10ns,但在半周期时钟模式下,死区延迟的基本单位是
计算高分辨率部分:
- 剩余的小数部分 = 3.75 - 3 = 0.75。
- 假设
MEP_ScaleFactor = 55(此值需由SFO确定,这里为示例)。 - 高分辨率寄存器值
DBREDHR = (0.75 * 55 + 0.5) << 8。 - 计算过程:
0.75 * 55 = 41.25,加0.5四舍五入得41.75,取整得41。左移8位(乘以256)得到41 * 256 = 10496 = 0x2900。 - 注意:手册计算示例中提到了硬件会忽略
DBREDHR的低9位,所以在某些计算中可能需要调整。
> 关键点:要使能死区的高分辨率模式,DBRED和DBFED的整数值必须大于3。这是为了给高分辨率调整留出足够的余量,避免边沿过于靠近计数器零点或周期点而导致的不确定行为。这个限制与HRPWM占空比操作中要求CMPA值大于3是类似的。
7. 常见问题、调试技巧与避坑指南
在实际项目中使用HRPWM和SFO库,肯定会遇到各种问题。下面是我从多个项目中总结出来的“避坑清单”和调试方法。
7.1 SFO库集成与调用问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
链接错误,提示找不到SFO()函数 | 1. 库文件未添加到工程。 2. 库文件与编译器/芯片型号不匹配。 | 1. 在CCS工程中,右键项目 -> Properties -> Build -> C2000 Linker -> File Search Path,确保添加了SFO_TI_Build_V8.lib及其路径。2. 确认你使用的SFO库版本是否支持你的具体C2000型号(如F28003x, F28004x等)。TI通常为不同系列提供对应的库。 |
SFO()函数一直返回0 | 1. 校准未完成。 2. ePWM时钟未使能或配置错误。 3. 受保护的寄存器访问未解锁。 | 1. 确保循环调用SFO(),它需要时间完成。首次调用可能耗时较长(约1.3ms @100MHz)。2. 检查 InitSysCtrl()或相关函数是否已正确初始化系统时钟并使能ePWM外设时钟。3. 确保在配置HRPWM相关寄存器( HRCNFG,HRMSTEP)前,使用了EALLOW指令。 |
SFO()函数返回2(错误) | EPWMCLK频率低于50MHz,或处于极端温度/电压下,导致MEP步数超过255。 | 1. 检查EPwm1Regs.TBCTL.bit.HSPCLKDIV和CLKDIV配置,确保EPWMCLK = SYSCLKOUT / (HSPCLKDIV * CLKDIV)不低于50MHz。2. 如果频率确实需要低于50MHz,则不能使用HRPWM的高分辨率模式,或者需要接受精度下降。 |
| PWM输出异常,边沿位置不准 | 1.MEP_ScaleFactor未正确初始化或更新。2. AUTOCONV位设置与软件计算方式不匹配。3. CMPA/CMPAHR更新时机错误。 | 1. 在调试器中查看MEP_ScaleFactor全局变量的值,确认SFO()已将其更新为合理值(例如100MHz下约66)。2.最易错点:如果 AUTOCONV=1,则CMPAHR应写入分数值 << 8。如果AUTOCONV=0,则需手动计算分数值 * MEP_ScaleFactor。务必统一。3. 确保在CTR=0或CTR=PRD等影子寄存器装载点更新CMPA:CMPAHR,避免周期中间更新��致毛刺。 |
7.2 HRPWM配置与输出问题
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 使能HRPWM后无PWM输出 | 1. HRPWM配置覆盖了动作限定器配置。 2. 高分辨率寄存器值超出范围。 | 1. 检查HRCNFG.bit.EDGMODE。如果设置为HR_BEP(双边沿控制),则原始的AQCTLA配置可能被覆盖。确保你理解所选模式下的信号生成逻辑。2. 确保计算出的 CMPAHR值在合理范围内。在AUTOCONV=1时,它应是0x0000到0xFF00之间的值(左移8位后)。 |
| 高分辨率效果不明显,调节占空比仍有“台阶感” | 1.MEP_ScaleFactor太小(接近1)。2. PWM频率过高,导致粗调步进数(TBPRD)本身太小。 | 1. 确认SFO()运行正常,MEP_ScaleFactor值合理(>50)。2. HRPWM的优势在粗调步进数较多时更明显。例如,在100MHz下,1MHz的PWM(TBPRD=100)比10MHz的PWM(TBPRD=10)能获得更精细的高分辨率控制。权衡开关频率和分辨率。 |
| 死区时间无法高精度控制 | 1. 误以为在Up-Count模式下可以直接使用死区模块的高分辨率模式。 2. DBRED/DBFED整数值设置小于等于3。 | 1. 回顾第6章,在Up-Count模式下使用HRPWM时,需用两个HRPWM通道模拟死区,或使用Down-Count/Up-Down模式并仔细阅读手册关于死区高分辨率模式的限制。 2. 确保死区延迟的整数部分( DBRED,DBFED)至少设置为4。 |
7.3 性能与实时性考量
- SFO的执行时间:130,000个EPWMCLK周期不是小数。在100MHz下是1.3ms,在50MHz下是2.6ms。绝对不要在电流环、速度环等高频中断(通常10-100kHz)中调用
SFO()。这会导致中断执行时间过长,严重影响系统实时性。务必将其放在主循环或一个专用的低频(如1kHz)定时器中断中。 - HRPWM的“盲区”:手册提到,HRPWM逻辑在PWM周期的前3个和后3个EPWMCLK周期内是不活跃的。这意味着:
- 如果你的占空比非常小(CMPA < 3)或非常大(CMPA > TBPRD - 3),高分辨率调节将失效,输出会被钳位在常规分辨率。
- 在设计系统时,应避免让占空比工作点进入这两个“盲区”。例如,对于最小占空比限制,可以在软件中做限幅:
if (duty < 3) duty = 3;。
- 精度与温度/电压关系:虽然SFO能动态补偿,但其更新频率需要跟上环境变化的速度。对于快速变化的工况(如汽车引擎舱),可能需要每秒调用SFO数次;对于环境稳定的工业设备,几分钟甚至更长时间调用一次即可。可以通过监控芯片内部温度传感器或供电电压来动态调整SFO的调用频率。
调试HRPWM,最有力的工具是高带宽、高采样率的示波器。通过测量实际输出的PWM脉冲宽度,并与理论值对比,可以直观地验证HRPWM的精度。同时,利用CCS的实时变量观察窗口,监控MEP_ScaleFactor的变化,可以确认SFO是否在正常工作。