PCI9x5x驱动移植支持PCI9054在win7下使用5

接上文,本文章继续记录中泰联创的数据采集卡驱动翻新过程。

移植应用层代码

继续给Qoder下指令:

参照sys目录下的代码,以及已经修改好的zt9054/sys/dll里面的OpenIRQ、CloseIRQ、EnableAD、DisableAD等四个函数,根据应用程序目录下的调用流程,完善zt9054/sys/目录下的内核驱动和dll,除了中断和DMA必要操作,将内核操作的和本地总线相关的代码全部转移到dll中

Qoder很快完成工作,但是把部分原来有的代码给改坏了,告诉他不要修改之前已经写好的代码,又重新生成了一边,编译的时候又报了几个错误,粘贴给Qoder,很快就解决了

Qoder在实现之前先生成了一个清单,我看了没有什么大问题,就让她开始干活了。生成的代码依然编译无法通过,不过将错误代码赋值给她后,也很快解决了。

Qoder生成的待实现函数清单:

一、重要说明

1.1 已实现函数(请勿修改)

以下函数已经完成实现,不要修改

  • ReadD / WriteD - 寄存器读写
  • EnableAD / DisableAD - AD启停
  • InitIRQ / OpenIRQ / CloseIRQ - 中断控制

1.2 使用的寄存器读写宏

继续使用原有的宏定义,不要修改

#define READD CZTCARD::ReadD
#define WRITED CZTCARD::WriteD
#define _READ MEM_READD
#define _WRITE MEM_WRITED

二、需要补充实现的函数列表

根据 数据采集卡加波形CS82/demo2008CS82/DEMODlg.cpp 的调用分析,需要实现以下函数:

2.1 SFIFO操作函数(优先级:高)

位置: zt9054/sys/dll/SFIFO.cpp
状态: 已基本实现,需验证

函数 调用位置 实现状态 说明
GetSFifoDataCount DEMODlg.cpp:L451, L453, L529 ✅ 已实现 获取SFIFO数据计数
ReadSFifo DEMODlg.cpp:L454 ✅ 已实现 从SFIFO读取数据
ClearSFifo DEMODlg.cpp:L500 ✅ 已实现 清空SFIFO
SetSFifoThreshold DEMODlg.cpp:L504 ✅ 已实现 设置SFIFO阈值

验证要点

  • 确认DeviceIoControl调用正确
  • 确认返回值处理正确
  • 测试大数据量读取

2.2 EEPROM/ROM操作函数(优先级:高)

位置: zt9054/sys/dll/ROMAD.cpp (需要创建或完善)
参考: dll2008/ROMAD.cpp

函数 调用位置 实现状态 说明
RomAdReadZeroCode DEMODlg.cpp:L232 ❌ 未实现 读取通道零点码值
RomAdReadFullCode DEMODlg.cpp:L234 ❌ 未实现 读取通道满度码值

实现要点

2.2.1 创建ROMAD.cpp文件
// zt9054/sys/dll/ROMAD.cpp
#include "stdafx.h"
#include "ZTCARD.h"

// 从EEPROM读取零点码值
ZT_API long _stdcall RomAdReadZeroCode(ULONG chNO, ULONG reserved, short *pZeroCode)
{
    // 实现参考 dll2008/ROMAD.cpp 中的对应函数
    // 使用 CEEPROM::Rom_ReadW 读取EEPROM
    
    ULONG cardNO = 1; // 假设单卡系统
    CHECK_CARDNO(cardNO);
    
    if (!pZeroCode) {
        g_errorLevel = ERR_PARAMETER_NULL_POINTER;
        return -1;
    }
    
    // EEPROM地址计算:基址 + 通道偏移
    // 假设每通道零点占2字节,从地址0x100开始
    ULONG romAddr = 0x100 + chNO * 4; // 每通道4字节(零点2字节+满度2字节)
    
    long result = CEEPROM::Rom_ReadW(cardNO, romAddr);
    if (result < 0) {
        g_errorLevel = ERR_EEPROM_READ;
        return -1;
    }
    
    *pZeroCode = (short)result;
    return ZT_SUCCESS;
}

// 从EEPROM读取满度码值
ZT_API long _stdcall RomAdReadFullCode(ULONG chNO, ULONG reserved, short *pFullCode)
{
    ULONG cardNO = 1;
    CHECK_CARDNO(cardNO);
    
    if (!pFullCode) {
        g_errorLevel = ERR_PARAMETER_NULL_POINTER;
        return -1;
    }
    
    // EEPROM地址计算:零点地址 + 2字节
    ULONG romAddr = 0x100 + chNO * 4 + 2;
    
    long result = CEEPROM::Rom_ReadW(cardNO, romAddr);
    if (result < 0) {
        g_errorLevel = ERR_EEPROM_READ;
        return -1;
    }
    
    *pFullCode = (short)result;
    return ZT_SUCCESS;
}
2.2.2 EEPROM基础I2C操作(继承CEEPROM类)

CEEPROM类的I2C操作需要使用FPGA寄存器,参考 dll2008/EEPROM.cpp

// CEEPROM类中的基础操作已在 dll/PCI8KPLX.cpp 中定义
// 需要确保以下函数正确实现:

static long CEEPROM::Rom_ReadW(ULONG cardNO, ULONG romAddr)
{
    // 通过I2C协议读取EEPROM
    // 1. 发送START位
    SetStartBit(cardNO, 1);
    
    // 2. 发送设备地址 + 写命令
    Write8bits(cardNO, 0xA0, 1); // EEPROM设备地址
    if (ReadACK(cardNO, 1) != 0) return -1;
    
    // 3. 发送高地址字节
    Write8bits(cardNO, (romAddr >> 8) & 0xFF, 1);
    if (ReadACK(cardNO, 1) != 0) return -1;
    
    // 4. 发送低地址字节
    Write8bits(cardNO, romAddr & 0xFF, 1);
    if (ReadACK(cardNO, 1) != 0) return -1;
    
    // 5. 重新START + 读命令
    SetStartBit(cardNO, 1);
    Write8bits(cardNO, 0xA1, 1); // 读命令
    if (ReadACK(cardNO, 1) != 0) return -1;
    
    // 6. 读取高字节
    UCHAR highByte = Read8bits(cardNO, 1);
    WriteACK(cardNO, 1); // 发送ACK
    
    // 7. 读取低字节
    UCHAR lowByte = Read8bits(cardNO, 1);
    WriteACK(cardNO, 1); // 发送NACK
    
    // 8. 发送STOP位
    SetStopBit(cardNO, 1);
    
    return (highByte << 8) | lowByte;
}

关键寄存器(需要查看硬件文档确认):

  • EEPROM控制寄存器偏移量(假设为64)
  • SDA和SCL控制位

2.3 错误处理函数(优先级:中)

位置: zt9054/sys/dll/PCI8KPLX.cpp

函数 调用位置 实现状态 说明
GetLastErr DEMODlg.cpp:L531 ❌ 未实现 获取最后错误码
ClearLastErr DEMODlg.cpp:L501 ❌ 未实现 清除错误码

实现示例

// 全局错误码变量(已在PCI8KPLX.cpp中定义)
extern ULONG g_errorLevel;

ZT_API unsigned long _stdcall GetLastErr(unsigned long cardNO)
{
    CHECK_CARDNO(cardNO);
    return g_errorLevel;
}

ZT_API void _stdcall ClearLastErr(unsigned long cardNO)
{
    CHECK_CARDNO(cardNO);
    g_errorLevel = ZT_SUCCESS;
}

2.4 特殊控制函数(优先级:低)

位置: zt9054/sys/dll/PCI8KPLX.cpp

函数 调用位置 实现状态 说明
SetCanWrite DEMODlg.cpp:L512, L517 ❌ 未实现 控制AD期间是否可写IO

实现示例

ZT_API long _stdcall SetCanWrite(unsigned long cardNO, ULONG canWrite)
{
    CHECK_CARDNO(cardNO);
    
    // 读取当前控制字
    ULONG ctrlWord = READD(cardNO, OFF_CTRLWORD);
    
    // 假设bit14控制写保护(需查看硬件文档确认具体位)
    if (canWrite) {
        ctrlWord |= (1 << 14);
    } else {
        ctrlWord &= ~(1 << 14);
    }
    
    WRITED(cardNO, OFF_CTRLWORD, ctrlWord);
    
    return ZT_SUCCESS;
}

三、实施步骤建议

步骤1: 验证SFIFO函数(1小时)

  1. 编译现有dll
  2. 运行demo程序
  3. 观察SFIFO数据读取是否正常
  4. 如有问题,检查DeviceIoControl返回值

步骤2: 实现错误处理函数(30分钟)

  1. zt9054/sys/dll/PCI8KPLX.cpp 中添加:

    ZT_API unsigned long _stdcall GetLastErr(unsigned long cardNO);
    ZT_API void _stdcall ClearLastErr(unsigned long cardNO);
    
  2. 导出这些函数到.def文件

步骤3: 实现EEPROM读取函数(2-3小时)

  1. 创建 zt9054/sys/dll/ROMAD.cpp
  2. 实现 RomAdReadZeroCodeRomAdReadFullCode
  3. 确保CEEPROM的I2C基础函数可用
  4. 查阅硬件文档确认:
    • EEPROM控制寄存器偏移
    • SDA/SCL控制位定义
    • 零点/满度数据在EEPROM中的存储地址

步骤4: 实现特殊控制函数(1小时)

  1. 实现 SetCanWrite
  2. 查阅硬件文档确认控制位

步骤5: 集成测试(2小时)

  1. 编译完整dll
  2. 运行demo程序
  3. 验证所有功能
  4. 修复发现的问题

四、需要确认的硬件信息

以下信息需要查阅PLX 9054和FPGA的硬件文档:

  1. EEPROM相关

  2. 控制寄存器

  3. 参考文档

    • PLX 9054芯片手册
    • FPGA寄存器定义文档
    • 数据采集卡硬件说明书

五、文件修改清单

需要新建的文件:

需要修改的文件:

需要验证的文件:


六、测试检查清单


文档版本: 1.0
创建日期: 2026-01-24
更新记录: 初始版本,明确待实现函数和实施步骤

接下来就是调试工作了。

posted @ 2026-01-25 05:31  自由的好好干活  阅读(2)  评论(0)    收藏  举报