项目分析结果
我已经仔细阅读了项目的关键文件,下面是我的分析。
一、Panel2-Panel4 没有数据的原因 ------ 找到了多个Bug
这是一个WinForms C#多端口光模块自动测试软件,主界面是 FourDutFrm,里面放了4个 TestControl(每个port对应一个)。问题出在 FourDutFrm.cs 的初始化和定时器逻辑上,有3个关键Bug:
Bug 1(根本原因):testControl2/3/4 的 InitForDut() 没有被调用
在 FourDutFrm_Load() 中:
- DUT1 (第63-65行):调用了
testcontrol.DeviceConn()和testcontrol.InitForDut(),正确初始化了设备引用和通道配置 - DUT2/3/4 (第74-114行):只做了
GlobalVarFun.mycontrol_dut2 = testControl2赋值,没有调用testControl2.InitForDut()/testControl3.InitForDut()/testControl4.InitForDut()
没有调用 InitForDut() 的后果:
_evb字段停留在字段初始化值new EVB()(未连接的空实例),没有指向GlobalVarFun.Evb(已连接的设备)_evbSlot、_opmCh、_voaCh、_bertCh、_vcc、_txBias等全部是默认值(0),不是对应的槽位1/2/3/4- 所有I2C读操作都走了一个未连接的EVB实例,全部返回null → 所以面板上没有任何数据
Bug 2:主定时器 timer1_Tick 只处理 DUT1
在 timer1_Tick() 中(第179行开始):
- 调用的是
ShowModuleDdmInfo(),而这个方法内部使用的是局部变量testcontrol(即DUT1的TestControl) - 只判断
TestResult.vccDDM < 2.0(DUT1的结果) - 只调用
mycontrol_dut1.CheckDebugPWD() StartNewTestSequence()也只对DUT1启动测试流程
DUT2/3/4的模块插入检测、DDM刷新、自动测试启动逻辑全部缺失。
Bug 3:testControl2/3/4 的 DutId 不正确
testControl2/3/4 是由Visual Studio设计器(InitializeComponent())创建的。TestControl 的构造函数是 TestControl(byte dutId),设计器创建时要么使用了默认构造函数(如果存在的话),要么传入的dutId是1(默认值),导致它们认为自己都是DUT1。对比代码中DUT1是手动创建的:
csharp
TestControl testcontrol = new TestControl(TestSet.Dut); // dutId = 1
// TestControl testcontrol2 = new TestControl(TestSet2.Dut); // 被注释掉了!
第34行被注释掉的代码证明原来DUT2也是手动创建的,但后来改成了设计器拖拽方式,却忘了正确初始化。
二、如何快速修复(需要切换到Act模式后我可以帮你改)
修复步骤:
- FourDutFrm_Load 中,为testControl2/3/4添加
InitForDut()调用 - 确保testControl2/3/4构造时传入正确的dutId(2/3/4),或者在InitForDut之前设置
- timer1_Tick 中添加DUT2/3/4的DDM刷新和模块检测逻辑
- 修复EVB基类的线程安全问题(
_slot字段在多线程并发下会串位)
三、如何高效熟悉这个项目
项目架构梳理:
| 层次 | 文件/目录 | 作用 |
|---|---|---|
| 程序入口 | Program.cs → LoginFrm → ConnectFrm → FourDutFrm |
登录→连接设备→主测试界面 |
| 主界面 | FourDutFrm.cs |
4端口容器,放4个TestControl |
| 单端口界面(旧) | TestSourceFrm/TestDut2Frm/... |
原来单/双端口版本的遗留代码,可以参考 |
| 核心测试控件 | TestControl.cs |
最重要的文件,封装了单个端口所有测试逻辑 |
| 设备驱动层 | Device/ 目录 |
你写的OTP12Driver(光开关/光功率计/VOA/BERT)、SFP_EVB_Heater(加热台EVB板) |
| 模块协议 | Module/ 目录 |
SFP-8472、SFF-8436等协议解析,DDM读取、A0/A2页数据解析 |
| 测试流程 | Algorithm/ 目录 |
APC校准、LOS校准、接收功率校准等算法 |
| 全局数据 | Data/Common.cs |
TestSet/TestResult/GlobalVarFun,4套独立的TestResult1-4对应4个端口 |
| 数据库 | SQLserver/ 目录 |
测试记录保存到SQL Server |
建议学习路线(按优先级):
- 先看 Program.cs → ConnectFrm.cs(30分钟):理解程序启动流程,设备怎么连接的
- 重点看 TestControl.cs (2-3小时):这是核心,理解一个端口从插入模块到完成测试的完整流程:
InitForDut()→ 初始化设备和通道映射dataRefresh_Tick/ShowModuleDdmInfoAndCheck()→ 定时刷新DDMFirstTestProcessAsync()→ 初测流程FinalTestProcessAsync()→ 终测流程Read_moduleInfo()/Converted_analog_values()→ I2C读DDM并换算
- 对照你写的驱动看 TestControl 里怎么调用设备 (1小时):看OTP12的槽位映射(
VOAtxDutToSlot/VOArxDutToSlot/OpmDutToOtpSlot),理解光开关路由逻辑 - 看 Module/ 目录的模块类(1小时):理解A0/A2内存布局,DDM校准公式
- 看 FourDutFrm.cs(30分钟):理解4端口如何并行工作,修复上面提到的Bug
- 看 SetupFrm.cs(30分钟):理解测试参数怎么配置的
调试技巧:
- 车间设备在生产,你可以在你的电脑上用Visual Studio接设备调试
- 在
timer1_Tick和ShowModuleDdmInfo()里加断点,看数据怎么流动的 - 看日志文件
D:\SFPXFPTesTLogDUT1.txt了解测试流程顺序 - 关键数据流:EVB(I2C) → Read_moduleInfo() → Converted_analog_values() → TestResult.xxxDDM → UI显示
你是否确认以上分析?如果确认,请切换到Act模式,我来帮你修复panel2-4无数据的Bug。
项目分析和Bug诊断结果
一、项目整体架构
启动流程:Program.cs → ConnectFrm(连接设备) → LoginFrm(登录配置) → FourDutFrm(主界面)
├── panel1 = TestDut2Frm (dut=1, 模块槽位1)
├── panel2 = TestDut3Frm (dut=2, 模块槽位2)
├── panel3 = TestDut4Frm (dut=3, 模块槽位3)
└── panel4 = TestSourceFrm (dut=4, 模块槽位4/光源端)
核心分层:
- Device层 (你写的):
SFP_EVB_Heater.cs(EVB加热台TCP驱动)、OTP12Driver.cs(光开关/光功/VOA/BERT驱动) - Module层:每种模块类型的测试逻辑(SFPUX3320T / SFPPGN1196),每个Dut(1~4)有独立子类
- Data/Common层 :
EVB抽象基类、ModuleTest抽象基类、全局变量类GlobalVarFun、配置类TestSet/2/3/4 - UI层:4个测试窗体 + TestControl(核心测试控制器,所有测试逻辑都在这里)
关键设计: 4个TestControl实例共享同一个 GlobalVarFun.Evb(SFP_EVB_Heater单TCP连接),通过slot参数(1~4)区分控制哪个物理端口。OTP12也是单例共享,通过SendScpiToSlot(slot, cmd)切换不同板卡。
二、🔴 panel2~4无数据的根本原因
经过代码分析,所有EVB操作(电压/电流/功率查询、IO控制、部分I2C命令)都没有传递Dut(slot)参数! 这导致所有4个TestControl实例都在操作slot=1(端口1)。
问题1:EVB功率/电压/电流查询没有传slot(TestControl.cs 多处)
csharp
// Converted_analog_values() 和 FirstTestProcessAsync() 中:
TestResult.vcc = Convert.ToDouble(i2c.GetVoltage()) / 1000; // ❌ 默认slot=1
TestResult.bias = Convert.ToDouble(i2c.GetCurrent()) / 100; // ❌ 默认slot=1
TestResult.TxPwr_meter = Convert.ToDouble(i2c.GetPower()) / 100; // ❌ 默认slot=1
AddTestLog("Vcc:" + i2c.GetVoltage()); // ❌ 默认slot=1
应该改为:
csharp
TestResult.vcc = Convert.ToDouble(i2c.GetVoltage(Dut)) / 1000;
TestResult.bias = Convert.ToDouble(i2c.GetCurrent(Dut)) / 100;
TestResult.TxPwr_meter = Convert.ToDouble(i2c.GetPower(Dut)) / 100;
问题2:EVB IO控制没有传slot(Converted_analog_values()中)
csharp
i2c.SetPowerEN(1); // ❌ 只开启了slot1的电源!slot2/3/4没上电
i2c.SetTxDis(0); // ❌ 只控制slot1
i2c.SetRs0High(0); // ❌
i2c.SetRs1High(0); // ❌
string rx_los1 = i2c.GetRxLos(); // ❌ 读的是slot1
string abs = i2c.GetABS(); // ❌ 读的是slot1
string txfault = i2c.GetTxFalu();// ❌
应该改为:
csharp
i2c.SetPowerEN(1, Dut);
i2c.SetTxDis(0, Dut);
i2c.SetRs0High(0, Dut);
i2c.SetRs1High(0, Dut);
string rx_los1 = i2c.GetRxLos(Dut);
string abs = i2c.GetABS(Dut);
string txfault = i2c.GetTxFalu(Dut);
问题3:Read_moduleInfo()中IIC初始化命令没有传slot
csharp
i2c.IIC_Set("50", "7F", "1", "00"); // ❌ 默认slot=1
i2c.IIC_Set("50", "7E", "1", "00"); // ❌ 默认slot=1
应该改为:
csharp
i2c.IIC_Set("50", "7F", "1", "00", Dut);
i2c.IIC_Set("50", "7E", "1", "00", Dut);
总结:slot2/3/4模块电源根本没有被开启(SetPowerEN只对slot=1生效),所以模块没有上电,I2C读不到任何数据,UI自然无显示。
⚠️ 注意:OTP12Driver的光开关路由
SW_SetRouteForModule(moduleSlot, isTxTest)看起来是正确的(根据moduleSlot选择slot11/12和通道1-4),但也需要实际硬件验证。
三、如何高效熟悉这个项目
| 顺序 | 学习内容 | 方法 | 预计时间 |
|---|---|---|---|
| 1 | 跑通启动流程 | 从Program.cs开始,F5单步调试:ConnectFrm→LoginFrm→FourDutFrm,看每个窗体做什么 | 0.5天 |
| 2 | 理解你写的两个驱动如何被调用 | 在SFP_EVB_Heater的SendCommand和OTP12Driver的SendScpiCmd里打断点,看谁在调用、传什么参数 | 0.5天 |
| 3 | 看懂TestControl测试流程 | 重点看3个方法:Converted_analog_values()(上电+读DDM)、FirstTestProcessAsync()(初测流程)、FinalTestProcessAsync()(终测流程) |
1天 |
| 4 | 看懂Module子类差异 | 对比SFPUX3320T.cs和SFPUX3320T_dut2/3/4.cs,理解不同slot需要什么特殊处理 | 0.5天 |
| 5 | 理解配置系统 | TestSet/TestSet2/TestSet3/TestSet4是每个端口的测试参数配置(功率范围、波长等),对应SetupFrm设置界面 | 0.5天 |
| 6 | 理解光通路切换 | OTP12Driver.SW_SetRouteForModule()和FirstTestProcessAsync中的光开关控制逻辑 | 0.5天 |
学习技巧:
- 在
SFP_EVB_Heater.SendCommand()第一行加断点,每次TCP通信都会停下,看命令格式和返回值 - 在
OTP12Driver.SendScpiToSlot()加断点,看光开关/功率计/VOA的命令 - 利用日志:
log/目录下有运行日志,AddTestLog()方法会输出测试步骤信息 - 4个Dut窗体结构完全对称,理解了TestDut2Frm(dut=1),其他3个是一样的模式
四、修复计划
要修复panel2~4无数据的问题,需要修改 TestControl.cs 中以下位置,将Dut字段作为slot参数传递给所有EVB方法调用:
- Converted_analog_values()方法:SetPowerEN/SetTxDis/SetRs0High/SetRs1High/GetRxLos/GetABS/GetTxFalu/GetVoltage/GetCurrent/GetPower 全部加Dut参数
- FirstTestProcessAsync()方法:所有GetVoltage/GetCurrent/GetPower调用加Dut参数
- Read_moduleInfo()方法:IIC_Set("50",...)调用加Dut参数
- FinalTestProcessAsync()等其他测试方法:排查所有i2c.XXX()调用确保传了slot
需要切换到Act模式来执行代码修复。请确认以上分析是否正确,是否需要我切换到Act模式进行修复?