一次“载电流显示为 0“的排查经历:负值钳位引发的踩坑

目录

一、背景

二、现象

三、排查过程

[1. 先梳理数据链路](#1. 先梳理数据链路)

[2. 新旧版本 diff,圈定改动范围](#2. 新旧版本 diff,圈定改动范围)

[3. 真正的根因](#3. 真正的根因)

[4. 修复方案](#4. 修复方案)

四、经验总结


标签:嵌入式 / FPGA / STM32 / 双向电源 / 调试笔记

一、背景

产品是一台双向直流电源,支持两种工作模式:

  • 源模式(Source):向外输出功率,电流为正;

  • 载模式(Sink) :吸收功率,电流为负。 系统架构是典型的"FPGA + MCU"方案:

    AD7606(ADC采样) → FPGA(校准/滤波/多通道求和) → 并行总线 → STM32H7(M7内核) → 显示/上报

FPGA 负责把 AD 采样的原始码值做系数校准、偏置修正、低通滤波,以及两通道电流求和(并联运行时的总电流),再通过并行数据口发给 M7。M7 把 FPGA 的 Q19 定点数换算成浮点物理量,经过一阶低通后用于显示和上位机上报。 近期做了一次版本升级,改动主要有两块:

  1. FPGA:新增了 CH1+CH2 的电流/电压求和通路,并把求和结果回注到"并机采样"数据通道;
  2. M7:显示电流不再用本机值顶替,改为真正使用 FPGA 传来的并机求和值,同时给一批采样值加了"负值钳位为 0"的处理。

二、现象

改版后联调,源模式一切正常,载模式下电流显示直接是 0 。 在线调试观察,"FPGA 传过来的电流值"也是 0。第一反应很自然:是不是 FPGA 求和通路写错了,把数据算成了 0?

三、排查过程

1. 先梳理数据链路

遇到"某数据变成 0"的问题,第一步是把链路完整捋一遍,确认每一级是谁、改了谁:

复制代码
AD7606 → FPGA校准/求和(DisSampleAdjust / CtrlSampleAdjust_offset)
       → 通信接口(armm4_if,显示电流在 addr 39/40)
       → M7 的 AppFpgaData(原始 int32)
       → APP_AICalculate(Q19→浮点换算)
       → 低通滤波 → 显示/Modbus上报

2. 新旧版本 diff,圈定改动范围

手上有新旧两套工程,直接逐文件 diff:

  • FPGA 侧:通信接口和寄存器地址映射一字未动;新增的求和状态机逐步检查了流水线时序、饱和判断,逻辑上没有问题;
  • M7 侧 :整个工程只有 4 个文件有差异,其中 APP_AICalculate.c 是数据换算的核心。 到这里,FPGA"算错成 0"的嫌疑基本可以排除了------发送链路没变,接收端的换算代码变了。

3. 真正的根因

对比新旧代码,发现新版 M7 有两处关键改动:

改动一:给多个电流量新增了负值钳位

复制代码
pCalcuData->IodisParall = (float)pFpgaData->IodisParall * Q19_TO_Q0;
if(pCalcuData->IodisParall < 0.0f)      // ← 新增
{
    pCalcuData->IodisParall = 0.0f;
}

Iodis(显示电流)、IodisParall(并机显示电流)、IoctrlParall、IoctrlParallcomm 全部加了 < 0 → 0 的钳位。

改动二:显示值强制改用并机求和值 各种运行模式下,Iodisall / Ioctrlall 在几乎所有分支里被替换成了上面这些钳位后的并机值。 问题就在这里:

载模式下电流本来就是负的 。系统里"源/载自动判别"甚至就是靠 Iodisall < 0 来判断载模式的。钳位一加,负电流全部变成 0,显示自然是 0;顺带连源/载自动判别也一起失效了------钳位后的值恒非负,永远判成"源模式"。 所以"在线看 FPGA 传过来就是 0"其实是个误导:发送方传的是负数,是接收端把它钳成了 0 。如果你 watch 的是换算之后的变量(pCalcuData->IodisParall),看到的就是钳位后的 0;只有 watch 原始的 pFpgaData->IodisParall(int32)才能看到真实的负值。 这也解释了为什么只有载模式出问题:源模式电流为正,钳位不起作用,一切正常。

4. 修复方案

修复思路:按工作模式区别对待------源模式保留钳位(吸收空闲时采样的小负偏移),载模式放行负值。 系统配置里已有工作模式字段(3 = 源模式,4 = 载模式),把四处钳位改成条件钳位:

复制代码
// 仅源模式(PowerMode==3)钳位;载模式电流为负是物理事实,必须放行
if((pSysCfg->SysCfgControl.PowerMode == 3) && (pCalcuData->IodisParall < 0.0f))
{
    pCalcuData->IodisParall = 0.0f;
}

同样的处理应用到 Iodis、IoctrlParall、IoctrlParallcomm 三处。电压类采样(输出电压等)的钳位保持不变------电压不存在负值的合法场景。 修改后重新编译下载:

  • 源模式:空闲时的小负偏移仍被钳到 0,显示干净;
  • 载模式:负电流正常显示,源/载自动判别恢复工作。

四、经验总结

  1. "传过来就是 0" ≠ 发送方的问题。 接收端的换算、钳位、滤波单元同样会"制造"0。判断时一定要区分"原始值"和"处理后的值",在线调试 watch 对变量。
  2. 符号是有语义的,钳位前先问一句"这个量合法地取负值吗"。 电流在双向系统里天然带符号(源为正、载为负),电压/温度才适合无脑钳非负。给"带符号语义的量"加钳位,是最容易埋雷的地方。
  3. 钳位的副作用可能蔓延到依赖它的其他逻辑。 本例中源/载自动判别、功率计算、并机内阻计算都依赖电流的符号。改一个数的取值范围,要 grep 一遍它的所有消费者。
  4. 新旧版本 diff 是定位回归问题最快的路径。 这次从"看到现象"到"锁定根因"只花了很短时间,靠的就是对相邻版本做逐文件 diff,把排查范围从几十万行代码压缩到 4 个文件。
  5. 联调现象要和版本改动对齐着看。 "源模式正常、载模式为 0"这个不对称现象本身就在暗示:问题出在符号处理上,而不是数据通路上。
相关推荐
yingheceping5 小时前
复旦微FPGA开发板厂商TOP5甄选榜:2026选型参考
fpga开发·fpga
NamoAmitabha1287 小时前
PL 端的 GPIO IP(AXI GPIO)---PS控制----deepseek
fpga开发·zynq--ps
hahaha601610 小时前
3D降噪算法YUV降噪FPGA实现
fpga开发
Hello-FPGA1 天前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安1 天前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha60161 天前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld1 天前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家2 天前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家2 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x