C2000 HRCAP高分辨率捕获模块:从校准到实战的精密时间测量指南
1. 项目概述:为什么我们需要高分辨率捕获?
在电机控制、数字电源或者精密仪器开发的圈子里混久了,你肯定遇到过这样的场景:需要测量一个高速旋转编码器的脉冲间隔,或者解析一个脉宽调制信号的精确占空比。普通的定时器捕获功能,在几十兆赫兹的系统时钟下,分辨率可能只有几十纳秒,对于一些要求皮秒级抖动或者纳秒级边沿定位的应用,这就显得捉襟见肘了。
我第一次在伺服驱动器项目里被这个问题卡住,是试图测量一个高速光电编码器的信号。常规的eCAP模块捕获到的边沿时间,其抖动直接影响了位置环的计算精度,导致电机在高速运行时总有微小的“嗡嗡”声,不够平滑。后来把目光投向了C2000系列里的HRCAP模块,才发现原来硬件层面还有这种“降维打击”的解决方案。HRCAP,全称High-Resolution Capture,它不像传统捕获模块那样直接记录系统时钟的计数值,而是通过一个特殊的校准机制,将一个系统时钟周期(SYSCLKOUT)进一步细分成更小的“步进”,从而实现远高于系统时钟频率的时间分辨率。
简单来说,你可以把它理解成一个“硬件游标卡尺”。系统时钟是主尺,每一格是固定的(比如20ns @ 50MHz)。HRCAP则是在主尺的每一格上,又内置了一把可以精密移动的副尺,通过校准确定副尺上每一小格的实际时间宽度。当外部信号边沿到来时,它不仅能告诉你落在主尺的哪一格,还能精确告诉你落在了这一格副尺的哪个位置。这个“副尺”的精度,就是HRCAP的高分辨率所在,其步进大小(Step Size)可以通过专门的校准库来确定。
本文将以TMS320F2806x系列为例,手把手带你过一遍HRCAP校准库的使用流程,并深入每个关键寄存器的位域,让你不仅知道怎么配,更明白为什么要这么配。无论是想实现单线通信协议的精确解码,还是需要测量激光雷达的回波时间差,这套流程和底层原理都能给你提供扎实的参考。
2. HRCAP校准库使用全流程解析
官方文档里把校准库的使用分成了几个步骤,但直接照着抄很容易掉坑里。下面我结合自己的踩坑经验,把这些步骤重新梳理成一套更符合实际开发逻辑的流程。
2.1 环境搭建与头文件包含
第一步总是看起来最简单,却最容易埋雷。使用HRCAP校准库,你必须包含特定的头文件HCCal_Type0_V1.h。这个文件包含了校准函数HRCAP_Cal()的原型以及相关的状态宏定义。但关键在于,这个头文件和你所用的芯片型号紧密相关。
以F2806x为例,你的工程里通常已经包含了芯片的基础头文件和示例头文件。正确的包含顺序和依赖关系如下:
// 1. 芯片基础寄存器定义,这是所有外设编程的基石 #include "F2806x_Device.h" // 2. 芯片外设示例的通用宏和函数,常用于初始化GPIO、PIE等 #include "F2806x_Examples.h" // 3. HRCAP校准库专用头文件,必须在上述两个之后包含 #include "HCCal_Type0_V1.h"注意:
HCCal_Type0_V1.h这个文件名中的 “Type0” 指明了HRCAP模块的类型。C2000系列不同子型号的HRCAP模块可能有细微差异(Type0, Type1等),务必使用与你芯片型号匹配的校准库头文件。这个文件通常位于C2000Ware软件包的libraries/calibration/hrcap目录下。
如果你用的是自定义的或精简过的头文件,那么F2806x_Examples.h可能不是必须的,但F2806x_Device.h中关于HRCAP寄存器结构体的定义 (HRCAP_REGS) 必须存在,否则编译器会报错。一个常见的错误是只包含了外设驱动库的头文件而漏掉了设备寄存器定义头文件。
2.2 HRCAP寄存器数组的声明与理解
这是理解HRCAP模块多实例管理的关键一步。在C2000的软件架构中,每个外设(如HRCAP1, HRCAP2...)都对应一个全局的寄存器结构体变量。校准函数需要知道它要操作哪个模块。
文档给出的示例是这样的:
#define NUM_HRCAP 5 // # of HRCAP modules on 2806x + 1 volatile struct HRCAP_REGS *HRCAP[NUM_HRCAP] = {0, &HRCap1Regs, &HRCap2Regs, &HRCap3Regs, &HRCap4Regs};这里有几个细节需要深究:
- 为什么是
NUM_HRCAP = 5?F2806x实际上只有4个HRCAP模块(HRCAP1-4)。这里的5是“模块数量+1”。数组索引0被预留并置为NULL (0),真正的模块从索引1开始对应。这样设计的好处是,你可以直接用模块编号(1,2,3,4)作为数组下标来访问对应的寄存器指针,代码更直观。即HRCAP[1]指向HRCap1Regs。 volatile关键字的重要性:这个关键字告诉编译器,HRCAP数组指向的内容可能被硬件(HRCAP模块)在任何时刻改变,禁止编译器对其做激进的优化(比如把多次读取合并成一次,或者将值暂存在寄存器中)。在嵌入式硬件寄存器编程中,volatile是保证程序正确性的生命线,绝对不能省略。- 结构体指针数组:
HRCAP是一个数组,其元素是struct HRCAP_REGS *类型,即指向HRCAP寄存器组的指针。这种方式提供了极大的灵活性,校准函数HRCAP_Cal()通过传入的模块索引,就能直接操作对应的寄存器组。
2.3 一次性预校准:确定步进大小的基准
在应用程序使用高分辨率模式之前,必须进行一次性的预校准。这个步骤的目的是确定“步进大小”(Step Size)与HRCAP模块内部高速时钟HCCAPCLK之间的换算关系。HCCAPCLK可以是系统时钟SYSCLKOUT,也可以是锁相环2的时钟PLL2CLK,通常后者频率更高,能提供更好的分辨率。
校准过程本质上是让HRCAP模块测量一个已知频率的、非常干净的参考信号。这个参考信号通常由一个ePWM模块产生。HRCAP_Cal()函数内部会完成一系列测量和计算,最终将校准系数写入硬件。
示例代码的核心是一个循环:
int status; while (status != HCCAL_COMPLETE) { // 使用 HRCAP2 进行校准,时钟源选择 PLL2CLK,参考信号来自 ePWM8A status = HRCAP_Cal(2, HCCAPCLK_PLLCLK, &EPwm8Regs); if (status == HCCAL_ERROR) { ESTOP0; // 校准错误,停机检查 } }实操要点与避坑指南:
- 校准源的选择:示例中使用ePWM8A作为校准输入。你必须确保这个ePWM模块已经正确初始化,并输出一个稳定的、频率合适的方波。频率需要在HRCAP模块允许的范围内,具体请参考芯片数据手册的电气特性章节。通常,使用一个中等频率(如1-10MHz)的PWM信号效果较好。
HCCAPCLK频率检查:HRCAP_Cal()函数内部会检查HCCAPCLK的频率是否在有效范围内。如果返回HCCAL_ERROR,最常见的原因就是HCCAPCLK频率超限。你需要检查系统时钟配置,确保PLL2CLK(如果选用)已正确使能且频率合适。- 校准时机:预校准必须在系统时钟稳定之后、任何HRCAP高分辨率操作之前进行。通常放在
main()函数的硬件初始化阶段,在初始化HRCAP模块本身之后。 - 循环的必要性:校准可能不是一次就能成功的(
status可能返回HCCAL_RUNNING)。所以需要用循环等待,直到返回HCCAL_COMPLETE。务必加入超时机制,避免因硬件故障导致死循环。
2.4 运行时周期性校准:对抗温漂与电压波动
预校准搞定后,是不是就一劳永逸了?并不是。芯片在工作时,结温和供电电压的变化会导致内部模拟电路的延迟特性发生微小改变,从而影响之前校��好的“步进大小”。为了保证长期测量的绝对精度,需要在应用程序的后台低速循环中,周期性地重新运行HRCAP_Cal()。
void backgroundTask_1s(void) { // 假设这是一个1秒执行一次的后台任务 int status = HRCAP_Cal(2, HCCAPCLK_PLLCLK, &EPwm8Regs); if (status == HCCAL_ERROR) { // 错误处理:记录日志,可能切换到低分辨率模式,或使用上一次有效的校准值 errorHandler(); } // 如果 status == HCCAL_COMPLETE 或 HCCAL_RUNNING,可以忽略或记录 // HCCAL_RUNNING 表示校准未完成,但在后台任务中,我们通常只触发一次,不等结果 }设计考量:
- 校准频率:多久校准一次?这取决于你的应用环境。如果设备工作环境温度变化剧烈(如户外设备),可能需要每秒甚至更频繁地校准。如果是温度稳定的实验室环境,可以几分钟甚至更长时间校准一次。你需要权衡校准带来的开销(CPU时间、可能短暂影响捕获)与精度要求。
- 校准模块选择:通常指定一个HRCAP模块(如例程中的HRCAP2)作为专用的“校准通道”。这个通道可能就无法用于实际的信号测量了。在设计硬件时,可以考虑将ePWM校准信号通过一个模拟开关或跳线连接到这个HRCAP输入引脚。
- 错误处理:运行时校准失败不应导致系统崩溃。合理的策略是记录错误,并继续使用上一次成功的校准系数。可以在RAM中备份一份校准参数,当新校准失败时,恢复旧参数。
2.5 高精度脉冲宽度测量的实战代码
校准完成后,HRCAP模块就准备好了。当输入引脚发生边沿事件时,我们可以使用校准库提供的函数来读取高分辨率的脉冲宽度。这些函数内部会结合捕获计数器的值和校准的步进大小,计算出以HCCAPCLK周期为单位的精确时间。
下面是一个典型的中断服务程序示例,用于测量信号的周期、高电平和低电平宽度:
volatile uint32_t periodwidth_ns, pulsewidthhigh_ns, pulsewidthlow_ns; volatile int first_capture = 0; // 用于丢弃第一次无效捕获 interrupt void HRCAP1_Isr(void) { EALLOW; // 允许写入受保护的寄存器 // 1. 检查错误标志:上升沿溢出 if (HRCap1Regs.HCIFR.bit.RISEOVF == 1) { // 发生溢出,意味着在上一个上升沿中断被处理前,又来了一个新的上升沿 // 这通常意味着信号频率超过处理能力,或中断被阻塞太久 HRCap1Regs.HCICLR.bit.RISEOVF = 1; // 清除溢出标志 // 进行错误处理,如设置错误码 handleCaptureError(); } // 2. 丢弃第一次捕获 // 使能HRCAP时钟或复位后,第一个边沿触发中断时,计数器值是从时钟使能到边沿的时间,并非有效的脉冲宽度 if (first_capture < 1) { first_capture++; // 清除中断标志并返回 HRCap1Regs.HCICLR.bit.RISE = 1; HRCap1Regs.HCICLR.bit.INT = 1; PieCtrlRegs.PIEACK.bit.ACK4 = 1; // 手动应答PIE中断,组4是HRCAP1所在组 EDIS; return; } // 3. 读取高分辨率宽度值 // 这些函数返回的是以 HCCAPCLK 周期为单位的宽度,需要根据时钟频率转换为时间(如纳秒) periodwidth = PeriodWidthRise0((Uint16 *)&HRCap1Regs); // 周期(本次上升沿到上次上升沿) pulsewidthlow = LowPulseWidth0((Uint16 *)&HRCap1Regs); // 低电平宽度(上次下降沿到本次上升沿) pulsewidthhigh = HighPulseWidth0((Uint16 *)&HRCap1Regs); // 高电平宽度(上次上升沿到本次下降沿) // 4. 单位转换示例 (假设 HCCAPCLK = 100MHz, 即10ns) // periodwidth_ns = periodwidth * 10; // pulsewidthhigh_ns = pulsewidthhigh * 10; // pulsewidthlow_ns = pulsewidthlow * 10; // 5. 清除已处理的中断标志 HRCap1Regs.HCICLR.bit.RISE = 1; // 清除上升沿中断标志 HRCap1Regs.HCICLR.bit.INT = 1; // 清除全局中断标志 // 6. 应答PIE中断,允许该组后续中断进入 PieCtrlRegs.PIEACK.bit.ACK4 = 1; EDIS; // 禁止写入受保护的寄存器 }关键解析与注意事项:
EALLOW/EDIS:C2000中,一些关键的系统控制寄存器受EALLOW保护,防止误写。HRCAP的部分控制寄存器也在保护之列。在中断中修改它们前后,需要使用这对宏。- 丢弃首次捕获:这是一个极其重要的步骤。HRCAP计数器在模块使能后开始自由运行。第一个捕获事件记录的是从计数器启动到边沿发生的时间间隔,这个值是无意义的。必须丢弃第一次中断的数据。
- 函数参数:
PeriodWidthRise0,LowPulseWidth0,HighPulseWidth0这些函数需要传入HRCAP寄存器组的地址。注意类型转换(Uint16 *)&HRCap1Regs,这是因为这些校准库函数的历史定义方式,它期望一个指向16位单元数组的指针来访问特定的捕获寄存器。 - 中断标志清除顺序:先清除具体的边沿标志(
RISE),再清除全局中断标志(INT)。最后,必须操作外设中断扩展模块(PIE)的应答寄存器(PIEACK),告诉中断控制器该中断已被处理,否则该组后续中断将被阻塞。 - 实时性:中断服务程序必须尽可能短。复杂的计算(如单位转换、滤波)应考虑放到后台主循环中处理。中断里只做简单的数据读取和标志清除。
3. HRCAP核心寄存器深度剖析
理解了软件流程,我们再深入到寄存器层面。只有摸清每个比特位的含义,才能在出现异常时有效调试,甚至进行一些高级定制。HRCAP的寄存器集相对精简,但每个都至关重要。
3.1 控制寄存器(HCCTL):模块的指挥中心
HCCTL寄存器是配置HRCAP工作模式的起点。它的位域定义直接决定了模块的基本行为。
| 位域 | 名称 | 读写 | 描述与配置要点 |
|---|---|---|---|
| 15-9 | Reserved | R | 保留位,读取为0,写入无效。 |
| 8 | HCCAPCLKSEL | R/W | 捕获时钟选择位。这是影响分辨率的关键位。 0: HCCAPCLK = SYSCLKOUT。选择系统时钟,频率通常较低但稳定。1: HCCAPCLK = PLL2CLK。选择锁相环2时钟,频率更高,能提供更优的分辨率。必须确保所选时钟频率在数据手册规定的HRCAP电气特性范围内,否则校准会失败。 |
| 7-4 | Reserved | R | 保留位。 |
| 3 | OVFINTE | R/W | 计数器溢出中断使能位。 0:禁止计数器溢出中断。 1:使能计数器溢出中断。当16位自由运行计数器 HCCOUNTER从0xFFFF翻转到0x0000时,会触发中断。在测量极低频率信号(周期长于计数器溢出时间)时,需要使能此中断来统计溢出次数。 |
| 2 | FALLINTE | R/W | 下降沿捕获中断使能位。 0:禁止下降沿中断。 1:使能下降沿中断。当检测到输入信号下降沿时触发。 |
| 1 | RISEINTE | R/W | 上升沿捕获中断使能位。 0:禁止上升沿中断。 1:使能上升沿中断。当检测到输入信号上升沿时触发。通常需要根据测量需求(测周期、脉宽)来配置使能哪个边沿。 |
| 0 | SOFTRESET | R/W | 软件复位位。 0:写入0无效,读取始终为0。 1:写入1将复位HRCAP模块。���会清除 HCCOUNTER、所有捕获寄存器(HCCAPCNTRISE0/1,HCCAPCNTFALL0/1)以及中断标志寄存器(HCIFR)的所有位。该位是“瞬态”位,硬件会在复位操作后自动将其清零。 |
配置示例与心得:假设我们需要测量一个方波信号的高���平宽度,并且信号频率可能很低。
EALLOW; // 配置 HRCAP1 // 1. 选择PLL2CLK以获得高分辨率 HRCap1Regs.HCCTL.bit.HCCAPCLKSEL = 1; // 2. 使能上升沿和下降沿中断,以捕获两个边沿 HRCap1Regs.HCCTL.bit.RISEINTE = 1; HRCap1Regs.HCCTL.bit.FALLINTE = 1; // 3. 使能计数器溢出中断,防止在测量长周期信号时丢失计数 HRCap1Regs.HCCTL.bit.OVFINTE = 1; // 4. 执行一次软复位,确保模块从已知状态开始 HRCap1Regs.HCCTL.bit.SOFTRESET = 1; // 注意:SOFTRESET位会在一个时钟周期后被硬件自动清0,无需软件操作 EDIS;重要提示:
HCCTL寄存器是受EALLOW保护的。在修改其值之前,必须调用EALLOW宏,修改完成后调用EDIS宏。
3.2 中断标志寄存器(HCIFR):事件发生的公告板
HCIFR寄存器是一个只读寄存器(除保留位外),它实时反映了HRCAP模块内部的各种事件状态。中断服务程序的第一件事就是查看这个寄存器,以确定中断源。
| 位域 | 名称 | 读写 | 描述与触发条件 |
|---|---|---|---|
| 15-5 | Reserved | R | 保留位。 |
| 4 | RISEOVF | R | 上升沿中断溢出事件标志。这是一个错误状态标志。 0:无溢出事件。 1:当 RISE标志位已经为1(即上一个上升沿中断还未被处理)时,又发生了一个新的上升沿事件。这表明CPU处理中断的速度跟不上信号边沿的速度,或者中断被长时间关闭。 |
| 3 | COUNTEROVF | R | 计数器溢出中断标志。 0: HCCOUNTER未溢出。1:16位的 HCCOUNTER从0xFFFF溢出到0x0000。 |
| 2 | FALL | R | 下降沿捕获中断标志。 0:无下降沿事件。 1:检测到输入信号下降沿。 |
| 1 | RISE | R | 上升沿捕获中断标志。 0:无上升沿事件。 1:检测到输入信号上升沿。 |
| 0 | INT | R | 全局中断标志。 0:无HRCAP中断发生。 1:一个已使能的 RISE、FALL或COUNTEROVF中断事件已发生。只要此位为1,HRCAP模块将不会产生新的中断脉冲,直到该位被清除。 |
中断处理逻辑:在中断服务程序中,你应该先检查RISEOVF错误标志。然后根据RISE和FALL标志判断是哪个边沿触发了中断,并执行相应的读数操作。COUNTEROVF标志用于扩展计数范围。INT标志是总开关,必须在中断退出前清除。
3.3 中断清除寄存器(HCICLR):事件处理的确认键
HCICLR寄存器用于清除HCIFR中对应的中断标志位。向该寄存器的某个位写1,即可清除HCIFR中同名的标志位。这是一个只写寄存器(读取始终为0)。
| 位域 | 名称 | 读写 | 描述与操作 |
|---|---|---|---|
| 15-5 | Reserved | R | 保留位。 |
| 4 | RISEOVF | R/W | 上升沿溢出清除位。写1清除HCIFR.RISEOVF标志。 |
| 3 | COUNTEROVF | R/W | 计数器溢出清除位。写1清除HCIFR.COUNTEROVF标志。 |
| 2 | FALL | R/W | 下降沿中断清除位。写1清除HCIFR.FALL标志。 |
| 1 | RISE | R/W | 上升沿中断清除位。写1清除HCIFR.RISE标志。 |
| 0 | INT | R/W | 全局中断清除位。这是最关键的一位。写1清除HCIFR.INT标志。只有在清除了INT位之后,HRCAP模块才能响应新的中断事件。 |
清除顺序的最佳实践:
- 首先,读取
HCIFR确定中断源并完成必要的数据处理(如读取捕获寄存器)。 - 然后,清除具体的边沿标志(
HCICLR.RISE=1或HCICLR.FALL=1)。如果发生了溢出,也要清除HCICLR.COUNTEROVF=1。 - 最后,清除全局中断标志
HCICLR.INT=1。这个顺序很重要,可以避免在清除INT之后、清除具体标志之前,如果恰好发生新的边沿事件,导致标志位被再次置起,从而可能丢失一次中断。 - 清除
RISEOVF错误标志(如果发生)。
3.4 中断强制寄存器(HCIFRC):用于调试的触发器
HCIFRC寄存器允许软件模拟硬件中断事件,主要用于模块测试和调试。向该寄存器的RISE、FALL或COUNTEROVF位写1,会强制将HCIFR寄存器中对应的标志位置1,如果相应中断已使能,则会触发中断。这在验证中断服务程序逻辑时非常有用。
3.5 计数器与捕获寄存器:数据的核心
这部分寄存器是HRCAP模块存储原始数据的地方。
- HCCOUNTER (0x04): 16位自由运行计数器。每个
HCCAPCLK周期加1,从0x0000计数到0xFFFF后溢出归零。注意:由于HCCAPCLK可能与系统时钟SYSCLKOUT异步,直接读取此寄存器可能需要先停止HRCAP时钟 (HRCAPxENCLK = 0),否则可能读到不稳定的值。通常,我们不需要直接读取这个计数器,校准库函数会通过捕获寄存器间接获取其值。 - HCCAPCNTRISE0 (0x10): 上升沿0捕获寄存器。当检测到上升沿时,硬件自动将当前的
HCCOUNTER值锁存到此寄存器。 - HCCAPCNTFALL0 (0x12): 下降沿0捕获寄存器。当检测到下降沿时,硬件自动将当前的
HCCOUNTER值锁存到此寄存器。 - HCCAPCNTRISE1 (0x18): 上升沿1捕获寄存器。这是一个影子寄存器。当新的上升沿事件发生时,硬件会先将
HCCAPCNTRISE0的旧值复制到HCCAPCNTRISE1,然后再将新的HCCOUNTER值存入HCCAPCNTRISE0。这样,HCCAPCNTRISE1保存了上一次上升沿的计数器值。 - HCCAPCNTFALL1 (0x1A): 下降沿1捕获寄存器。功能同上,用于下降沿。
影子寄存器的妙用:HCCAPCNTRISE1和HCCAPCNTFALL1的存在,使得我们可以轻松计算连续两个同类型边沿之间的间隔(即周期),而无需在中断中手动保存上一次的值。例如,PeriodWidthRise0函数内部很可能就是利用HCCAPCNTRISE0和HCCAPCNTRISE1的差值来计算周期的。
4. 常见问题排查与实战技巧
理论终归要落到实操上,下面是我在项目中使用HRCAP时总结的一些典型问题和处理技巧。
4.1 校准失败(HRCAP_Cal返回HCCAL_ERROR)
这是最常见的问题。
- 检查时钟源:确认
HCCAPCLKSEL选择正确,并且PLL2CLK(如果使用)已正确配置并稳定运行。用示波器或通过寄存器读取验证其频率是否在数据手册规定的HRCAP工作频率范围内(例如,对于某些型号,HCCAPCLK最高不能超过某个特定值)。 - 检查校准信号:确认用于校准的ePWM模块已初始化,并且其输出信号确实连接到了HRCAP的输入引脚。用示波器检查该引脚是否有稳定、干净的方波,频率是否合适(参考校准库说明或例程)。
- 检查引脚复用:确认HRCAP输入引脚的GPIO复用功能已正确设置为HRCAP模式,而不是普通的GPIO或其他外设。
- 检查中断:校准过程可能需要HRCAP中断。确保PIE向量表已正确初始化,HRCAP的中断服务函数已注册,并且CPU全局中断已使能(
INTM位为0)。
4.2 测量结果跳动大或不准确
- 忽略首次捕获:确保在使能HRCAP或软复位后,丢弃第一个捕获事件的数据。
- 校准有效性:确认预校准已成功完成(
status == HCCAL_COMPLETE)。在环境变化大的应用中,检查运行时校准是否在正常工作。 - 信号质量问题:HRCAP对输入信号的边沿质量很敏感。如果信号有振铃、过冲或噪声,可能导致捕获点抖动。在硬件上,考虑在输入引脚附近添加适当的RC滤波或施密特触发器整形。
- 中断延迟:如果系统中断负载很重,HRCAP中断可能被延迟响应,导致虽然捕获值准确,但软件读取时已经过去了几个事件。检查中断优先级,确保HRCAP中断有足够高的响应优先级。或者,考虑使用DMA(如果HRCAP模块支持)来传输捕获数据,减轻CPU负担。
4.3 无法进入中断
- 寄存器配置链:这是一个完整的检查清单:
PCLKCRx寄存器:确保HRCAP模块的时钟使能位已置1。HCCTL寄存器:RISEINTE/FALLINTE使能了吗?- PIE配置:对应的PIE组(如HRCAP1通常在组4)使能了吗?PIE向量表里中断函数的地址填对了吗?
IER寄存器:对应的CPU中断级别使能了吗?INTM位:CPU全局中断使能了吗?(asm(“ CLRC INTM”))
- 中断标志清理:在初始化最后或发生异常后,尝试手动清除所有HRCAP中断标志 (
HCICLR) 和PIE应答位 (PIEACK),确保中断系统处于干净状态。 - 引脚配置:再次确认GPIO引脚已正确复用为HRCAP功能,而非普通输入。
4.4 高分辨率模式下的时间计算
校准库函数PeriodWidthRise0等返回的数值单位是HCCAPCLK的周期数,并且是经过高分辨率细分后的值。要得到实际时间(如纳秒),需要两步计算:
- 计算
HCCAPCLK周期:T_hccapclk = 1 / F_hccapclk。例如,HCCAPCLK = 100 MHz,则T_hccapclk = 10 ns。 - 应用校准系数:校准库函数内部已经使用了预校准得到的“步进大小”。这个步进大小是
HCCAPCLK周期的一个分数。因此,函数返回值val对应的实际时间为:Time = val * (Step_Size_in_HCCAPCLK_cycles) * T_hccapclk。 实际上,Step_Size_in_HCCAPCLK_cycles这个系数已经被封装在函数内部,函数返回的val可以近似理解为直接代表了HCCAPCLK的周期整数和小数部分。所以,更简单的理解是:返回值val乘以HCCAPCLK的时钟周期T_hccapclk,就得到了以秒为单位的精确时间。例如,val = 1500,T_hccapclk = 10 ns,则时间 =1500 * 10 ns = 15 us。
4.5 与标准eCAP模块的对比与选型
在C2000中,除了HRCAP,还有功能更丰富的eCAP模块。如何选择?
- eCAP优势:
- 32位计数器:测量范围极广,不易溢出。
- 4级深度缓冲:可连续捕获最多4个事件的时间戳,适合捕获脉冲序列。
- 灵活的工作模式:绝对时间戳模式、差值模式、单次/连续捕获。
- APWM模式:当不用于捕获时,可配置为PWM输出。
- HRCAP优势:
- 极高的分辨率:通过校准细分,分辨率远高于系统时钟周期,可达皮秒级。
- 硬件自动计算脉宽:提供直接读取高、低电平宽度和周期的函数,简化软件。
- 针对单信号高精度测量优化:专注于单一通道的极致精度。
选型建议:如果需要测量多事件序列或需要很长的测量范围,选eCAP。如果对单一信号的边沿时间定位有极高的精度要求(如激光飞行时间、高速通信解码),HRCAP是唯一选择。在某些高端型号上,两者可以结合使用,eCAP做粗测,HRCAP在关键边沿做精测。
