基于PXI总线的高速数字传输模块设计及正交解调的实现(三)
5.3 PXI数字传输模块软件面板的设计和测试结果
本课题上层应用程序是通过VC++工具进行开发的。之所以选择VC++是因为驱动程序也是在该软件平台上编写与实现的,这样便于应用程序与底层驱动的调用与衔接。应用程序访问设备驱动程序,一般由两种方法,一种是在应用程序中直接编程访问驱动程序,第二种方法是先利用 VC 等语言编写与驱动程序的接口,将函数封装成动态链接库供其它应用程序调用。这两种方法各有利弊,前一种方法比较灵活,应用程序几乎可实现对硬件的全面操作,但这种办法需应用程序开发工具支持与驱动程序的接口,并且开发者要全面了解驱动程序和硬件结构。后一种方法灵活性差,但动态连接库写好后上层应用程序可以用几乎任何一种高级语言写。并且由于应用程序和驱动程序之间隔了一层动态连接库,因此用户可以不用太关心驱动程序的情况和硬件结构。本课题选用直接接口设计。
直接接口与通过动态连接库实现接口,除了在接口上有区别之外,在打开设备,读写设备等方面两者是一样的。下面介绍一下接口和界面的实现步骤[40]。
(1)定义应用程序与设备驱动程序接口所需的唯一标识号GUID。
(2)编写接口函数。
(3)得到与对应GUID相关的信息。
(4)获取接口数据。
(5)获取符号连接名长度。
(6)获取符号连接名。
(7)创建文件,由于任何设备在Windows中都被认为是一个文件,所以从创建完文件开始,对该设备的操作将都使用文件读写函数完成。
(8)应用程序通过写文件函数,向设备驱动程序发送读写请求。
根据上述步骤设计的软面板如图5-5所示。通过软面板可以实现各种模式下的数据读写功能。
最后对设计出来的板卡进行了硬件测试,在应用程序中编写如下简单程序:
void CPDC4000DemoDlg::OnBlockDmaPciToLocalDemo()//DMA模式输出数据
{
unsigned char pData[0x100];//待输出的数组
for (int i = 0; i < 0x100; i ++)
{
pData[i] = i + 0x0;
}
m_iStatus = STATUS_BLOCK_WRITE;
BlockDmaPciToLocal(pData, 0x100);
}
通过逻辑分析仪测量板卡的输出波形,得到输出低8位结果见图5-6。在源程序中写入的数据为pData数组,它的取值是从0开始依次加1,因此从最低位开始往上一位走,依次为2分频。而从输出波形可以看出,输出完全符合写入的数据,数据输出的速率为16 MHz。

图5-5 PXI卡软件面板

图5-6 低8位输出结果
5.4 本章小结
本章详细的介绍了PCI/PXI设备驱动程序特点,以及DDK开发驱动程序的主要技术内容。本课题用DDK成功的开发出了基于PCI9054的设备驱动,并成功安装到硬件上且板卡能正常工作。
本设计中最突出的优点是采用DDK设计驱动程序,而没有采用DS(Driver Studio)和Windriver ,因为DDK是基于汇编语言的编程方式的,其优点是可以开发核心态的真正意义上的驱动程序,开发出来的驱动程序效率是最高的。
[1] 马嘉. PXI模块仪器系统. 机系统测试与控制, 1999, 7(1): 28~30
[2] 周琴. GPIB总线及应用技术. 低压电器, 2008, 1(9): 16~17
[3] 张世箕. 自动测试系统. 第一版. 成都: 科技大学出版社, 1990: 21~23
[4] 孙家琪. 自动测试系统. 第一版. 北京: 机械出版社, 1990: 36~40
[5] Subbarao V, Wunnava, Peter Hoo. Remote Instrumentation Access&Control (RIAC)Through Inter-Networking. IEEE Instrumentation and Measurement Technology c- onference 1999: 118~119
[6] 马怀俭. 自动测试系统. 第一版. 哈尔滨: 哈尔滨理工大学出版社, 1994: 41~45
[7] K. Chipperfield. Exploring VXIbus Systems and Instrumentation. IEEE,1995: 217~224
[8] 马怀俭. VXI总线讲座. 电测与仪表, 1990(4): 12
[9] 万鹏. 自动测试与VXI总线自动测试系统. 山东大学学报, 1997(3):85~86
[10] 杨乐平. 一种新的模块化仪器总线标准PXI. . 测控技术, 1998(5):62~63
[11] National Instruments. PXI Specification PCI eXtensions for Instrumentation An I- mplementation of CompactPCI, 1997:1~50
[12] Arlene Meadows, Grey Hill. VXI技术现状及其技术规范. 国外电子测量技术, 1998(6): 3~4
[13] 杨乐平, 曾敏. VXI仪器软件技术新-IVI. 第八届VXI技术研讨会集, 1999. 25~31
[14] 席成洲. 一种开放的工业计算机标准-CompactPCI. 测控技术, 1998(1): 7~11
[15] 马永杰, 杨志民. 100MHz高速数据采集卡研制中关键技术的探讨. 西北师范大学学报(版), 1999(1): 37~37
[16] 方慧, 王飞, 何配琨等. TMS320C6000系列DSPs的原理与应用, 第2版. 北京: 电子工业出版社, 2001. 53~62
[17] Exas Instruments Inc: TMS320C6416T FIXED-POINT DIGITAL SIGNAL PRO- CESSORS Data Sheet. Texas Instruments Inc:2004
[18] 苏涛, 蔡建隆. DSP接口电路设计与编程. 西安: 西安电子科技大学出版社, 2003. 21~56
[19] 黎向阳, 刘光平, 梁甸农. 宽带正交解调器幅相一致性测量. 国防科技大学学报, 2002(2): 60~63
[20] 向民, 张辉. 一种用于信号分析的数字正交解调电路设计. 电视技术, 2006(2): 65~69
[21] 立君, 马骏. 一种宽带正交解调器的试验研究. 电子, 2000(4): 30~32
[22] 崔勇, 王宏远. 基于SystemView的正交系统仿真与分析: 船舶电子工程, 2006(6): 90-92.
[23] James Kimery.PXI测量系统面对今天的测试挑战.Electronic Products China, 2000(5): 18
[24] 王鲁平, 李飚. 基于EPLD技术的PCI总线接口设计. 电子技术应用,2001(3): 5
[25] Finkelstein, Ehud, Weiss, Shlomo. PCI-based systems using CPLDand FPGA dev- ices. Proceedings of the Mediterranean Electrotechnical Conference-MELECON v2 1998 (3): 18~20
[26] Plx technology, PCI9054 Data Book, Version 2. 1, January,2000:15~60
[27] 振勇, 翁木云. FPGA设计及应用. 第一版. 西安: 西安电子科技大学出版社, 2002. 1~22, 111~140, 195~218
[28] DA先锋工作室, 吴继华, 王城. Altera FPGA/CPLD设计(基础篇)第一版. 北京: 人民邮电出版社, 2005. 1~116
[29] ltera. CycloneII Device Handbook. San Jose: Altera Corporation ,2006: 1~484
[30] 任爱锋, 初秀琴, 常存等. 基于FPGA的嵌入式系统设计. 第一版. 西安: 西安电子科技大学出版社,2004. 9~126
[31] Integrated Device Technology, Inc. IDT72V205/72V215/72V225/72V235/72V245 Data Sheet. Datasheet. FEBRUARY 2006:1~25
[32] 梅杰, 曹以龙, 许明东. 基于VerilogHDL语言的USB收发器设计. 电子技术, 2003, 12: 19~21
[33] 李玉柏, 彭启琮, 管庆. 基于VXI总线的虚拟仪器平台. 测控技术,1997, 16(3): 45~47
[34] VXI Plug & play System Alliance. The VISA Library. Texas: VXI Plug& play Sy- stem Alliance, 1996:121~256
[35] VXI Plug & play System Alliance. VISA Implementation Specificationfor Textual Languages. Texas:VXI Plug & play System Alliance, 1996:57~146
[36] Chris Cant . Windows WDM设备驱动程序开发指南(美)北京: 机械工业出版社, 2000. 1~100
[37] Walter Oney, Programming the Windows Model Driver. Microsoft Press, 1999: 35~71
[38] Microsoft,Windows 2000 DDK Documents, 1999: 20~54
[39] Walter O. Programming the microsoft windows driver model[M] . USA ,1999: 21~50
[40] VXI Plug & play System Alliance. Soft Front Panel Specification. Texas: VXI Plug & play System Alliance, 1996: 12~39
附录1 攻读学位期间发表的论文
[1] 陈国斌, 汤清华, 汤丁诚. 基于PXI总线高速数字I/O卡设计. 电子技术应用, 2008, 33(1): 59~61
附录2 FPGA控制程序
`define COUNTERSIZE 129
`define COUNTERSIZE_INT 10
module Statemachine (
…)//由于篇幅限制,端口定义省略
always @ (GCLK0)
if(LHOLD)
LHOLDA<=LHOLD;
else
LHOLDA<=1'b0;
always@(posedge GCLK0 or negedge LRSTo_)
begin
if(LRSTo_==1'b0)
begin
LRS_I_<=1'b0;
LRS_O_ <=1'b0;
end
else
begin
LRS_I_<=1'b1;
LRS_O_ <=1'b1;
end
end
//output logic
always @ (posedge GCLK0)
begin
casex (State)
1'b0:
begin
if (!LADS_)
begin
LREADY_ <= 1'b0;
if (LWR_==1'b0)
begin
LREN_I_ <=1'b0;
WEN_O_ <=1'b1;
begin
LREADY_ <=1'b0;
if (LWR_== 0)
begin
LREN_I_ <=1'b0;
WEN_O_ <=1'b1;
end
else
begin
LREN_I_ <=1'b1;
WEN_O_ <=1'b0;
end
State <= 1'b1;
end
else //Cycle Last
begin
LREADY_ <=1'b1;
LREN_I_ <=1'b1;
WEN_O_ <=1'b1;
State <=1'b0;
end
end
default:
State <=1'b0;
endcase
end
assign LOE_O_ =(LRSTo_)?1'b0:1'b1;
assign LOE_I_ =(LRSTo_)?1'b0:1'b1;
//assign LLINT_=1'b1;
always@(posedge GCLK0 or negedge LRSTo_)//or negedge LGCLK
begin
if(LRSTo_==1'b0)
begin
counter<=6'b0;
WCLK_reg <=1'b0;
end
else
if(counter==`COUNTERSIZE)
begin
WCLK_reg<=!WCLK_reg;
counter<=6'b0;
end
else
counter<=counter+6'b000001;
end
assign WCLK_O=(`COUNTERSIZE==129)?GCLK0:WCLK_reg;
always@(posedge GCLK0)begin
LHF_I_buf1<=LHF_I_;
LHF_I_buf2<=LHF_I_buf1;
end
always@(posedge GCLK0 or negedge LRSTo_)
begin
if(LRSTo_==1'b0)
begin
counter_int<=8'b0;
LLINT_<=1'b1;
sub_state<=3'b000;
end
else
begin
case(sub_state)
3'b000:
begin
LLINT_<=1'b1;
if(!LHF_I_buf1&&LHF_I_buf2)
sub_state<=3'b001;
else
sub_state<=3'b000;
end
3'b001:
begin
counter_int<=counter_int+8'b00000001;
LLINT_<=1'b0;
if(counter_int==`COUNTERSIZE_INT)
sub_state<=3'b000;
else
sub_state<=3'b001;
end
default sub_state<=3'b000;
endcase
end
end
if(!LRSTo_)
count<=0;
else if(count_flag)
count<=count+1;
else count<=0;
always@(posedge GCLK0 or negedge LRSTo_)
if(!LRSTo_)
LRE_ENA_<=1'b1;
else if(count>15)
LRE_ENA_<=1'b0;
else
LRE_ENA_<=1'b1;
endmodule
附录3 PXI部分驱动程序代码
PXI驱动部分代码
/************************************************************************
* Function : DispatchRead
* Description: Handle IRP_MJ_READ, which is not implemented by this driver ReadFile
************************************************************************/
NTSTATUS DispatchRead(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchRead
KdPrint((DBG_NAME "Read Device Start./n"));
ULONG ReturnedValue;
NTSTATUS status = STATUS_SUCCESS;
//将从硬件采集到的数据送给应用程序, 如果不能很快处理,将IRP进行串行化,交给StartIo处理。
IoMarkIrpPending(pIrp);
IoStartPacket(fdo, pIrp, NULL, CancelIrp);
KdPrint((DBG_NAME "Read Device End./n"));
return STATUS_PENDING;
} //DispatchRead
/************************************************************************
* Function : DispatchWrite
* Description: Handle the IRP_MJ_WRITE, which is not implemented by this driver
WriteFile
************************************************************************/
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT fdo,
IN PIRP pIrp)
{ //DispatchWrite
KdPrint((DBG_NAME "Write File Start./n"));
//将应用程序的数据送到硬件, 将IRP串行化,交给StartIo处理
IoMarkIrpPending(pIrp);
IoStartPacket(fdo, pIrp, NULL, CancelIrp);
KdPrint((DBG_NAME "Write File End./n"));
return STATUS_PENDING;
}
/************************************************************************
* Function : DispatchIoControl
* Description: Processes the IOCTL IRPs sent to this device.
************************************************************************/
{ case IOCTL_PDC4000_REGISTER_EVENT://注册Event变量
status= bReferenceObjectByHandle(*(PHANDLE)pIrp->AssociatedIrp.SystemBuffer,
EVENT_MODIFY_STATE, *ExEventObjectType,
pIrp->RequestorMode, (PVOID*)&pdx->pWaitEvent, NULL);
if (!NT_SUCCESS(status))
{
pdx->bSetWaitEvent = FALSE;
KdPrint((DBG_NAME "WARNNING - ObReferenceObjectByHandle failed/n"));
}
else
{
pdx->bSetWaitEvent = TRUE;
KdPrint((DBG_NAME "OK - ObReferenceObjectByHandle succeed/n"));
}
lReturnedValue = 0;
break;
case IOCTL_PDC4000_UNREGISTER_EVENT: //反注册Event变量
pdx->pWaitEvent = NULL;
pdx->bSetWaitEvent = FALSE;
lReturnedValue = 0;
break;
case IOCTL_PDC4000_READ_DATA:
ULONG Num, Buffer;
lPdcAddress = (ULONG)pdx->PdcMemBase0;
RtlCopyMemory(&Num, pIrp->AssociatedIrp.SystemBuffer, sizeof(ULONG));
KdPrint((DBG_NAME "Input Value is %x.", Num));
Buffer = READ_REGISTER_UCHAR((unsigned char *)(lPdcAddress + Num));
KdPrint((DBG_NAME "Read Data Value is %x./n", Buffer));
RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, &Buffer, sizeof(ULONG));
lReturnedValue = sizeof(ULONG);
break;
case IOCTL_PDC4000_WRITE_DATA:
ULONG dwWriteBuffer[2];
lPdcAddress = (ULONG)pdx->PdcMemBase0;
RtlCopyMemory(dwWriteBuffer, pIrp->AssociatedIrp.SystemBuffer, 2 * sizeofpIrpStack->Parameters.DeviceIoControl.InputBufferLength;//0x10;
RtlCopyMemory(pdx->DmaInfo[0].vaCommonBuffer, pIrp->AssociatedIrp.SystemBuffer, lDMAPciToLocalTransferSize);
KdPrint((DBG_NAME "The vaCommonBuffer is %X./n", *(unsigned char *)(pdx->DmaInfo[0].vaCommonBuffer)));
lPdcAddress = (ULONG)pdx->LocalRegisterMemBase;
dcd.BTERMInputEnable = 1;
dcd.DACChainLoad = 0;
dcd.DemandMode = 0;
dcd.DmaChannelPriority = Rotational;
dcd.DmaEOTPinEnable = 0;
dcd.DoneInterrputEnable = 1;
dcd.EnableTransferCountClear = 0; //For sgl DMA
dcd.FastSlowTerminateModeSelect = 0;
dcd.InternalWaitStates = 0;
dcd.InterrputSelect = 1;
dcd.LocalAddressingMode = 0;
dcd.LocalBurstEnable = 1;
dcd.LocalBusWidth = 0;
dcd.MemoryWriteAndInvalidateMode = 0;
dcd.ReadyInputEnable = 1;
dcd.ScatterGatherMODE = 0;
//DMA threshold
dte.DirectionOfTransfer = 0;
dte.EndOfChain = 0;
dte.InterruptAfterTerminalCount = 0;
dte.NextDescriptorAddress = 0;
KdPrint((DBG_NAME "The lDMAPciToLocalTransferSize is 0x%X./n", lDMAPciToLocalTransferSize));
rc = DmaBlockTransfer(pdx, 0, &dte);
if (rc != RC_SUCCESS)
{ KdPrint((DBG_NAME "Can't DmaBlockTransfer./n")); }
KdPrint((DBG_NAME "IOCTL_PDC4000_BLOCK_DMA_PCI_TO_LOCAL End./n"));
break;
case IOCTL_PDC4000_BLOCK_DMA_LOCAL_TO_PCI:
IoMarkIrpPending(pIrp);
IoStartPacket(fdo, pIrp, NULL, CancelIrp);











