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);