1. HET高级定时器:嵌入式实时控制的精密心脏
在汽车发动机控制单元(ECU)、电机驱动或者任何对时序有苛刻要求的嵌入式系统里,定时器从来都不是一个简单的“计时器”。它更像是一个交响乐团的指挥,需要精准地协调各个外设的动作,在微秒甚至纳秒级别上确保喷油、点火、PWM生成、信号采集等关键事件的绝对同步。通用定时器(GPT)可以处理基础任务,但当场景复杂到需要与不规则的外部事件(比如发动机曲轴上缺齿的齿轮信号)同步,并基于此生成复杂的控制波形时,我们就需要更强大的武器——高级定时器(HET)。
HET(High-End Timer)是德州仪器(TI)在其Hercules和部分C2000系列MCU中集成的一种高度可编程、指令驱动的定时器外设。它不像传统定时器那样通过配置一堆寄存器来工作,而是拥有一套精简的指令集(Instruction Set),允许开发者编写微程序(Micro-program)来定义其行为。这种架构带来了无与伦比的灵活性:你可以把它编程成一个带复杂同步逻辑的PWM发生器、一个多通道的输入捕获单元、一个自定义的通信接口,甚至是上述功能的任意组合。今天,我们就深入其指令集的腹地,拆解三个在复杂同步和信号处理中扮演关键角色的指令:SCNT(步进计数)、SHFT(移位)和WCAP(软件捕获字)。理解它们,你就能真正驾驭这颗“精密心脏”。
2. SCNT指令:构建与外部事件同步的虚拟时基
在发动机控制中,ECU需要知道曲轴精确的实时角度位置,以决定何时点火、何时喷油。曲轴信号通常由一个带缺齿(或多余齿)的齿轮产生,传感器输出一系列脉冲,其中一个或多个脉冲的间隔与正常齿不同,形成“同步缺口”。APCNT(角度计数)和ACNT(角度捕获)指令就是用来处理这种带缺齿的齿轮信号的。而SCNT,则是为它们搭建一个高分辨率、与外部信号同步的虚拟时间基准的关键桥梁。
2.1 SCNT的核心原理与数学模型
SCNT指令的本质,是一个可编程的步进累加器。它的目标是在两个外部齿轮脉冲之间(即上一个齿轮周期P(n-1)),产生一个频率更高的内部时基。这个内部时基的“步进”是均匀的,从而可以在齿轮脉冲间隔内,插值出更精细的角度或时间点。
它的工作原理可以用一个简单的公式概括:SCNT周期 = 上一个齿轮周期 P(n-1) / 步进宽度 K
这里的K就是step参数,可选8、16、32或64。假设上一个齿轮周期P(n-1)(由APCNT测量并存储在寄存器T中)的计数值是800(代表一定的时间长度)。如果设置K=32,那么SCNT就会在这个800个基础时钟周期内,均匀地计数800 / 32 = 25次。也就是说,SCNT的数据寄存器(Data Field)会以32为步长递增,每累加32次,SCNT自身的“虚拟周期”就走过一个。
但这里有个关键问题:800并不总能被32整除(800/32=25,正好整除,这是理想情况)。通常P(n-1)不是K的整数倍。SCNT采用了一种“余数补偿”机制。在每个SCNT循环结束时,它会计算当前数据寄存器值减去P(n-1)的差值(即余数),并将这个余数保留到下一个循环作为起始值的一部分。这确保了长期的平均频率与K*外部信号频率严格同步,避免了累积误差。
注意:
SCNT指令在整个HET程序中只能使用一次。这是因为它是为整个角度计时系统定义全局步进时基的。它的执行位置必须在APCNT之后、ACNT之前,形成一个APCNT -> SCNT -> ACNT的处理流水线。
2.2 关键参数深度解析与配置实战
理解参数是正确使用指令的前提。我们结合数据手册和实际配置场景来拆解:
1.step(步进宽度,K):这是SCNT的灵魂。它定义了内部虚拟时基相对于外部信号的分辨率提升倍数。K=64能提供最高的角度分辨率,但也会让SCNT的计数器更快溢出(因为步长大)。选择时需要权衡:
- 高分辨率需求:如需要非常精细的角度控制(例如直喷发动机的多段喷射),选择较大的K(32或64)。
- 长周期兼容性:如果发动机转速极低,齿轮周期
P(n-1)可能非常大,选择较小的K(8或16)可以防止SCNT计数器在单个齿轮周期内就溢出(虽然HET是25位或32位计数器,但需考虑计算溢出点)。 - 计算效率:K是2的幂,处理器进行除法和余数运算非常高效。
2.gapstart(间隙起始角):这个参数是SCNT指令中最容易让人困惑的部分,因为它对SCNT自身的运行毫无影响。它的唯一作用,是将一个计算好的值写入HET的寄存器A。
- 为什么需要它?在齿轮存在缺齿的区域,
APCNT会暂停测量周期,因为缺齿处的脉冲间隔不规则,不能用于计算转速/角度。这个“暂停测量”的起始角度点,就是gapstart。ACNT指令需要知道这个点,以在正确的位置忽略APCNT的输入。 - 如何计算?公式在手册中给出:
GAPSTART = (stepwidth × (actual_teeth_on_gear - 1)) + 1。stepwidth:就是K。actual_teeth_on_gear:齿轮上实际存在的物理齿数(不包括缺齿)。例如,一个60-2的齿轮(60个齿位,缺2齿),实际物理齿数是58。- 计算示例:对于60-2齿轮,
K=32,则Gapstart = 32 × (58 - 1) + 1 = 32 × 57 + 1 = 1825。这个值会被SCNT自动写入寄存器A,供后续的ACNT指令使用。
3.data(数据域):这是SCNT指令运行时使用的20位计数器。开发者通常不需要直接设置它的初始值,因为SCNT的运行逻辑会自动管理它。但在调试时,可以通过HET的调试接口观察这个数据域的变化,来验证SCNT是否按预期的步进K在累加。
2.3 SCNT执行流程与状态机剖析
手册中的执行流程描述比较简略,我们可以将其转化为更易理解的状态机:
- 初始化与标志设置:
SCNT首先根据step参数设置两个内部标志SWF0和SWF1,供ACNT指令查询使用。同时清零零标志Z。 - 周期检查:检查寄存器T(存放
P(n-1))是否为零。如果为零(例如启动时或丢失信号),则直接跳转到下一指令,SCNT不工作。 - 条件判断与计数器操作:
- 如果数据域控制标志
DCF或角度控制标志ACF为1(通常由APCNT在检测到缺齿等特殊事件时设置),则复位SCNT的数据域计数器。 - 否则(正常情况),数据域计数器增加一个步进宽度
K。
- 如果数据域控制标志
- 溢出判断与零标志设置:
- 计算
(数据域计数器 - 寄存器T)。如果结果大于等于0,说明SCNT的累加值已经达到或超过了一个齿轮周期的长度。 - 此时,从数据域计数器中减去寄存器T的值(实现余数补偿),并将零标志
Z置1。 - 这个
Z=1的时刻至关重要:它标志着一个虚拟的、高分辨率的“角度时钟”滴答了一次。ACNT指令可以依赖这个Z标志作为其递增条件。
- 计算
- 写入Gapstart并跳转:无论计数状态如何,
SCNT都会将计算好的gapstart值写入寄存器A,然后执行跳转。
实操心得:调试SCNT的关键点
- 验证同步:最有效的调试方法是同时捕获原始的齿轮传感器信号(HET输入引脚)和由
SCNT的Z标志触发产生的输出信号(可以用一个CNT指令在Z=1时翻转一个IO口)。用示波器观察,后者应该是一个频率为K×齿轮频率的稳定脉冲,且每个齿轮脉冲周期内,正好有K个SCNT脉冲(允许第一个和最后一个脉冲因余数补偿有微小相位偏移)。 - 关注寄存器T:
SCNT的正常工作完全依赖于APCNT写入寄存器T的值是否准确。务必先调试好APCNT,确保其在正常齿位能正确测量周期。 - 理解“虚拟时基”:
SCNT本身不直接产生PWM波。它产生的是一个同步的、高分辨率的“时间戳流”。后续的ACNT或PWMs指令利用这个时间戳流来决定何时设置或清除输出引脚,从而生成与曲轴角度严格同步的复杂波形。
3. SHFT指令:将定时器引脚变为灵活的数据端口
如果说SCNT展现了HET在时间维度上的精密控制能力,那么SHFT指令则展示了其在数据维度上的灵活性。它允许你将HET的特定引脚(CC24-CC31)配置为移位寄存器的输入或输出端,在定时器程序的精确调度下,进行串行数据的移入或移出。这在实现自定义串行协议(如某些传感器接口)、输出扩展(通过移位寄存器驱动LED阵列)或简单的位操作时非常有用。
3.1 SHFT指令的工作模式全解
SHFT指令的核心在于smode(移位模式)参数,它定义了移位的方向和填充位逻辑。手册中的编码表信息量很大,我们将其分类解读:
1. 输出模式(Output Modes, P3=0): 数据从HET的内部数据域移出到指定的引脚。LSB或MSB先行由模式决定。
OR0/OL0:移出,同时向空出的位(OR0是MSB,OL0是LSB)填充0。OR1/OL1:移出,同时向空出的位填充1。ORZ/OLZ:移出,同时向空出的位填充零标志Z的当前值。这可以实现条件性的数据填充,非常灵活。
2. 输入模式(Input Modes, P3=1): 数据从指定的引脚移入HET的内部数据域。
IRM/ILL:标准输入模式。引脚数据移入,另一端(IRM的LSB或ILL的MSB)被丢弃。IRZ/ILZ:带Z标志更新的输入模式。引脚数据移入,同时被移出的那一端(IRZ是LSB,ILZ是MSB)的值会更新到零标志Z。这允许你在移位过程中实时监测被移出的位。
移位条件(cond)决定了何时执行移位操作:
UNC(无条件):每次执行SHFT指令都移位一次。这适用于由HET程序循环率控制的固定速率移位。RISE/FALL(HET31边沿):仅在HET31引脚(常被用作外部时钟输入)的上升沿或下降沿时移位。这允许SHFT与一个外部时钟同步,实现精确的时钟数据对齐。
3.2 配置SHFT实现SPI从机模拟
一个经典的应用是用SHFT模拟一个SPI从机。假设我们使用HET30作为数据输入(MISO), HET31作为时钟输入(SCLK),模式为CPOL=0, CPHA=0(时钟空闲低,数据在上升沿采样)。
- 引脚分配:
pin=31(时钟),pin=30(数据)。 - 指令设置:
- 我们需要两条
SHFT指令(因为一条指令只能关联一个引脚)。但通常,我们会用一条指令处理时钟边沿触发。 - 创建一条
SHFT指令,pin=31(时钟引脚),cond=RISE(在上升沿触发),smode=IRM(假设MSB先行,从引脚移入数据到MSB)。reg=A(将移位结果存到寄存器A)。 - 数据域
data初始化为0。每次HET31上升沿到来,这条指令就会执行,将HET30引脚的电平移入data域的MSB。
- 我们需要两条
- 中断与判断:可以设置
irq=ON并关联一个cond_addr,当数据域全部移满(全0或全1,取决于你的数据)时产生中断,在中断服务程序中读取寄存器A(即完整的移位结果),并进行处理。 - 输出数据:如果需要同时输出数据(作为MISO),情况更复杂,因为需要在时钟沿输出下一位。这可能需要结合
SHFT的输出模式和另一条指令(或利用PRV位和条件判断)来预装和更新输出数据。
注意事项:SHFT使用的硬件限制
SHFT指令只能用于引脚CC24到CC31。这是由HET硬件的引脚复用逻辑决定的。在规划硬件连接时,必须将移位功能安排在这些引脚上。- 移位操作是单次执行的。即每满足一次条件(或无条件执行一次),只移动1位。要实现8位数据传输,你需要确保该指令被执行8次(例如,通过循环或8个外部时钟边沿)。
Prv. bit的更新是无条件的。每次执行SHFT指令,无论是否发生移位,它都会采样当前CC31(或指定引脚)的电平并存储。这个位常用于边沿检测逻辑中。
3.3 SHFT指令执行逻辑详解
手册中的执行流程可以简化为以下步骤:
- 条件判断:检查
cond条件。如果是UNC,或指定的CC31边沿发生,则进入移位流程。 - 执行移位:根据
smode([P3:P0])对立即数据域(Immediate Data Field)执行一次移位操作。结果同时写回数据域和选定的寄存器(reg)。 - 更新Z标志:
- 对于输出模式(
000X或001X),如果移位后数据域全0或全1,则Z=1。 - 对于
IRZ/ILZ模式,Z标志被设置为被移出的那个位(LSB或MSB)。 - 否则
Z=0。
- 对于输出模式(
- 中断判断:如果中断使能(
irq=ON),并且数据域变为全0或全1,则设置软件中断标志并跳转到条件地址(cond_addr)。否则跳转到下一程序地址(next)。 - 更新Prv.位:始终执行,记录当前引脚电平。
实操心得:调试串行通信
- 从简单开始:先用
UNC条件和OR0模式,让程序循环执行SHFT,用示波器观察引脚输出,验证基本的移位功能是否正确,LSB/MSB先行是否符合预期。 - 时钟同步是关键:当使用
RISE/FALL条件时,务必确保HET31引脚上的时钟信号是干净的,并且HET的输入滤波配置得当,防止毛刺导致误触发。 - 利用Z标志:
ORZ/OLZ模式和IRZ/ILZ模式提供了强大的状态反馈。例如,在输出一串数据后,通过检查Z标志可以判断最后一个移出位是什么,或者在进行输入移位时,实时获取被移出的位用于流控制。
4. WCAP指令:高精度事件时间戳捕获
在实时控制中,我们不仅需要产生精确的信号,还需要精确地测量外部事件发生的时刻。这就是捕获(Capture)功能。WCAP(软件捕获字)指令是HET实现软件触发捕获的核心。与硬件捕获单元不同,WCAP的捕获动作是由HET程序流控制的,这带来了独特的灵活性和应用场景。
4.1 WCAP与硬件捕获的差异与应用场景
传统的定时器硬件捕获单元,通常在输入引脚发生指定边沿时,自动将当前定时器计数器的值锁存到捕获寄存器中。这个过程是纯硬件行为,速度极快,抖动极小。
WCAP指令的捕获是“软件”的,意味着:
- 触发条件更灵活:除了引脚边沿,还可以设置为
UNC(无条件),在任何需要的时候(例如程序判断某个条件满足后)捕获寄存器的值。 - 捕获源多样:它可以捕获HET的内部寄存器(A, B, T)的值,而不仅仅是自由运行计数器的值。你可以捕获由
SCNT生成的虚拟角度计数、由其他指令计算出的中间结果等。 - 精度依赖程序循环:捕获发生的时刻是
WCAP指令被执行且条件满足的时��。因此,其时间戳的精度和抖动取决于HET指令循环的执行时间(HR时钟周期)。对于高分辨率(HR)引脚,这个精度可以非常高(例如在100MHz HR时钟下,理论精度10ns)。
典型应用场景:
- 关联事件捕获:当系统检测到某个复杂条件(由多条HET指令逻辑判断得出)成立时,立即捕获当前的时间或角度值。
- 多寄存器快照:在同一个时刻,捕获多个内部寄存器(A, B, T)的状态,用于复杂的计算或诊断。
- 高分辨率引脚的事件计时:对于连接到HR引脚(HET23-HET0)的高速信号,
WCAP可以捕获其边沿发生的精确HR时间戳。
4.2 HR/LR捕获与边沿检测机制
WCAP指令的一个强大特性是它对高分辨率(HR)引脚的支持。
hr_lr位:当此位为0,且选择的引脚是HR引脚(HET23-HET0)时,WCAP会在捕获发生时,不仅将选定寄存器的值存入20位的data域,还会将一个5位的hr_data值捕获到指令的特定字段。这个5位值代表了HR时钟域内更精细的时间信息(通常是对HR时钟的进一步分频或计数),与主LR时钟结合,能提供比LR时钟周期(例如100MHz vs 12.5MHz)更高精度的时间戳。- 边沿检测:
WCAP的边沿检测是基于软件循环的。它比较当前循环开始时采样的引脚电平(Pin level)与上一次存储的Prv. bit([C20])的值。- 如果
event=RISE,且当前为高,Prv.为低,则判定为上升沿。 - 如果
event=FALL,且当前为低,Prv.为高,则判定为下降沿。 - 如果
event=BOTH,则上述两种情况任一发生都触发。 - 关键点:无论检测到的边沿是否是你设定的捕获条件,
WCAP指令每次执行都会更新Prv. bit为当前引脚电平。这意味着即使你只关心上升沿,该指令也在持续跟踪引脚状态,为边沿检测提供历史信息。
- 如果
4.3 WCAP配置示例:测量脉冲宽度
假设我们需要测量HET10引脚上一个正脉冲的宽度(高电平持续时间)。
- 思路:使用两条
WCAP指令。第一条在上升沿捕获时间戳T1,第二条在下降沿捕获时间戳T2。脉冲宽度 = T2 - T1。 - 指令配置:
- WCAP1:
pin=10,event=RISE,reg=T(假设寄存器T是某个自由运行的计数器),irq=ON,cond_addr=CAP_RISE_ISR。data域初始值不重要,捕获后会自动更新。 - WCAP2:
pin=10,event=FALL,reg=T,irq=ON,cond_addr=CAP_FALL_ISR。
- WCAP1:
- 程序流程:两条
WCAP指令顺序放置在HET程序循环中。当上升沿到来,WCAP1条件满足,它将当前T寄存器的值捕获到其data域,触发中断,程序跳转到CAP_RISE_ISR标签处执行服务程序(可以保存data值到某个共享变量)。下降沿同理。 - 计算宽度:在主CPU的中断服务程序(由HET中断触发)中,读取两个保存的
data值,相减并乘以计数器时钟周期,即得到脉冲宽度。
注意事项与避坑指南
- 中断风暴风险:如果设置
irq=ON,且捕获条件很容易满足(比如UNC模式放在快速循环中),会导致频繁中断,增加CPU负载。务必确保中断处理程序足够高效,或者仅在需要时才使能中断。 - 时间戳溢出:如果使用的计数器(如寄存器T)是自由运行的,且脉冲宽度可能很长,需要考虑计数器溢出的情况。计算宽度时需要做溢出处理:
width = (T2 - T1) & COUNTER_MASK(假设计数器是环绕的)。 - HR捕获的同步:当使用
hr_lr=0进行HR捕获时,hr_data是5位。你需要查阅具体MCU的数据手册,明确这5位对应HR时钟的哪个分频或相位,以正确解析出绝对时间。通常需要将data(LR部分)和hr_data(HR部分)组合起来计算。 - Prv. bit的初始化:
Prv. bit在上电或引脚功能初始化为HET后是未知的。这可能导致第一条WCAP指令在第一个循环时就误触发一个边沿事件(如果当前电平与未知的Prv.值不同)。一个常见的做法是在程序开始时,先执行一条WCAP指令,设置event=NOCOND(或UNC)且irq=OFF,目的仅仅是让Prv. bit被初始化为当前的实际引脚电平,然后再开始正常的边沿检测。
5. 高级应用与联合编程实战
单独理解每条指令是基础,但HET的强大之处在于将这些指令像积木一样组合起来,实现复杂的定时、同步和IO逻辑。我们来看一个综合性的实战场景:生成与发动机曲轴同步的、带有一段特定角度域内消隐的PWM信号。
5.1 场景分析与指令规划
需求:发动机曲轴60-2齿轮信号输入。需要在每个气缸的压缩上止点前某个精确角度(如90度)输出一个脉宽固定的PWM脉冲,但这个脉冲在曲轴转过某个特定角度范围(例如对应气门重叠角附近)时必须被强制拉低(消隐),以避免干扰。
系统设计:
- 信号解码与同步:使用
APCNT测量齿轮周期并检测缺齿,实现同步。使用SCNT(K=32)生成高分辨率虚拟角度时基。使用ACNT基于SCNT的Z标志进行角度累加,得到当前曲轴角度值(存储在某个寄存器,如B)。 - 角度判断与PWM生成:
- 使用
CNT或PWMs指令来产生PWM波形。 - 需要两条
WCAP指令(或ECNT事件计数)来辅助判断角度域。WCAP1:设置为当寄存器B(角度值)等于“消隐开始角度”时,无条件(UNC)捕获一个值(可以是任意值,主要利用其跳转功能),并跳转到一段将PWM输出强制拉低的程序段。WCAP2:设置为当寄存器B等于“消隐结束角度”时,无条件捕获并跳转回正常的PWM调制程序段。
- 正常的PWM调制由
PWMs指令实现,其占空比由另一个算法决定,但使能条件受上述跳转逻辑控制。
- 使用
5.2 程序流与状态机实现
HET程序是一个循环执行的指令列表。我们可以通过next和cond_addr字段构建条件跳转,实现状态机。
; 假设 HET 程序片段 (伪代码风格) START: APCNT ... ; 测量齿轮周期,检测缺齿,更新寄存器T和同步标志 SCNT step=32, gapstart=1825 ; 生成32倍频虚拟时基,计算并写入Gapstart到A ACNT ... ; 利用SCNT的Z标志递增角度计数器,结果存于寄存器B ANGLE_CHECK: WCAP event=UNC, reg=B, data=BLANK_START_ANGLE, cond_addr=DO_BLANK, next=CHECK_PWM_COND ; 如果B == BLANK_START_ANGLE,跳转到DO_BLANK,否则继续 CHECK_PWM_COND: ; 这里可以插入其他条件判断,例如判断是否到了点火角度 CMP reg=B, value=IGNITION_ANGLE ... ; 根据比较结果可能跳转到点火控制段 PWM_GENERATE: PWMs ... ; 正常的PWM生成指令 JMP START ; 循环 DO_BLANK: ; 消隐区:强制PWM输出为低电平 MOV pin=PWM_OUT, value=LOW ; 等待退出消隐角度的条件 WCAP event=UNC, reg=B, data=BLANK_END_ANGLE, cond_addr=PWM_GENERATE, next=DO_BLANK ; 在DO_BLANK循环,直到B == BLANK_END_ANGLE,才跳回PWM_GENERATE在这个例子中,WCAP指令的event=UNC和cond_addr被用来实现基于角度值的条件跳转,构建了一个简单的状态机。SCNT提供的精确角度时基是这一切的基础。
5.3 性能考量与调试技巧
- 指令循环时间:HET程序的执行时间是所有指令周期之和。
SCNT需要3个周期,WCAP需要1个周期,PWMs通常需要2个周期。必须确保在最坏的指令路径下,整个循环的执行时间小于SCNT的步进周期(即P(n-1)/K的时间),否则会丢失SCNT的Z标志事件,导致角度计算出错。设计时需要精简指令,必要时使用条件跳转跳过不必要的指令。 - 中断延迟:如果使用
WCAP或SHFT的中断功能通知CPU,需要考虑从中断触发到CPU开始读取HET数据域之间的延迟。对于高速事件,可能更适合让HET程序自行处理,或者使用DMA将HET的数据域直接传输到内存。 - 逻辑分析仪是利器:调试复杂的HET交互,一个多通道逻辑分析仪至关重要。可以同时捕获:
- 原始齿轮信号。
- 由
SCNT的Z标志触发的同步信号。 - 关键的HET输出引脚(如PWM)。
- 甚至可以利用HET的IO口,在特定指令处(如进入消隐例程)输出一个调试脉冲。通过观察这些信号的时间关系,可以直观地验证
SCNT的同步、WCAP的条件触发以及PWMs的输出是否正确。
- 寄存器与数据域监视:大多数HET开发环境(如TI的HET IDE或特定MCU的调试器)都允许实时查看和修改HET的寄存器(A, B, T)、数据域以及程序计数器。在关键点设置断点,观察这些值的变化,是排查逻辑错误的最直接方法。
6. 常见问题排查与优化实录
在实际项目中,使用HET高级指令时难免会遇到各种问题。下面记录了一些典型问题的排查思路和解决经验。
6.1 SCNT相关的问题
问题1:SCNT产生的同步脉冲不稳定,偶尔会多一个或少一个脉冲。
- 排查:首先检查
APCNT提供给SCNT的寄存器T值是否稳定。在齿轮信号正常齿区域,T值应该基本恒定(随转速微小变化)。如果T值跳动剧烈,问题出在APCNT的输入滤波或周期测量逻辑上。 - 检查:
SCNT的step参数K设置是否过大?如果K值太大,而P(n-1)值较小,可能导致SCNT在一个齿轮周期内多次溢出(Z标志置位多次),但ACNT可能只响应第一次。确保(P(n-1) / K) > 1且留有足够余量。 - 根源:最可能的原因是齿轮信号噪声。在缺齿附近或信号质量差时,
APCNT可能产生错误的周期测量,导致T值异常,进而扰乱SCNT的步进节奏。加强输入引脚的数字滤波(如果HET支持),或优化APCNT的缺齿检测算法。
问题2:在缺齿区域,角度计算出现累积误差。
- 排查:重点检查
gapstart的计算和传递。SCNT计算出的gapstart值是否正确写入寄存器A?ACNT指令是否在正确的位置(角度达到gapstart时)启用了间隙模式(忽略APCNT输入)? - 验证:可以在非缺齿区域和缺齿区域,分别读取
ACNT之后的角度计数器值。在缺齿区域,角度应继续平滑递增(基于SCNT的虚拟时基),而不应因为缺少齿轮脉冲而停滞。如果停滞,说明间隙模式未正确激活。
6.2 SHFT相关的问题
问题1:移位数据顺序错误(LSB/MSB混淆)。
- 确认:仔细核对
smode设置。OR0/OR1/ORZ是右移,LSB先出。OL0/OL1/OLZ是左移,MSB先出。这与一些常见协议(如SPI通常是MSB先出)可能相反。 - 调试:先使用
UNC条件,手动单步执行HET程序(如果调试器支持),或让程序慢速循环,用示波器观察每一位移出的顺序和电平。
问题2:使用外部时钟(HET31)触发时,数据移位不同步。
- 检查时钟质量:用示波器观察HET31引脚上的时钟信号,确保边沿干净,无振铃或毛刺。
- 检查HET31引脚配置:确保该引脚已正确配置为HET功能输入,并且上拉/下拉电阻配置与你的时钟驱动兼容。
- 理解同步点:
SHFT指令在cond=RISE/FALL时,是在检测到边沿的那个HET循环执行移位。如果HET程序循环很慢,而外部时钟很快,可能会丢失时钟边沿。确保HET循环频率至少是外部时钟频率的两倍(奈奎斯特采样定理),实际上建议5-10倍以上以保证可靠捕获。
6.3 WCAP相关的问题
问题1:边沿捕获不触发或误触发。
- 检查
Prv. bit初始化:如前所述,在程序开始阶段用一条event=NOCOND的WCAP指令初始化Prv. bit。 - 检查边沿极性:确认
event参数(RISE/FALL)与实际信号边沿匹配。 - 检查输入信号:确认信号已正确连接到HET引脚,并且电压电平在HET的输入容限内。使用示波器查看信号质量。
- 注意消抖:对于机械开关等慢速信号,边沿可能伴有抖动。HET的软件边沿检测没有硬件消抖功能。需要在外部电路或软件(在CPU侧)增加消抖处理,或者使用HET的输入滤波功能(如果可用)。
问题2:捕获的时间戳值跳变或不连续。
- 检查计数器源:
WCAP捕获的是你选择的寄存器(A, B, T)的值。确保这个寄存器在被捕获时正在按预期更新(例如,T寄存器由APCNT更新,A寄存器由SCNT更新等)。 - 中断服务程序速度:如果使用中断,并且中断服务程序读取捕获值的速度不够快,而下一次捕获很快又发生,可能会覆盖数据域的值,导致读取到错误数据。考虑使用双缓冲机制(两个
WCAP指令交替使用),或者使用DMA传输。 - HR/LR时钟域交叉:如果使用了
hr_lr=0进行HR捕获,hr_data属于HR时钟域,data属于LR时钟域。这两个时钟是异步的。在读取这两个值并组合时,需要确保它们是同一个捕获事件产生的。通常硬件会保证在捕获瞬间对两者进行同步采样,但读取软件的先后顺序也可能需要处理。
6.4 资源冲突与性能优化
- 引脚复用冲突:HET的引脚功能是复用的。确保你使用的
SHFT、WCAP或PWM输出等功能所分配的引脚,没有与其他外设(如GPIO、另一个定时器、ADC等)冲突。仔细查阅MCU的数据手册和引脚复用表。 - 程序内存与指令限制:HET的程序内存(Instruction RAM)大小有限。复杂的逻辑可能使程序超出容量。优化方法包括:使用循环和跳转减少重复指令;简化状态机;将不常用的功能移到CPU软件中实现。
- 减少循环时间:对于高动态性能应用,优化HET程序循环时间至关重要。
- 避免不必要的条件跳转分支。
- 将最频繁执行的路径放在程序前面。
- 考虑使用
CNT(计数)指令代替多个CMP(比较)指令来实现简单的计数器功能。 - 审查每条指令的周期数,
SCNT(3周期)和PWMs(2周期)通常较慢,尽可能合理安排。
驾驭HET的高级指令集,就像在为一个高度并行的、确定性的实时协处理器编写微代码。它要求开发者不仅理解每条指令的语义,更要能从系统层面思考时间、事件和数据的流动。从SCNT构建的同步时基,到SHFT处理的串行数据流,再到WCAP抓取的关键事件瞬间,这些指令共同将HET从简单的定时器,提升为一个能够处理复杂机电系统同步控制问题的强大引擎。