F28379D 下载后 VOFA+ 无数据、Reset 后恢复:一次 TZ 中断误触发排查记录

结论先行

在 LAUNCHXL-F28379D 上调试 SCIA 和 VOFA+ 时,出现了一个很有迷惑性的现象:程序下载后 VOFA+ 没有数据,gMainLoopCount 也不增加;在 CCS 中执行一次 Reset 后,程序却能进入 while(1),VOFA+ 随即正常显示数据。

最终确认,SCIA 初始化和 VOFA+ 发送代码并不是根本原因,真正的问题是 CMPSS 输入引脚悬空,导致 ePWM Trip Zone 保护被误触发

本工程的保护链路为:

ADCINA2/ADCINA3 悬空 → CMPSS1 输出不确定 → EPWM XBAR TRIP4 → DCAEVT1 → One-Shot TZ → TZ 中断持续触发 → CPU 无法稳定执行主循环 → VOFA+ 没有数据

Reset 之后暂时恢复,只是因为复位改变了外设状态以及悬空模拟引脚上的残余电荷,输入短时间内恰好没有触发保护。这种恢复具有偶然性,不能作为正常启动方案。

开发环境与工程配置

本次问题对应的主要环境如下:

  • MCU:TMS320F28379D
  • 开发板:LAUNCHXL-F28379D
  • IDE:Code Composer Studio 20.5.1
  • 配置工具:SysConfig 1.28 及以上版本
  • 上位机:VOFA+
  • 串口:SCIA,GPIO42 为 TX,GPIO43 为 RX
  • 串口参数:115200、8 数据位、无校验、1 停止位
  • VOFA+ 协议:FireWater

SysConfig 中还配置了 ADC、CMPSS、EPWM、EPWM XBAR、Digital Compare 和 Trip Zone,用于实现硬件过流保护。

故障现象

程序下载后主要表现为:

  • VOFA+ 串口指示有时闪烁,但没有形成有效波形;
  • gVofaSci.txFrameCount 和调试帧计数不增加;
  • gMainLoopCount 保持为 0,说明程序没有正常执行主循环;
  • 初始化步骤变量能够运行到 EINT 附近;
  • 在 CCS 中执行一次 Reset 并继续运行后,gMainLoopCount 开始增加,VOFA+ 也能接收数据。

由于 Reset 后串口能够正常发送,说明串口引脚、波特率和数据格式基本正确。问题重点应从"串口为什么发不出去"转向"CPU 为什么没有持续执行发送函数"。

为什么悬空的 ADC 引脚会触发 TZ

F28379D 的部分模拟引脚同时连接到 ADC 和 CMPSS。与本工程相关的两个引脚为:

  • ADCINA2 同时是 CMPIN1P
  • ADCINA3 同时是 CMPIN1N

因此,即使程序主要把它们当作差分 ADC 输入使用,只要启用了 CMPSS1,这两个引脚上的电压也会直接影响比较器输出。

模拟引脚悬空并不等于 0 V。悬空输入会受到以下因素影响:

  • ADC 采样保持电容的残余电荷;
  • 芯片输入漏电流;
  • 电源和 PWM 开关噪声;
  • 人体、导线和周围电路的电磁耦合;
  • 上一次采样和复位过程留下的瞬态电压。

因此,悬空引脚可能随机越过 CMPSS 阈值,使保护信号处于有效状态。

本工程的 CMPSS DAC 配置值为:

c 复制代码
CMPSS_setDACValueHigh(CMPSS1_BASE, 3225U);
CMPSS_setDACValueLow(CMPSS1_BASE, 869U);

当 CMPSS DAC 参考电压为 3.3 V 时,阈值可近似计算为:

V T H = 3225 4096 × 3.3 ≈ 2.60 V V_{TH} = \frac{3225}{4096}\times 3.3 \approx 2.60\text{ V} VTH=40963225×3.3≈2.60 V

V T L = 869 4096 × 3.3 ≈ 0.70 V V_{TL} = \frac{869}{4096}\times 3.3 \approx 0.70\text{ V} VTL=4096869×3.3≈0.70 V

只要比较器输入落到保护区间,CTRIPHCTRIPL 就可能使 EPWM XBAR 的 TRIP4 变为有效状态。

TZ 保护链路如何阻止主循环运行

本工程的硬件保护链路可以简化为:

CMPSS1 CTRIPH/CTRIPL → EPWM XBAR TRIP4 → DCAH → DCAEVT1 → One-Shot Trip Zone

SysConfig 生成的关键配置逻辑如下:

c 复制代码
XBAR_setEPWMMuxConfig(XBAR_TRIP4,
                      XBAR_EPWM_MUX00_CMPSS1_CTRIPH_OR_L);
XBAR_enableEPWMMux(XBAR_TRIP4, XBAR_MUX00);

EPWM_selectDigitalCompareTripInput(EPWM1_BASE,
                                   EPWM_DC_TRIP_TRIPIN4,
                                   EPWM_DC_TYPE_DCAH);

EPWM_setTripZoneDigitalCompareEventCondition(
    EPWM1_BASE,
    EPWM_TZ_DC_OUTPUT_A1,
    EPWM_TZ_EVENT_DCXH_HIGH);

EPWM_enableTripZoneSignals(EPWM1_BASE,
                           EPWM_TZ_SIGNAL_DCAEVT1);

Trip Zone 属于硬件快速保护。即使 CPU 还没有进入中断,DCAEVT1 也可以直接把 ePWM 输出强制到安全电平。

问题发生在全局中断开启之后:

c 复制代码
EINT;
ERTM;

while(1)
{
    gMainLoopCount++;
    VofaSci_SendCsv3U16(1U, 2U, 3U);
    DEVICE_DELAY_US(10000U);
}

如果 CMPSS 保护信号已经有效,CPU 执行 EINT 后会立即进入 EPWM1 TZ 中断。若 ISR 又立即清除所有 One-Shot 标志,而外部故障条件仍然存在,就会形成以下循环:

TZ 触发 → 进入 ISR → 清除 OST/DCAEVT1 → 悬空输入再次触发 → 再次进入 ISR

CPU 大部分时间都消耗在 TZ ISR 中,主循环中的 VOFA 发送函数得不到执行机会,于是表现为"串口没有数据"。

排查过程

检查 SCIA 与 VOFA+ 参数

首先检查了以下内容:

  • SCIA 是否使用开发板板载 USB-UART 对应的 GPIO42/GPIO43;
  • 波特率是否为 115200;
  • VOFA+ 是否选择正确的 COM 口;
  • 串口格式是否为 8N1;
  • FireWater 数据是否以逗号分隔,并以 \r\n 结束;
  • SCIA 发送计数是否增加。

由于 Reset 后相同程序能够发送数据,说明串口链路并没有根本性错误。

使用主循环计数判断程序位置

在主循环中增加计数变量:

c 复制代码
volatile uint32_t gMainLoopCount = 0UL;

while(1)
{
    gMainLoopCount++;
    VofaSci_SendCsv3U16(1U, 2U, 3U);
    DEVICE_DELAY_US(10000U);
}

第一次下载运行时,gMainLoopCount 不增加,说明问题发生在 VOFA 发送函数之前。继续观察初始化步骤,程序正好停留在全局中断开启附近,排查重点随即转向 ADC 和 TZ 中断。

临时关闭 TZ 的 CPU 中断

Board_init() 后临时加入:

c 复制代码
Board_init();

// 仅关闭CPU的EPWM1 TZ中断,用于定位问题。
// ePWM硬件Trip Zone动作仍然可以保持有效。
Interrupt_disable(INT_Phase_A_TZ);

关闭 TZ 的 CPU 中断后,程序能够直接进入 while(1),VOFA+ 也能正常显示数据。这一步证明问题来自 TZ 中断,而不是 SCIA。

检查模拟输入状态

进一步检查发现,ADCINA2 和 ADCINA3 均未连接任何稳定电压,处于悬空状态。由于这两个引脚同时是 CMPSS1 的输入,CMPSS 输出自然无法保持确定状态,最终导致 TZ 误触发。

正确处理方法

模拟保护输入不能悬空

测试差分 ADC 零输入时,可以先给 ADCINA2 和 ADCINA3 提供相同的稳定共模电压。例如使用两个电阻对 3.3 V 分压,获得约 1.65 V,再把两个输入都接到该电压。

此时:

  • 差分输入接近 0 V;
  • 16 位差分 ADC 结果通常接近中间码 32768;
  • 1.65 V 位于当前约 0.70~2.60 V 的阈值范围内;
  • CMPSS 高、低保护信号都应处于非故障状态。

实际设计仍需满足数据手册规定的 ADC 差分输入范围、共模电压和信号源阻抗要求。

低限保护需要正确设置极性

如果 CTRIPH OR CTRIPL 用于表示"超过上限或低于下限",低比较器输出通常需要配置为反相。生成代码应包含:

c 复制代码
CMPSS_configLowComparator(CMPSS1_BASE,
                          CMPSS_INSRC_DAC |
                          CMPSS_INV_INVERTED);

否则低比较器可能在输入高于低阈值时输出有效,使 CTRIPH OR CTRIPL 的逻辑与预期保护区间不一致。

One-Shot 中断不要在 ISR 中自动恢复 PWM

One-Shot 的作用是故障发生后锁存 PWM 关断状态,直到软件确认故障已经消失并主动恢复。因此 ISR 中只记录故障并确认 PIE 中断,不立即清除 OST:

c 复制代码
volatile uint16_t gPhaseATzFault = 0U;
volatile uint32_t gPhaseATzCount = 0UL;

__interrupt void INT_Phase_A_TZ_ISR(void)
{
    gPhaseATzFault = 1U;
    gPhaseATzCount++;

    // One-Shot故障保持锁存,不在ISR中清除OST。
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP2);
}

只有在确认 CMPSS 输入已经恢复到安全范围后,才执行恢复操作:

c 复制代码
void PhaseA_ClearTripAfterFaultRemoved(void)
{
    // 清除DCAEVT1对应的One-Shot来源标志。
    EPWM_clearOneShotTripZoneFlag(
        EPWM1_BASE,
        EPWM_TZ_OST_FLAG_DCAEVT1);

    // 清除TZ状态并恢复PWM输出。
    EPWM_clearTripZoneFlag(
        EPWM1_BASE,
        EPWM_TZ_FLAG_OST |
        EPWM_TZ_FLAG_DCAEVT1 |
        EPWM_TZ_INTERRUPT);

    gPhaseATzFault = 0U;
}

恢复前必须确保故障源已经无效。若 CMPSS 输出仍然处于保护状态,清除标志后会立即再次触发 TZ。

One-Shot 保护优先使用 OST 中断源

如果 DCAEVT1 已经作为 One-Shot Source,TZ 中断源更适合选择 OST,而不是直接选择持续有效的 DCAEVT1 电平中断。对应逻辑为:

c 复制代码
EPWM_enableTripZoneInterrupt(EPWM1_BASE,
                             EPWM_TZ_INTERRUPT_OST);

这样一次故障只需要进入一次保护 ISR,PWM 保持锁存关断,后续由主循环完成故障记录、状态显示和人工恢复。

推荐的调试顺序

为了避免多个模块互相干扰,可以按照以下顺序调试:

  1. 暂时关闭 TZ 的 CPU 中断,只测试 SCIA 和 VOFA+,确认主循环计数持续增加。
  2. 给 ADCINA2/ADCINA3 接入稳定电压,确认 ADC 差分结果合理。
  3. 单独观察 CMPSS 状态,确认正常输入不会触发高限或低限。
  4. 启用 EPWM XBAR 和 DCAEVT1,先验证硬件能够把 PWM 拉到安全电平。
  5. 将 TZ 中断源配置为 OST,并在 ISR 中只记录故障。
  6. 故障解除后,通过独立恢复函数清除 One-Shot 标志。

这种顺序可以快速判断问题发生在串口、ADC、CMPSS、XBAR、Digital Compare 还是 TZ 中断,避免把"主循环没有运行"误判成"串口发送代码错误"。

总结

本次 VOFA+ 无数据并不是 SCIA 驱动失效,而是 ADCINA2/ADCINA3 悬空后引起 CMPSS 输出不确定,进而触发 EPWM Trip Zone。全局中断开启后,CPU 持续处理 TZ 事件,主循环无法稳定运行,最终表现为 VOFA+ 没有数据。

这次排查得到几个重要结论:

  • 模拟比较器和 ADC 输入不能悬空;
  • 判断串口问题前,应先确认主循环是否真的在运行;
  • ePWM Trip Zone 的硬件关断不依赖 CPU 中断;
  • One-Shot 故障不应在 ISR 中立即自动恢复;
  • CTRIPH OR CTRIPL 做窗口保护时,需要检查低比较器极性;
  • Reset 后偶尔恢复不能说明问题已经解决,稳定输入和正确的保护状态机才是可靠方案。

当 VOFA+ 没有数据时,除了检查串口参数,还应重点观察 gMainLoopCount、CMPSS 状态、TZFLG 和 ISR 计数。只要先确认 CPU 实际运行到了哪里,排查范围就会迅速缩小。

参考资料

相关推荐
国科安芯1 小时前
空间机电一体化:AS32S601型抗辐射MCU在卫星推进与执行机构控制中的关键技术研究
单片机·嵌入式硬件·物联网·机器人·云计算
国科安芯1 小时前
AS32S601型抗辐射MCU在分布式太空算力架构中的技术演进与应用前景
人工智能·分布式·单片机·嵌入式硬件·架构·边缘计算
纯音乐sjc2 小时前
ARM Linux 嵌入式中断全流程解析:从 GPIO 到 GIC 架构实战
单片机·嵌入式硬件
雯宝2 小时前
|____1.4外部中断/看门狗/定时器/PWM/RTC/待机唤醒/ADC/DAC/IIC/SPI/485/CAN
单片机
星恒随风2 小时前
C++ STL 详解:list 的使用、迭代器失效、模拟实现与 vector 对比
开发语言·数据结构·c++·笔记·学习·list
一起努力啊~2 小时前
DataWhale组队学习笔记--llm-algo-leetcode(五)
笔记·学习·llm
是上好佳佳佳呀3 小时前
【机器学习|DAY03】K近邻算法(KNN)笔记
笔记·机器学习·近邻算法
圣光SG13 小时前
Servlet学习笔记
笔记·学习·servlet
奋发向前wcx13 小时前
y1,y2总复习笔记5 2026.7.19
数据结构·笔记·算法