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小时)
- 编译现有dll
- 运行demo程序
- 观察SFIFO数据读取是否正常
- 如有问题,检查DeviceIoControl返回值
步骤2: 实现错误处理函数(30分钟)
-
在
zt9054/sys/dll/PCI8KPLX.cpp中添加:ZT_API unsigned long _stdcall GetLastErr(unsigned long cardNO); ZT_API void _stdcall ClearLastErr(unsigned long cardNO); -
导出这些函数到.def文件
步骤3: 实现EEPROM读取函数(2-3小时)
- 创建
zt9054/sys/dll/ROMAD.cpp - 实现
RomAdReadZeroCode和RomAdReadFullCode - 确保CEEPROM的I2C基础函数可用
- 查阅硬件文档确认:
- EEPROM控制寄存器偏移
- SDA/SCL控制位定义
- 零点/满度数据在EEPROM中的存储地址
步骤4: 实现特殊控制函数(1小时)
- 实现
SetCanWrite - 查阅硬件文档确认控制位
步骤5: 集成测试(2小时)
- 编译完整dll
- 运行demo程序
- 验证所有功能
- 修复发现的问题
四、需要确认的硬件信息
以下信息需要查阅PLX 9054和FPGA的硬件文档:
-
EEPROM相关:
-
控制寄存器:
-
参考文档:
- PLX 9054芯片手册
- FPGA寄存器定义文档
- 数据采集卡硬件说明书
五、文件修改清单
需要新建的文件:
需要修改的文件:
需要验证的文件:
六、测试检查清单
文档版本: 1.0
创建日期: 2026-01-24
更新记录: 初始版本,明确待实现函数和实施步骤
接下来就是调试工作了。
浙公网安备 33010602011771号