TMS320F2837xD CMPSS数字滤波器配置、校准与系统集成实战指南
1. 项目概述:为什么CMPSS数字滤波器是实时控制系统的“守门员”
在电机驱动、数字电源或者任何需要快速响应模拟信号的嵌入式控制系统中,我们常常会遇到一个头疼的问题:噪声。比如,你想用比较器监测电机的相电流,一旦超过某个阈值就立刻关断PWM进行保护。但实际电路中,开关噪声、地线干扰无处不在,一个尖峰毛刺就可能让比较器误动作,导致系统频繁误保护甚至停机。这种“狼来了”的误报,在工业现场是绝对不允许的。
这时候,TMS320F2837xD这类高性能DSP内部的比较器子系统(CMPSS)及其数字滤波器,就成了系统稳定运行的“守门员”。它不像软件滤波那样占用CPU周期,而是在硬件层面,实时地对比较器的原始输出进行“多数表决”和去抖,只让真正持续存在的有效信号通过,滤除那些短暂的干扰脉冲。这不仅仅是加了个功能,而是从根本上提升了系统的鲁棒性和可靠性。
然而,这个“守门员”上岗前需要正确的“培训”和“校准”。如果初始化序列不对,滤波器可能根本不工作;如果参数配置不当,要么反应迟钝(滤除有效信号),要么过于敏感(放过噪声);如果不进行校准,器件本身的偏移误差会导致触发点“跑偏”,你以为在10A保护,实际可能9.5A就动作了,或者11A还没反应,这在高精度控制中是致命的。
本文将以一个深耕电机控制多年的工程师视角,手把手带你拆解CMPSS数字滤波器的初始化、配置与校准全过程。我们不只讲手册上的步骤,更会结合我在多个量产项目中踩过的坑,告诉你每个参数背后的设计考量、校准时的实操技巧,以及如何避开那些让系统不稳定的陷阱。目标是让你读完就能在F2837xD上,搭建一个既快速又可靠的硬件保护前端。
2. CMPSS数字滤波器核心原理与设计思路拆解
在深入代码之前,我们必须先搞清楚CMPSS数字滤波器到底在干什么。它不是我们传统DSP课上讲的IIR或FIR滤波器,不进行复杂的乘累加运算。它的核心任务非常简单却极其重要:对比较器的原始、异步、可能充满噪声的输出进行实时整形和去抖。
你可以把它想象成一个“投票委员会”。这个委员会有一个观察窗口(Sample Window),会持续观察比较器在一段时间内的输出状态(高或低)。委员会内部设定了一个“通过决议”的票数门槛(Threshold)。只有当窗口内,某种状态(比如高电平)的样本数超过了这个门槛,滤波器的最终输出才会改变为该状态。这个机制能有效滤除持续时间短于窗口的噪声脉冲。
2.1 关键参数解析:SAMPWIN, THRESH, CLKPRESCALE
手册里提到了三个核心寄存器位域:SAMPWIN、THRESH和CLKPRESCALE。它们的设置直接决定了滤波器的性格是“急性子”还是“慢性子”,是“严格”还是“宽松”。
SAMPWIN(样本窗口大小):
- 是什么:定义了参与“投票”的样本总数。寄存器值
N对应窗口大小为N+1个样本。例如,SAMPWIN = 4,则窗口大小为5个样本。 - 为什么:窗口越大,滤波器对噪声的免疫力越强,因为需要更长时间的连续有效信号才能改变输出。但代价是引入的延迟也越大。在过流保护这种对速度要求极高的场景,窗口不能设得太大。
- 是什么:定义了参与“投票”的样本总数。寄存器值
THRESH(多数表决阈值):
- 是什么:定义了改变输出所需的最小“赞成票”数。寄存器值
M对应阈值为M+1。例如,THRESH = 2,则至少需要3个样本赞成,输出才会翻转。 - 为什么:它和
SAMPWIN共同决定了滤波器的灵敏度。一个经典且稳定的配置是让阈值略高于窗口的一半(例如窗口5,阈值3),这要求信号必须持续占据明显多数才能通过,既能滤除单脉冲噪声,也能容忍个别样本的偶然错误。
- 是什么:定义了改变输出所需的最小“赞成票”数。寄存器值
CLKPRESCALE(时钟预分频):
- 是什么:决定了采样时钟的周期。系统时钟(SYSCLK)经过
(CLKPRESCALE + 1)分频后,作为数字滤波器的采样时钟。例如,SYSCLK=200MHz,CLKPRESCALE=199,则采样周期 = (199+1) / 200MHz = 1us。 - 为什么:这是调节滤波器时间分辨率的关键。它需要和你想要滤除的噪声频率相匹配。如果要滤除100ns的毛刺,那么采样周期必须小于100ns(即
CLKPRESCALE要设置得足够小)。同时,整个滤波器的响应延迟 = 窗口大小 × 采样周期,这个总延迟必须在系统允许的范围内。
- 是什么:决定了采样时钟的周期。系统时钟(SYSCLK)经过
2.2 初始化序列背后的逻辑
手册给出的初始化序列看似简单,但每一步都有其深意:
- 先配置并使能比较器:这是信号源头。必须确保比较器本身工作正常,输入源(外部引脚或内部DAC)、输出极性等配置正确,否则后续滤波都是空谈。
- 再配置数字滤波器参数:在比较器有稳定输出之前,就设定好滤波规则。如果顺序反过来,在滤波器使能但参数混乱的瞬间,比较器输出的噪声可能被误判为有效信号,导致不可预知的输出。
- 初始化FIFO窗口(FILINIT):这是非常关键但容易被忽略的一步。上电后,滤波器内部的FIFO(先进先出队列)内存内容是随机的。
FILINIT位写入1,会将当前比较器的输入值一次性填充到整个样本窗口中。这能防止系统启动时,因为FIFO内是未知状态而导致滤波器输出产生错误的瞬态跳变。务必在配置完比较器和滤波器参数后,使能滤波器前执行此操作。 - 清除状态锁存器(COMPSTSCLR):如果你打算使用锁存输出路径(即
CTRIPxSEL=3),那么需要在上电后清除可能存在的残留锁存状态,确保从一个已知的、干净的状态开始。 - 配置信号路径:决定滤波后的信号(
CTRIP)或直接输出(CTRIPOUT)是送给ePWM模块做故障触发,还是送到GPIO或输出交叉开关(OUTPUTXBAR)给其他外设使用。这一步将滤波器的“决策”与系统的“执行机构”连接起来。 - 配置目标模块:例如,配置ePWM模块的Trip-Zone子模块,使其能够响应来自CMPSS的
CTRIP信号,实现硬件级的快速关断。
这个序列的核心思想是“自底向上,从源到流,确保状态确定”。先准备好信号源,再设定处理规则,然后初始化处理器的内部状态,最后建立输出通路。任何颠倒都可能引入启动瞬态问题。
3. 数字滤波器配置实操与参数计算详解
理论清楚了,我们来看怎么动手配置。这里我以配置CMPSS1的高侧比较器(COMPH)数字滤波器为例,目标是滤除宽度小于500ns的噪声脉冲,同时要求滤波器总延迟不超过2.5us,用于一个开关频率为100kHz的电机驱动过流保护。
3.1 寄存器级直接配置
首先,我们根据系统时钟和需求来计算参数。假设SYSCLK = 200 MHz (周期5ns)。
确定采样周期:要滤除500ns的毛刺,采样周期必须小于500ns。我们取250ns以确保可靠性。那么,采样时钟周期 Ts = 250ns。
- 计算
CLKPRESCALE: Ts = (CLKPRESCALE + 1) * T_sysclk => CLKPRESCALE = Ts / T_sysclk - 1 = 250ns / 5ns - 1 = 49。 - 所以,
CTRIPHFILCLKCTL.CLKPRESCALE = 49。
- 计算
确定窗口大小和阈值:总延迟要求小于2.5us。总延迟 T_delay = (SAMPWIN + 1) * Ts。
- 我们可以反推最大允许的窗口大小:SAMPWIN_max = T_delay / Ts - 1 = 2.5us / 0.25us - 1 = 9。
- 选择一个适中的值,比如
SAMPWIN = 6(��7个样本窗口)。这样实际延迟为 7 * 0.25us = 1.75us,满足要求且有裕量。 - 选择阈值
THRESH = 4(即需要5个样本同意)。这是一个比较严格的设置,7个样本中需要5个一致才翻转,可以有效抵抗随机单点或双点干扰。
编写初始化代码:
// 假设已启用EALLOW保护,可以写受保护的寄存器 // 1. 配置滤波器参数 Cmpss1Regs.CTRIPHFILCLKCTL.bit.CLKPRESCALE = 49; // 采样周期250ns Cmpss1Regs.CTRIPHFILCTL.bit.SAMPWIN = 6; // 7样本窗口 Cmpss1Regs.CTRIPHFILCTL.bit.THRESH = 4; // 5票阈值 // 2. 初始化FIFO窗口 (假设此时比较器已配置,输入稳定) Cmpss1Regs.CTRIPHFILCTL.bit.FILINIT = 1; // 写入1初始化,硬件会自动清零此位 // 3. 清除可能存在的锁存状态(如果使用锁存路径) Cmpss1Regs.COMPSTSCLR.bit.HLATCHCLR = 1; // 写入1产生一个清除脉冲 // 4. 配置输出路径:将滤波后的信号送至CTRIPH,用于触发ePWM Cmpss1Regs.COMPCTL.bit.CTRIPHSEL = 2; // 2: 数字滤波器输出驱动CTRIPH // 同时,也可以将原始或同步后的信号送到CTRIPOUTH给其他外设监控 Cmpss1Regs.COMPCTL.bit.CTRIPOUTHSEL = 1; // 1: 同步比较器输出驱动CTRIPOUTH // 5. (可选)使能异步路径,用于超快速响应。但需谨慎,因为它可能绕过滤波器! // Cmpss1Regs.COMPCTL.bit.ASYNCHEN = 1; // 使能高比较器异步路径到或门 // 此时若CTRIPHSEL=3,则锁存器输出会与异步输出进行“或”操作。注意:
FILINIT和HLATCHCLR都是“写入1生效”的位。写入后,硬件会自动将其清零,所以你读回来总是0。不要试图通过写0来清除它们,那是无效操作。
3.2 使用DriverLib库函数配置
TI提供的DriverLib库封装了寄存器操作,让代码更易读和维护。实现上述同样功能的代码如下:
#include "driverlib.h" void CMPSS_Filter_Config(void) { // 定义滤波器配置结构体 CMPSS_FilterConfig hFilterConfig; // 填充配置参数 hFilterConfig.maxSampleWindow = 6; // SAMPWIN = 6 hFilterConfig.threshold = 4; // THRESH = 4 hFilterConfig.clkPrescale = 49; // CLKPRESCALE = 49 // 调用库函数配置高侧滤波器 CMPSS_configFilterHigh(CMPSS1_BASE, &hFilterConfig); // 初始化滤波器FIFO CMPSS_initFilterHigh(CMPSS1_BASE); // 清除高侧滤波器锁存 CMPSS_clearFilterLatchHigh(CMPSS1_BASE); // 配置输出源选择 CMPSS_configOutputsHigh(CMPSS1_BASE, CMPSS_OUTPUT_CTRIP_FILTER, // CTRIPH 来自滤波器 CMPSS_OUTPUT_CTRIPOUT_SYNC); // CTRIPOUTH 来自同步输出 // (可选)使能异步路径 // CMPSS_enableAsyncHigh(CMPSS1_BASE); }使用库函数的好处是屏蔽了底层寄存器细节,代码意图更清晰,且在不同型号的C2000器件间移植性更好。但务必清楚每个API对应的底层操作,这在调试时至关重要。
3.3 配置心得与避坑指南
- 参数计算验证:永远不要凭感觉设参数。务必根据
系统时钟、需滤除噪声的最大宽度和系统允许的最大响应延迟这三个关键指标,精确计算CLKPRESCALE和SAMPWIN。我习惯在代码中用注释写明计算过程,方便后续复查和调整。 - FILINIT的时机:必须在比较器输入稳定、且滤波器参数设置完成后,使能滤波器输出路径之前执行。如果比较器输入还在波动(比如DAC值在变化),
FILINIT可能会用一个错误的值初始化窗口。 - 锁存器(Latch)的使用:
CTRIPxSEL=3选择的是“锁存的数字滤波器输出”。这个锁存器一旦被置位(即滤波器输出变高),会一直保持,直到被COMPSTSCLR.HLATCHCLR或EPWMSYNCPER信号(如果使能)清除。这在需要“故障保持直到软件干预”的场景非常有用,比如锁存一个过流事件。但如果你的应用需要滤波器实时反映输入变化(如窗口比较),则应选择CTRIPxSEL=2(非锁存滤波器输出)。 - 异步路径(ASYNCHEN)的权衡:使能异步路径后,异步比较器输出会与锁存的滤波器输出进行“或”操作。这意味着,一个极大的噪声尖峰可能直接绕过滤波器触发保护,提供了最快的响应,但也丧失了抗噪性。除非你对信号质量极度自信,或有特殊的超快速保护需求,否则慎用。
4. CMPSS校准流程深度解析与实战
偏移误差(Offset Error)是模拟电路无法避免的先天缺陷。CMPSS模块涉及两个主要的误差源:比较器输入参考偏移误差和内部DAC的静态偏移误差。手册里提到,当比较器反相端由内部CompDAC驱动时,我们主要需要补偿DAC的静态偏移误差,因为它已经包含了比较器自身的偏移。
不校准的后果是,你代码里设定DAC输出1.000V作为保护阈值,但实际芯片由于工艺偏差,输出可能是0.985V或1.015V。在精密控制中,这几十毫伏的误差可能就是正常与故障的界限。
4.1 校准原理与流程拆解
手册提供的校准流程(向下扫描DAC值)其核心思想是:寻找使比较器状态发生翻转的那个临界DAC码值。
准备工作:
- 静态DC信号:在校准期间,必须给比较器的同相端(通常是外部输入引脚)施加一个稳定、干净的直流电压
V_target。这是校准的基准点。可以用精密电源,或者在板子上通过分压电阻产生。 - 禁用迟滞:将
COMPHYSCTL.COMPHYS设为0,暂时关闭比较器迟滞功能。迟滞会引入一个电压回差,干扰我们寻找精确的翻转点。校准完成后再根据需求重新使能。 - 启用滤波与锁存:为了对抗可能存在的输入噪声,确保数字滤波器已配置并启用,且使用锁存输出(
CTRIPHSEL=3)。这样,只有持续有效的翻转信号才会被锁存住,避免因噪声导致校准结果抖动。
- 静态DC信号:在校准期间,必须给比较器的同相端(通常是外部输入引脚)施加一个稳定、干净的直流电压
校准流程(向下扫描):
- 步骤1:设置起始DAC值。最安全的方法是设置为最大值0xFFF(对应DAC满量程电压)。这保证了初始状态比较器输出一定是低(假设同相端电压
V_target小于满量程电压)。如果你想加速,且已知V_target的大致范围,可以设置为V_target + Offset_spec + Margin,其中Offset_spec是数据手册给出的最大静态偏移误差,Margin是一个小的裕量(比如10mV对应的DAC码)。 - 步骤2:递减DAC值。每次循环将DAC值减1(对应输出电压微降)。
- 步骤3:等待DAC稳定。DAC输出电压改变需要一定的建立时间。这个时间在数据手册的“DAC Settling Time”参数中给出。通常需要插入几个微秒的软件延时(例如
DELAY_US(5)),或者查询某个状态位(如果支持)。 - 步骤4:清除锁存。写
COMPSTSCLR.HLATCHCLR = 1,清除上一次的锁存状态,为本次检测做准备。 - 步骤5:等待锁存可能置位。需要等待足够长的时间,让信号经过同步器、滤波器并可能置位锁存器。这个时间至少应大于
(滤波器延迟 + 几个系统时钟周期)。一个简单方法是延时1-2个滤波器采样窗口的时间。 - 步骤6:检查锁存状态。读取
COMPSTS.COMPHLATCH。如果为1,说明比较器已翻转,当前DAC值(或前一个值)就是临界点Code_trip。记录此值。 - 步骤7:循环。如果锁存为0,回到步骤2继续递减DAC,直到找到翻转点或DAC降到0。
- 步骤1:设置起始DAC值。最安全的方法是设置为最大值0xFFF(对应DAC满量程电压)。这保证了初始状态比较器输出一定是低(假设同相端电压
计算与应用校准值:
- 找到的
Code_trip,是使比较器在输入电压为V_target时翻转的实际DAC码。 - 理论上,你期望的DAC码
Code_expected= (V_target / V_ref) * 4095(12位DAC)。 - 偏移误差对应的DAC码
Offset_code=Code_expected-Code_trip。 - 在实际应用中,当你需要设置一个阈值电压
V_th时,你计算出的理论DAC码Code_set= (V_th / V_ref) * 4095。然后,应用校准补偿:最终写入DAC的值 =Code_set+Offset_code。
- 找到的
4.2 实战代码示例与优化
下面是一个简化的校准函数,包含了必要的注释和延时:
#define DAC_SETTLING_TIME_US 5 // DAC建立时间,根据数据手册调整 #define FILTER_DELAY_US 10 // 预估的滤波器最大延迟,根据配置计算 #define VREF 3.3f // DAC参考电压 #define V_TARGET 1.65f // 施加到比较器同相端的校准电压 uint16_t CMPSS_CalibrateDACOffset(uint32_t cmpssBase) { uint16_t dacValue = 0x0FFF; // 起始值:最大值 uint16_t tripCode = 0xFFFF; // 初始化为一个无效值 float codeExpected = (V_TARGET / VREF) * 4095.0f; // 1. 准备工作:禁用迟滞,确保使用滤波锁存输出 CMPSS_disableHysteresis(cmpssBase); // 假设之前已配置好滤波器,且CTRIPHSEL=3 // 2. 开始向下扫描 for(; dacValue > 0; dacValue--) { // 设置DAC值(写入影子寄存器,并立即加载) CMPSS_setDACValueHigh(cmpssBase, dacValue); // 等待DAC稳定 DELAY_US(DAC_SETTLING_TIME_US); // 清除之前的锁存状态 CMPSS_clearFilterLatchHigh(cmpssBase); // 等待足够时间,让信号通过滤波器 DELAY_US(FILTER_DELAY_US); // 检查锁存器是否置位 if(CMPSS_getLatchStatusHigh(cmpssBase) == 1) { tripCode = dacValue; // 记录翻转点 // 可选:双重验证,增加dacValue看锁存是否消失 // CMPSS_setDACValueHigh(cmpssBase, dacValue + 1); // DELAY_US(DAC_SETTLING_TIME_US); // CMPSS_clearFilterLatchHigh(cmpssBase); // DELAY_US(FILTER_DELAY_US); // if(CMPSS_getLatchStatusHigh(cmpssBase) == 0) { // tripCode = dacValue; // 确认 // } break; } } // 3. 恢复迟滞(如果需要) CMPSS_setHysteresis(cmpssBase, CMPSS_HYSTERESIS_MEDIUM); if(tripCode == 0xFFFF) { // 校准失败处理,可能V_target设置不对或硬件故障 return 0xFFFF; } // 4. 计算偏移码(这里简化处理,实际可存储浮点偏移电压) uint16_t offsetCode = (uint16_t)codeExpected - tripCode; // 将offsetCode存储到非易失性存储器(如Flash)中,供后续使用 // saveCalibrationOffset(offsetCode); return tripCode; // 或返回offsetCode }4.3 校准实战中的“坑”与技巧
- V_target的选择:校准电压
V_target最好选在你常用阈值范围的中间值附近。例如,你的保护阈值通常在1V到2V之间,那么选1.5V作为V_target比较理想。避免在接近电源轨(0V或VREF)的地方校准,因为那里DAC的非线性误差可能更大。 - 噪声是校准的天敌:校准期间,确保
V_target极其稳定。如果信号源有噪声,即使有滤波器,也可能导致翻转点在几个DAC码之间跳动。可以尝试:- 在输入端增加硬件RC滤波。
- 软件上多次校准取平均值。例如,运行5次扫描,去掉最大最小值后取平均。
- 增大滤波器的窗口和阈值,提高抗噪能力,但要知道这会增加校准过程的时间。
- DAC建立时间:这是最容易忽略的细节。如果
DAC_SETTLING_TIME_US不够,DAC输出电压还没稳定就去读比较器,结果必然不准。务必查阅芯片数据手册的电气特性章节。 - 校准的存储与应用:校准得出的
Offset_code应该存储在非易失性存储器中(如Flash)。每次系统上电初始化时,读取该值并应用于后续所有DAC阈值设置函数中。可以封装一个写DAC的函数,自动加上偏移补偿。 - 双端输入校准:如果比较器的两个输入都来自外部引脚,校准流程类似,但需要外部扫描一个输入端的电压(例如使用一个高精度的可编程电压源),同时监控另一个固定输入端的电压和比较器输出,寻找翻转点。这通常需要额外的自动化测试设备。
5. 高级主题:与ePWM同步及系统集成要点
CMPSS很少孤立工作,它最重要的搭档就是增强型脉宽调制模块(ePWM),共同构成硬件保护环路。这里有两个关键同步机制需要理解。
5.1 LATCHCLR与EPWMSYNCPER的协同
- 软件清除(LATCHCLR):通过写
COMPSTSCLR.HLATCHCLR位,软件可以随时清除滤波器的锁存输出。这用于在故障处理完毕后,手动复位保护状态。 - 硬件同步清除(EPWMSYNCPER):这是一个由ePWM时基模块产生的周期性信号。当
COMPSTSCLR.HSYNCCLREN使能时,EPWMSYNCPER信号的上升沿可以自动清除锁存器。 - 应用场景:在周期性控制系统中(如每个PWM周期更新一次DAC值进行逐周期限流),你可以将
EPWMSYNCPER连接到ePWM的周期匹配事件(TBCTR = TBPRD)。这样,每个PWM周期开始时,锁存器都会被自动清零。这意味着保护是“逐周期”的:本周期的过流事件会被锁存并触发保护动作(如关断PWM),但下一个周期开始时会自动清零,允许新的周期开始,除非故障持续存在。这避免了需要软件干预才能重启PWM,非常适合需要连续运行的电机控制。
关键警告:手册中特别提到,如果
COMPDACCTL[SWLOADSEL]=1(即DAC值在EPWMSYNCPER时更新),并且ePWM的TBCTR和TBPRD都为零,EPWMSYNCPER会保持高电平,导致DAC立即加载。因此,务必先正确配置ePWM的时基(设置非零的TBPRD),然后再将SWLOADSEL设为1。这个顺序错误会导致DAC在错误的时间加载,可能引发系统启动异常。
5.2 信号路径延迟分析
从比较器输入到CTRIP信号输出,信号会经过一系列模块,每个都会引入延迟:
- 同步器(Synchronizer):1-2个系统时钟周期。这是将异步的模拟比较器输出同步到数字时钟域所必需的。
- 数字滤波器(Digital Filter):如果使能,延迟 =
(SAMPWIN + 1) * (CLKPRESCALE + 1) * T_sysclk。如果旁路(所有参数为0),则固定为2个系统时钟。 - 锁存器(Latch):1个系统时钟周期。
总延迟= 同步器延迟 + 滤波器延迟 + 锁存器延迟。 在设计过流保护等快速保护电路时,必须计算这个总延迟,并确保它小于你的“故障容忍时间”。例如,在短路情况下,电流可能在几微秒内飙升到危险值,你的保护环路总延迟(包括CMPSS延迟、ePWM Trip-Zone响应延迟、功率器件关断时间)必须小于这个时间,否则器件会损坏。
5.3 系统集成与配置检查清单
在实际项目集成CMPSS时,我习惯按以下清单核对,这能避免90%的配置问题:
- [ ]时钟与电源:确认CMPSS所在模块的时钟已使能(通过PCLKCRx寄存器)。确认给内部DAC供电的模拟电源(VDDA, VDAC)稳定且干净。
- [ ]输入引脚配置:比较器的输入引脚是否已通过GPIO复用功能正确配置为模拟输入?相关ADC模块是否已禁用该通道的上下拉电阻?
- [ ]比较器基本配置:
COMPCTL中,COMPHSOURCE/LSOURCE(输入源选择)、COMPHINV/LINV(输出极性)是否正确? - [ ]DAC配置:
COMPDACCTL中,DACSOURCE(DAC值来源)、SELREF(参考电压选择)、SWLOADSEL(加载触发源)是否正确?DAC初始值是否已写入DACxVALS并加载? - [ ]滤波器参数:
SAMPWIN,THRESH,CLKPRESCALE是否根据需求计算并设置?FILINIT是否已执行? - [ ]输出路径:
CTRIPxSEL和CTRIPOUTxSEL是否指向了正确的信号源(异步、同步、滤波、锁存滤波)? - [ ]ePWM连接:
CTRIPx信号是否已通过输入交叉开关(INPUTXBAR)正确路由到目标ePWM模块的Trip-Zone输入?ePWM的Trip-Zone子模块是否已配置为相应的动作(强制高、强制低、高阻)? - [ ]锁存与清除:是否使用了锁存输出?如果需要周期性清除,是否使能了
HSYNCCLREN/LSYNCCLREN并连接了正确的EPWMSYNCPER信号? - [ ]校准数据:是否已执行校准并将偏移补偿值存储和应用?
6. 常见问题排查与调试技巧实录
即使按照手册一步步来,调试时也总会遇到CMPSS“不听话”的情况。下面是我总结的几个最常见的问题和排查思路。
6.1 问题速查表
| 现象 | 可能原因 | 排查步骤 |
|---|---|---|
| 比较器无输出/始终为低 | 1. 模块时钟未使能。 2. 比较器未使能 ( COMPCTL.COMPDACE=0)。3. 输入电压未超过迟滞范围。 4. 输入引脚配置错误(仍是数字GPIO)。 5. DAC值设置错误,反相端电压始终高于同相端。 | 1. 检查PCLKCR4.bit.CMPSS1ENCLK=1。2. 检查 COMPCTL寄存器。3. 测量实际输入电压,或暂时禁用迟滞( COMPHYS=0)。4. 检查GPIOAMSEL和GPIOCTRL寄存器。 5. 读取 DACHVALA寄存器,验证DAC输出值,并用万用表测量DAC输出引脚电压(如果引出)。 |
| 滤波器输出无变化(不滤波) | 1. 滤波器参数全为0(被旁路)。 2. CTRIPxSEL未选择滤波器输出(值为0,1,3)。3. FILINIT未执行,FIFO初始状态随机。4. 采样时钟过快( CLKPRESCALE太小),噪声样本被捕获。 | 1. 检查CTRIPHFILCTL和CTRIPLFILCTL寄存器值。2. 确认 COMPCTL.CTRIPxSEL=2。3. 确保在初始化序列中写了 FILINIT=1。4. 增大 CLKPRESCALE,降低采样率。 |
| 保护动作延迟过大 | 1. 滤波器窗口(SAMPWIN)设置过大。2. 采样时钟( CLKPRESCALE)分频比过大。3. 使用了锁存输出且未及时清除,导致故障状态保持过久。 | 1. 重新计算允许的延迟,减小SAMPWIN。2. 减小 CLKPRESCALE,提高采样率。3. 检查是否使能了 EPWMSYNCPER自动清除,或软件清除逻辑。 |
| 校准结果重复性差 | 1. 输入校准电压V_target有噪声或波动。2. DAC建立时间等待不足。 3. 滤波器参数在较噪环境下太宽松。 | 1. 改善V_target电源质量,增加硬件滤波。2. 增加 DELAY_US(DAC_SETTLING_TIME_US)的延时。3. 校准期间临时增大 SAMPWIN和THRESH。 |
| ePWM无法被CMPSS关断 | 1.CTRIPx信号未路由到ePWM。2. ePWM的Trip-Zone子模块未配置。 3. Trip-Zone动作未使能或配置错误。 4. CMPSS输出极性( COMPxINV)与ePWM期望的触发极性不匹配。 | 1. 使用InputXbarRegs.INPUTnSELECT将CTRIPx连接到ePWM的TZn输入。2. 检查ePWM的 TZSEL寄存器,确保对应Trip输入已使能。3. 检查 TZCTL寄存器,配置了正确的动作(如强制高/低)。4. 检查 COMPCTL.COMPHINV位,或调整ePWMTZCTL中的动作。 |
6.2 核心调试技巧:寄存器查看与信号追踪
- 活用CCS的寄存器视图:在Code Composer Studio调试时,直接查看
Cmpss1Regs的所有寄存器。重点关注:COMPSTS:实时查看COMPHSTS(滤波器输出)和COMPHLATCH(锁存器输出),这是判断滤波器是否工作的最直接证据。DACHVALA:确认DAC的实际输出值,而不是影子寄存器。RAMPSTS:如果你使用了斜坡发生器,这里可以看到当前计数值。
- 软件模拟信号注入:在调试初期,可以不用真实模拟信号。通过代码动态修改DAC值(
CMPSS_setDACValueHigh),来模拟一个变化的输入电压,观察比较器和滤波器的响应。这能快速验证逻辑是否正确。 - 利用CTRIPOUT和GPIO:将
CTRIPOUTH或CTRIPOUTL信号通过OUTPUTXBAR连接到某个GPIO引脚(配置为输出)。用示波器同时观察这个GPIO(代表原始或同步后的比较器输出)和最终用于触发ePWM的CTRIP信号(代表滤波后输出),可以直观地看到滤波器的效果:噪声毛刺在CTRIPOUT上跳动,但在CTRIP上被滤除了。 - 检查时钟树:确保你计算的
CLKPRESCALE是基于正确的SYSCLK频率。F2837xD有多个时钟域,确认CMPSS使用的系统时钟频率与你计算时假设的一致。
最后,关于CMPSS模块的时钟门控:手册提到,即使关闭CMPSS模块时钟,比较器模拟部分仍会工作,但数字部分(同步器、滤波器、斜坡发生器)会冻结。这意味着,如果你在低功耗模式下关闭了时钟,那么硬件保护功能将失效。在唤醒后重新使能时钟时,数字部分会恢复到冻结前的状态。在设计低功耗应用时,必须充分考虑这一点,可能需要软件在进入低功耗前禁用比较器,唤醒后重新初始化整个CMPSS。