1. eCAP模块:从硬件捕获到PWM生成的瑞士军刀
在电机控制、数字电源或者任何需要精确测量外部脉冲信号时序的嵌入式实时控制项目中,工程师们常常面临一个核心挑战:如何以最小的CPU开销,精准地捕获一个高频信号的上升沿、下降沿,并计算出其周期和占空比?更进一步,当系统需要生成一路独立的、可灵活配置的PWM信号时,难道必须动用宝贵的ePWM模块资源吗?如果你正在使用TI的C2000系列微控制器,比如TMS320x2806x,那么eCAP模块就是你解决这些问题的“瑞士军刀”。这个模块的设计初衷,就是将高精度的时间测量和灵活的波形生成能力,集成在一个高度可配置的硬件单元里。
我最初接触eCAP是在一个无刷直流电机(BLDC)的霍尔传感器测速项目里。传统的软件捕获方式,在高速运行时不仅CPU占用率高,还容易因中断响应延迟引入误差。而eCAP模块的硬件时间戳捕获功能,让我第一次体会到了“硬件加速”的爽快感——它能在纳秒级精度上记录事件发生的时刻,CPU只需在合适的时候去读取结果即可。后来,在一个需要多路PWM但ePWM资源紧张的电源项目中,我又发现eCAP的APWM模式可以完美充当一个简易但够用的PWM发生器。今天,我就结合官方手册和多年的实战踩坑经验,为你彻底拆解eCAP模块的捕获与PWM生成功能,从核心原理、四种经典应用场景,到每个关键寄存器的配置细节,手把手带你玩转这个强大的外设。
2. eCAP模块核心架构与工作模式解析
要驾驭eCAP模块,首先得理解它的“双重人格”:捕获模式和APWM模式。这并非两个独立的模块,而是同一套硬件资源在不同配置下的两种表现形式,其核心都是一个32位的时间戳计数器。
2.1 核心硬件单元:模块的“心脏”与“记忆”
eCAP模块的核心可以看作由几个关键部件协同工作:
- 32位时间戳计数器:这是模块的“心脏”,一个自由运行的向上计数器,时钟源通常来自系统时钟分频。它是所有时间测量的基准。
- 4级深度捕获寄存器:这是模块的“短期记忆”。当捕获事件发生时,TSCTR的当前值会被自动锁存到CAP1、CAP2、CAP3、CAP4这四个寄存器中的一个。它们构成了一个循环缓冲区,可以连续记录最多4个事件的时间戳。
- 4状态顺序器:这是一个2位的模4计数器,决定了下一个捕获事件发生时,时间戳将被存入哪个CAP寄存器(CAP1->CAP2->CAP3->CAP4->CAP1...)。它就像是一个指针,管理着循环缓冲区的写入位置。
- 事件预分频与边沿检测:输入信号首先经过一个可配置的分频器,用于滤除高频噪声。然后,边沿检测电路根据配置,决定在信号的上升沿、下降沿,还是两者都触发捕获事件。
- APWM模式下的影子寄存器:在APWM模式下,CAP1和CAP2的角色从“捕获结果寄存器”转变为“活动周期/比较寄存器”,而CAP3和CAP4则成为它们的“影子寄存器”。这种影子机制允许CPU在任何时候更新CAP3/CAP4,而硬件会在一个安全的时刻(通常是PWM周期边界)自动将影子寄存器的值加载到活动寄存器,从而避免在PWM输出中间产生毛刺。
理解这个架构是理解所有应用示例的基础。模块的灵活性就体现在,通过配置寄存器,你可以让这套硬件执行完全不同的任务:要么专心致志地记录外部世界的时间,要么兢兢业业地对外输出规整的PWM波。
2.2 捕获模式 vs. APWM模式:模式切换的本质
模式的选择由ECCTL2.CAP_APWM位控制。这个位的切换,实际上改变了内部数据通路和引脚功能:
- 捕获模式:引脚配置为输入。TSCTR计数器的值在外部事件触发时被“捕获”到CAPx寄存器。CPU的工作是读取这些捕获到的时间值。
- APWM模式:引脚配置为输出。TSCTR计数器作为一个递减或递增的时基,不断与CAP1(活动周期寄存器)和CAP2(活动比较寄存器)比较,从而在引脚上产生PWM波形。CPU的工作是向影子寄存器写入新的周期和比较值。
这里有一个至关重要的实操心得:模式切换最好在模块初始化、计数器停止时进行。虽然理论上可以在运行时切换,但这可能导致不可预知的引脚状态或寄存器内容混乱。我的习惯是,在初始化函数中,先停止计数器,清空所有标志位,再配置CAP_APWM位,最后根据所选模式配置其他相关寄存器。
3. 捕获模式深度剖析:四种经典应用场景
官方手册给出了四个示例,这几乎是eCAP捕获功能的所有典型用法。我们不仅要看懂时序图,更要理解每种模式下的寄存器配置和软件操作流程。
3.1 示例一:绝对时间戳与上升沿触发
这是最基础的捕获模式。TSCTR计数器自由运行,永不复位。每当检测到输入信号的上升沿时,发生以下动作:
- 将TSCTR的当前值锁存到由顺序器指向的CAPx寄存器中。
- 4状态顺序器加1,指向下一个CAP寄存器。
- 如果使能了中断,则触发相应的捕获事件中断。
它能得到什么?连续两个上升沿事件的时间戳差值,就是信号的周期。因此,这种模式仅用于测量信号周期或频率。
关键配置解析:
ECCTL2.CONT_ONESHT = 0:设置为连续模式。ECCTL2.STOP_WRAP = 3:顺序器在4个事件后归零,构成一个4深度的环形缓冲区。ECCTL1.CTRRST1/2/3/4 = 0:所有事件均不复位TSCTR计数器,这是“绝对时间戳”的关键。ECCTL1.CAPxPOL = 0:将所有事件的极性设为上升沿触发。ECCTL1.CAPLDEN = 1:使能捕获加载。
软件操作流程:
- 完成上述配置并启动计数器。
- 等待
ECFLG.CEVT4标志置位(表示4个CAP寄存器都已填充了有效数据)。 - 在
CEVT4中断服务程序中,一次性读取CAP1、CAP2、CAP3、CAP4四个寄存器。 - 进行后处理计算:
Period1 = CAP2 - CAP1,Period2 = CAP3 - CAP2,Period3 = CAP4 - CAP3。 - 清除
CEVT4中断标志。
注意:由于TSCTR是32位计数器,存在溢出风险。在计算周期时,必须考虑溢出情况。如果
CAP(n+1)的值小于CAP(n),说明发生了溢出,实际周期应为(0xFFFFFFFF - CAP(n)) + CAP(n+1) + 1。使能CTROVF中断并记录溢出次数是处理长周期测量的稳健方法。
3.2 示例二:绝对时间戳与双沿触发
此模式在示例一的基础上,将事件触发边沿配置为交替的上升沿和下降沿。通常设置CAP1POL=0(上升沿),CAP2POL=1(下降沿),CAP3POL=0,CAP4POL=1,如此循环。
它能得到什么?除了周期信息,还能直接得到脉冲的高电平时间和低电平时间,从而计算出占空比。
Period1 = CAP3 - CAP1(第一个完整周期)High_Time1 = CAP2 - CAP1(第一个周期的高电平时间)Low_Time1 = CAP3 - CAP2(第一个周期的低电平时间)Duty Cycle1 = (High_Time1 / Period1) * 100%
配置差异:仅需修改ECCTL1.CAPxPOL寄存器,为每个捕获事件分别指定上升沿或下降沿。其他配置与示例一相同。
实操心得:双沿触发模式对输入信号的质量要求较高。如果信号存在抖动,可能会在预期的边沿附近意外触发多次捕获,导致顺序器错乱和数据错误。务必合理使用ECCTL1.PRESCALE(事件预分频器)来滤除噪声。例如,设置PRESCALE=2(2分频)意味着输入信号需要连续2个时钟周期保持稳定状态变化���会被识别为一个有效事件,这能有效抑制毛刺。
3.3 示例三:差值模式与上升沿触发
这是捕获模式中非常高效的一种用法,也称为“周期捕获模式”。其核心特点是:每次捕获事件发生后,TSCTR计数器都会自动复位到0。
工作流程如下:
- 第一个上升沿到来:TSCTR当前值
t1被捕获到CAP1,然后TSCTR立即复位为0,并重新开始计数。 - 第二个上升沿到来:此时TSCTR的值
T1(即从上一次复位到现在的时间)被捕获到CAP2,然后TSCTR再次复位为0。 - 以此类推。
它的巨大优势:CAP寄存器中存储的值T1、T2、T3、T4...直接就是相邻两个上升沿之间的时间差,即信号的周期。CPU无需做任何减法运算,直接读取即可。这节省了计算时间,也避免了处理32位计数器溢出带来的复杂性。
关键配置解析:
ECCTL1.CTRRST1 = 1:这是与绝对时间戳模式最根本的区别。设置事件1复位计数器。通常我们会将CTRRST2/3/4也设为1,让每个捕获事件都复位计数器,确保每个CAPx中存储的都是一个独立的周期值。ECCTL2.CONT_ONESHT = 0:连续模式。ECCTL1.CAPxPOL = 0:上升沿触发。
应用场景:这种模式特别适合需要快速、连续测量固定类型事件周期(如编码器脉冲、固定占空比方波)的应用。读取数据后几乎无需处理,效率极高。
3.4 示例四:差值模式与双沿触发
此模式结合了差值模式的便捷性和双沿触发获取占空比的能力。配置上,它采用了差值模式(CTRRSTx = 1)和双沿触发(交替设置CAPxPOL)。
数据处理逻辑: 假设配置为:事件1(上升沿,复位),事件2(下降沿,复位),事件3(上升沿,复位),事件4(下降沿,复位)...
CAP1:无意义(或为从开始到第一个上升沿的时间,通常忽略)。CAP2:存储了第一个脉冲的高电平时间T1。CAP3:存储了第一个脉冲的低电平时间T2。CAP4:存储了第二个脉冲的高电平时间T3。- 那么,第一个脉冲的周期 =
T1 + T2,占空比 =T1 / (T1 + T2) * 100%。
配置要点:需要仔细规划CTRRSTx和CAPxPOL的对应关系。一个常见的配置方案是让每个事件都复位计数器,这样每个CAP寄存器捕获的都是一个边沿到下一个边沿的“段”时间。
避坑指南:在差值模式下,如果输入信号的频率非常高,而TSCTR的计数时钟较慢,可能会出现计数器在两次事件之间来不及计数到较大值的情况。虽然不影响周期测量,但会降低时间分辨率。此时需要提高TSCTR的时钟源频率(通过预分频器设置)。反之,如果信号频率很低,要警惕计数器在两次事件间从0计数到最大值
0xFFFFFFFF然后溢出归零的情况。虽然硬件会置位CTROVF标志,但此时CAPx中捕获的值是溢出后的值,会导致周期计算错误(你会得到一个很小的值)。因此,在差值模式下,也必须使能溢出中断,并在中断中做特殊标记,或在软件中判断捕获值是否异常小。
4. APWM模式:将捕获器变为PWM发生器
当ECCTL2.CAP_APWM位设置为1时,eCAP模块摇身一变,成为一个独立的、单通道的PWM发生器。虽然功能上比全功能的ePWM模块简单(没有死区、互补输出、故障保护等高级功能),但对于许多只需要一路基础PWM的场景来说,它既节省了ePWM资源,配置也更为简洁。
4.1 APWM模式工作原理
在APWM模式下,核心工作元件依然是TSCTR计数器,但它的工作方式变了:
- 计数模式:TSCTR通常工作在递增计数模式,从0开始计数到周期值
APRD(存储在CAP1的阴影寄存器CAP3中),然后复位为0,如此循环。 - 输出逻辑:TSCTR的值会不断与比较值
ACMP(存储在CAP2的阴影寄存器CAP4中)进行比较。- 如果
APWMPOL=0(主动高电平):当TSCTR < ACMP时,输出高电平;当TSCTR >= ACMP时,输出低电平。 - 如果
APWMPOL=1(主动低电平):逻辑相反。
- 如果
- 影子寄存器机制:这是实现PWM无毛刺更新的关键。CAP1和CAP2是“活动寄存器”,直接参与硬件比较。CAP3和CAP4是它们的“影子寄存器”。CPU平时只更新CAP3和CAP4。硬件会在一个安全的时刻(TSCTR等于周期值
APRD并复位时),自动将CAP3的值加载到CAP1,将CAP4的值加载到CAP2。
4.2 APWM模式配置步骤
- 模式选择:
ECCTL2.CAP_APWM = 1。 - 设置周期和占空比:
- 向
CAP3寄存器写入周期值(APRD)。 - 向
CAP4寄存器写入比较值(ACMP)。 - 关键一步:在初始化时,需要手动触发一次影子寄存器的加载,将CAP3和CAP4的值同步到CAP1和CAP2。可以通过设置
ECCTL2.SWSYNC = 1(软件强制同步)来实现。
- 向
- 设置输出极性:
ECCTL2.APWMPOL选择高电平有效或低电平有效。 - 启动计数器:
ECCTL2.TSCTRSTOP = 1。
一个具体的配置示例: 假设系统时钟SYSCLKOUT = 100MHz,我们希望生成一个频率为10kHz,占空比为30%的PWM波。
- PWM周期
T = 1 / 10kHz = 100us。 - 周期寄存器值
APRD = T * SYSCLKOUT = 100e-6 * 100e6 = 10000。 - 比较寄存器值
ACMP = APRD * Duty = 10000 * 0.3 = 3000。 - 初始化代码逻辑如下:
// 1. 停止计数器,配置模式 ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0; // 停止TSCTR ECap1Regs.ECCTL2.bit.CAP_APWM = 1; // 选择APWM模式 ECap1Regs.ECCTL2.bit.APWMPOL = 0; // 主动高电平 // 2. 配置影子寄存器(周期和比较值) ECap1Regs.CAP3 = 10000; // APRD 影子寄存器 ECap1Regs.CAP4 = 3000; // ACMP 影子寄存器 // 3. 执行软件同步,将影子寄存器值加载到活动寄存器 ECap1Regs.ECCTL2.bit.SWSYNC = 1; // 4. 启动计数器 ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1;运行后,CAPx/APWMx引脚就会输出预期的10kHz,30%占空比的PWM波形。
4.3 运行时动态更新PWM参数
这是APWM模式最常用的功能之一。由于有影子寄存器,我们可以在PWM周期的任何时刻安全地更新参数。
- 更新占空比:只需向
CAP4寄存器写入新的比较值。硬件会在下一个PWM周期开始时(TSCTR复位时),自动将其加载到活动的CAP2寄存器中。 - 更新频率:需要同时更新周期和比较值。先向
CAP3写入新周期值,再向CAP4写入新的比较值(通常根据新周期和期望占空比计算)。两者会在同一个周期边界被同步加载。注意:如果只改周期不改比较值,占空比会发生变化。
重要经验:在需要同时改变频率和占空比时,务必注意写入顺序。虽然影子寄存器是独立加载的,但为了避免在极短的时间窗口内出现周期和比较值不匹配的“畸形”PWM周期,建议先计算好新值,然后在关闭全局中断的短暂保护期内,依次更新
CAP4和CAP3。对于C2000,由于其支持32位原子写,通常连续两条赋值语句即可,但养成这个习惯对代码的健壮性有好处。
5. 关键寄存器详解与配置实战
理解了工作原理,我们再来深入看看那些控制eCAP模块行为的寄存器。手册里的表格虽然详尽,但缺乏上下文。这里我将它们分类,并结合实战配置进行解读。
5.1 核��数据寄存器:TSCTR与CAP1-4
- TSCTR:32位时间戳计数器。在捕获模式下,它是测量的基准;在APWM模式下,它是PWM的时基。软件可读写,通常上电后清零。
- CAP1-CAP4:这4个寄存器是eCAP模块多功能性的体现。
- 捕获模式:它们���只读的(虽然可写,但通常不写),存储捕获到的时间戳。
- APWM模式:
CAP1和CAP2是只读的活动寄存器,由硬件使用;CAP3和CAP4是可读写的影子寄存器,供软件更新PWM参数。初始化时必须向CAP3和CAP4写入初始值,并通过SWSYNC同步。
5.2 控制寄存器:ECCTL1与ECCTL2
这是配置eCAP模块的“大脑”。
ECCTL1 - 捕获控制寄存器1:
FREE/SOFT:仿真控制位。在代码调试时非常重要。设置为10b或11b(自由运行),这样当你在CCS中暂停CPU时,eCAP计数器不会停止,方便观察动态波形。PRESCALE:事件预分频。用于滤除输入信号噪声。例如,设置为2(4分频)意味着信号边沿需要稳定4个ECLK周期才会被确认。CAPLDEN:捕获加载使能。必须置1,捕获事件发生时才会将时间戳加载到CAP寄存器。CTRRSTx:计数器复位控制。这是选择绝对时间戳与差值模式的关键。0=不复位(绝对),1=复位(差值)。CAPxPOL:事件极性。0=上升沿,1=下降沿。通过为CAP1-4设置不同的极性,可以实现复杂的边沿序列捕获。
ECCTL2 - 捕获控制寄存器2:
CAP_APWM:模式选择开关。0=捕获,1=APWM。APWMPOL:APWM输出极性。CONT/ONESHT:连续/单次模式。在捕获模式下,连续模式会循环覆盖CAP1-4;单次模式在捕获指定次数(由STOP_WRAP决定)后停止,等待REARM。STOP_WRAP:在单次模式下,定义在哪个捕获事件后停止(1-4);在连续模式下,定义循环缓冲区的深度(1-4)。通常设为3(4事件循环)。TSCTRSTOP:计数器启停控制。1=运行,0=停止。配置模块时,应先停止计数器。SWSYNC:软件同步位。写1产生一个同步脉冲。在APWM模式初始化时,用于手动触发影子寄存器加载。
5.3 中断相关寄存器:ECEINT, ECFLG, ECCLR, ECFRC
eCAP的中断结构清晰,管理方便。
- ECEINT:中断使能寄存器。需要使能哪个事件的中断,就将对应位置1。例如,在连续捕获模式下,通常使能
CEVT4,这样每捕获4个事件产生一次中断,效率较高。 - ECFLG:中断标志寄存器。当事件发生时,硬件自动置位对应标志位。即使未使能中断,标志位也会被置位,可供软件查询。
- ECCLR:中断标志清除寄存器。向某位写1,可清除
ECFLG中对应的标志位。这是清除中断标志的正确方式。 - ECFRC:中断强制寄存器。向某位写1,可以手动置位
ECFLG中对应的标志位,用于软件测试或触发中断。
标准的中断服务程序流程:
__interrupt void ECAP1_ISR(void) { // 1. 判断中断源 if (ECap1Regs.ECFLG.bit.CEVT4 == 1) { // 2. 读取数据 timestamp1 = ECap1Regs.CAP1; timestamp2 = ECap1Regs.CAP2; timestamp3 = ECap1Regs.CAP3; timestamp4 = ECap1Regs.CAP4; // 3. 进行数据处理(计算周期、占空比等) process_capture_data(timestamp1, timestamp2, timestamp3, timestamp4); // 4. 清除中断标志(必须!) ECap1Regs.ECCLR.bit.CEVT4 = 1; } // 如果需要,检查并清除其他标志位,如CTROVF if (ECap1Regs.ECFLG.bit.CTROVF == 1) { overflow_count++; ECap1Regs.ECCLR.bit.CTROVF = 1; } // 5. 清除PIE中断应答位 PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; }6. 实战配置指南与常见问题排查
理论最终要服务于实践。下面我以一个具体的场景——使用eCAP1模块测量一个频率约10kHz、占空比变化的PWM输入信号的周期和占空比——来展示完整的配置流程和代码框架。
6.1 场景分析与配置选择
目标:连续测量,需要周期和占空比信息。 选择:采用连续捕获模式、差值模式、双沿触发(对应手册示例四)。这样,CAP寄存器中直接存储了交替的高电平和低电平时间,软件处理简单。
- 优点:硬件自动计算时间差,CPU直接读取即得脉宽。
- 配置要点:设置
CTRRST1=CTRRST2=CTRRST3=CTRRST4=1,CAP1POL=0,CAP2POL=1,CAP3POL=0,CAP4POL=1。
6.2 完整初始化代码示例
void InitECAP1_for_DutyCycleMeasurement(void) { // 步骤1:确保模块时钟使能(通常在SysCtrl模块中配置) SysCtrlRegs.PCLKCR0.bit.ECAP1ENCLK = 1; // 使能eCAP1模块时钟 DELAY_US(10); // 短暂延时,让时钟稳定 // 步骤2:配置GPIO引脚为eCAP1功能 // 假设CAP1引脚是GPIO5,需查阅具体芯片数据手册 GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 1; // 将GPIO5配置为外设功能 GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0; // 使能内部上拉(根据实际电路选择) // 步骤3:停止eCAP计数器,开始配置 ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0; // 停止计数器 // 步骤4:配置ECCTL1 - 捕获控制1 ECap1Regs.ECCTL1.bit.FREE_SOFT = 2; // 自由运行,仿真时不停止 ECap1Regs.ECCTL1.bit.PRESCALE = 0; // 事件不分频(根据信号质量调整) ECap1Regs.ECCTL1.bit.CAPLDEN = 1; // 使能捕获加载到寄存器 // 配置差值模式:每个事件后复位计数器 ECap1Regs.ECCTL1.bit.CTRRST4 = 1; ECap1Regs.ECCTL1.bit.CTRRST3 = 1; ECap1Regs.ECCTL1.bit.CTRRST2 = 1; ECap1Regs.ECCTL1.bit.CTRRST1 = 1; // 配置双沿触发序列:上升、下降、上升、下降... ECap1Regs.ECCTL1.bit.CAP4POL = 1; // 事件4:下降沿 ECap1Regs.ECCTL1.bit.CAP3POL = 0; // 事件3:上升沿 ECap1Regs.ECCTL1.bit.CAP2POL = 1; // 事件2:下降沿 ECap1Regs.ECCTL1.bit.CAP1POL = 0; // 事件1:上升沿 // 步骤5:配置ECCTL2 - 捕获控制2 ECap1Regs.ECCTL2.bit.CAP_APWM = 0; // 捕获模式 ECap1Regs.ECCTL2.bit.CONT_ONESHT = 0; // 连续模式 ECap1Regs.ECCTL2.bit.STOP_WRAP = 3; // 4个事件后循环(CAP1->CAP4) ECap1Regs.ECCTL2.bit.SYNCI_EN = 0; // 禁用外部同步(本例不需要) ECap1Regs.ECCTL2.bit.TSCTRSTOP = 0; // 保持计数器停止(最后才启动) // 步骤6:配置中断 ECap1Regs.ECEINT.bit.CEVT4 = 1; // 使能第4个捕获事件中断 ECap1Regs.ECEINT.bit.CTROVF = 1; // 使能计数器溢出中断(安全起见) // 清除所有可能存在的旧中断标志 ECap1Regs.ECCLR.all = 0xFFFF; // 步骤7:将eCAP1中断服务程序链接到PIE向量表 // 假设使用CPU INT4, PIE Group 4, Vector 1 (具体查手册) EALLOW; PieVectTable.ECAP1_INT = &ECAP1_ISR; EDIS; // 使能PIE组4中的INT1(即eCAP1) PieCtrlRegs.PIEIER4.bit.INTx1 = 1; // 使能CPU级中断INT4 IER |= M_INT4; // 全局中断使能 EINT; ERTM; // 步骤8:清零计数器,然后启动 ECap1Regs.TSCTR = 0; ECap1Regs.ECCTL2.bit.TSCTRSTOP = 1; // 启动计数器! }6.3 中断服务程序与数据处理
volatile unsigned long high_time[2] = {0, 0}; // 存储高电平时间 volatile unsigned long low_time[2] = {0, 0}; // 存储低电平时间 volatile unsigned long period[2] = {0, 0}; // 存储周期 volatile float duty_cycle[2] = {0.0, 0.0}; // 存储占空比 volatile int data_index = 0; // 用于双缓冲 __interrupt void ECAP1_ISR(void) { unsigned long cap1, cap2, cap3, cap4; if (ECap1Regs.ECFLG.bit.CEVT4 == 1) { // 读取4个捕获值(按顺序:上升沿时间戳?不,在差值模式下是时间差) // 注意:在差值+双沿模式下,CAP1是第一个上升沿后的高电平时间, // CAP2是随后的低电平时间,CAP3是下一个高电平时间,CAP4是下一个低电平时间。 // 但根据配置(CTRRSTx=1),每个事件后计数器复位,所以CAPx存储的是间隔时间。 // 我们需要根据配置的极性序列��解读数据。 // 配置是:Evt1(上升沿,复位),Evt2(下降沿,复位),Evt3(上升沿,复位),Evt4(下降沿,复位) // 因此:CAP1 = 高电平时间1, CAP2 = 低电平时间1, CAP3 = 高电平时间2, CAP4 = 低电平时间2 cap1 = ECap1Regs.CAP1; cap2 = ECap1Regs.CAP2; cap3 = ECap1Regs.CAP3; cap4 = ECap1Regs.CAP4; // 处理第一组数据(来自CAP1和CAP2) high_time[data_index] = cap1; low_time[data_index] = cap2; period[data_index] = cap1 + cap2; if (period[data_index] != 0) { duty_cycle[data_index] = (float)cap1 / (float)period[data_index] * 100.0f; } // 切换缓冲区索引(简单的双缓冲) data_index ^= 1; // 可以在此设置一个标志,通知主循环数据已更新 new_data_ready = 1; // 清除中断标志 ECap1Regs.ECCLR.bit.CEVT4 = 1; } if (ECap1Regs.ECFLG.bit.CTROVF == 1) { // 计数器溢出处理:通常记录溢出次数,用于扩展测量范围 overflow_counter++; ECap1Regs.ECCLR.bit.CTROVF = 1; } // 必须清除PIE组应答位,以接收后续中断 PieCtrlRegs.PIEACK.all = PIEACK_GROUP4; }6.4 常见问题与排查技巧
在实际项目中,eCAP模块可能会遇到一些“坑”。以下是我总结的常见问题及解决方法:
捕获不到任何数据,中断不触发
- 检查GPIO复用:这是最常见的原因。确认
GPxMUX寄存器已将引脚配置为eCAP功能,而非普通GPIO。 - 检查输入信号:用示波器确认信号是否真的到达了芯片引脚,电平是否符合要求(0-3.3V)。
- 检查时钟使能:确认
PCLKCR0寄存器中对应的eCAP模块时钟已使能。 - 检查计数器是否运行:确认
ECCTL2.TSCTRSTOP位已设置为1。 - 检查中断配置:确认PIE向量表正确,PIEIER和IER已使能,全局中断
EINT已打开。 - 检查事件极性:确认
CAPxPOL设置与输入信号的实际边沿匹配。
- 检查GPIO复用:这是最常见的原因。确认
捕获数据跳动大,不准确
- 信号噪声:输入信号可能有毛刺。尝试增大
ECCTL1.PRESCALE值,对事件进行滤波。例如,设置为2(4分频)可以滤除短于4个ECLK周期的毛刺。 - 时钟源不稳定:确保给eCAP模块的时钟
ECLK是稳定的系统时钟分频。避免在测量期间动态改变系统时钟。 - 中断响应延迟:在连续捕获模式下,如果中断服务程序执行时间过长,可能会错过后续的捕获事件。确保ISR尽可能高效,或者考虑使用DMA将CAP寄存器数据直接搬运到内存。
- 信号噪声:输入信号可能有毛刺。尝试增大
APWM模式无输出或波形不对
- 引脚方向:在APWM模式下,引脚自动配置为输出,但最好再次确认GPIO配置。
- 影子寄存器未加载:这是新手常犯的错误。初始化时,向
CAP3和CAP4写入值后,必须置位ECCTL2.SWSYNC = 1来触发第一次加载。否则,活动寄存器CAP1和CAP2是0,比较器不会动作。 - 周期/比较值不合理:确保
ACMP值小于APRD值。如果ACMP >= APRD,在主动高模式下,输出将始终为高或始终为低。 - 极性理解错误:确认
APWMPOL的设置是否符合你的电路逻辑(高电平有效还是低电平有效)。
在调试器中暂停CPU后,eCAP行为异常
- 仿真模式设置:检查
ECCTL1.FREE_SOFT位。在开发阶段,建议设置为2或3(自由运行),这样在CCS中暂停CPU时,eCAP计数器不会停止,便于观察实时信号。在产品代码中,可根据需要调整。
- 仿真模式设置:检查
测量长周期信号时数据出错
- 计数器溢出:TSCTR是32位计数器,在高速时钟下,其溢出时间可能短于你测量的信号周期。例如,100MHz时钟下,溢出时间约为
2^32 / 100e6 ≈ 42.9秒。对于接近或超过此时间的测量,必须使能CTROVF中断,并在软件中维护一个溢出计数器,将捕获到的时间戳与溢出次数结合计算真实时间。
- 计数器溢出:TSCTR是32位计数器,在高速时钟下,其溢出时间可能短于你测量的信号周期。例如,100MHz时钟下,溢出时间约为
通过系统地理解eCAP模块的双重模式、四种经典应用场景以及每个寄存器的细微作用,你就能在电机控制、电源管理、传感器接口等实时控制项目中,游刃有余地运用这个强大的硬件外设。记住,关键是根据应用需求选择正确的模式,并注意配置细节,特别是计数器复位、影子寄存器同步和中断处理这些容易出错的地方。