📄 4.虚拟仪器驱动程序.txt
字号:
0xBFFC0D28 */
#define prefix_INSTR_ERROR_PARAMETER18 (_VI_ERROR+0x3FFC0D29L)/*
0xBFFC0D29 */
#define prefix_TIMEOUT_MAX 2147483647
#define prefix_TIMEOUT_MIN 0
/* All function with the prefix of _VI_FUNC */
/* ALL pointer type parameters with the prefix of _VI_FAR */
/* required plug and play functions from VPP-3.1*/
/* Common Functions in all virtual instrument drivers */
ViStatus _VI_FUNC prefix_init (ViRsrc InstrDesc, ViBoolean id_query,
ViBoolean do_reset, ViPSession vi);
ViStatus _VI_FUNC prefix_close (ViSession vi);
ViStatus _VI_FUNC prefix_reset (ViSession vi);
ViStatus _VI_FUNC prefix_selfTest (ViSession vi, ViPInt16 test_result,
ViChar _VI_FAR test_message[]);
ViStatus _VI_FUNC prefix_errorQuery (ViSession vi, ViPInt32
error_number,
ViChar _VI_FAR error_message[]);
ViStatus _VI_FUNC prefix_errorMessage (ViSession vi, ViStatus
error_number,
ViChar _VI_FAR message[]);
ViStatus _VI_FUNC prefix_revisionQuery (ViSession vi,
ViChar _VI_FAR driver_rev[], ViChar _VI_FAR instr_rev[]);
/* prefix other standard functions */
ViStatus _VI_FUNC prefix_dcl(ViSession vi);
ViStatus _VI_FUNC prefix_timeout(ViSession vi, ViInt32 timeOut);
ViStatus _VI_FUNC prefix_timeout_query(ViSession vi, ViPInt32 timeOut);
/* Used for "C" externs in C++ */
#if defined(__cplusplus) || defined(__cplusplus__)
} /* end of "C" externs for C++ */
#endif
#endif /* prefix_INCLUDE */
2、 参考相关例程法:在仪器驱动程序设计过程中,也可以找出与本模块类似或同
类的驱动程序源代码作为参考。需要声明的是,参考不是抄袭,这种允许源代码之
间的参考正是VPP规范所提倡的开放性与兼容性的要求。仍以可编程数字输入/输出
模块dio开发为例,可以找到对应的HP公司的相关产品hpe1458或Tek公司的相关产
品VX4802,阅读hpe1458与VX4802仪器驱动程序源代码,在其上面进行修改(修改
的依据是模块功能的调整),就会大大提高本仪器驱动程序的正确性与效率。在这
种参考相关例程法中,理解自己要实现的功能任务与理解参考源代码是同样重要的
,当可参考的例程(指产品化的例程)与本仪器驱动程序越接近时,这种方法越有
效,而当需要设计一个特定的仪器模块而无法找到合适的参考例程时,只能找到越
相近的例程越好。因此,参考例程的质量与风格会直接影响所设计的驱动程序的质
量与风格的。
3、 以上两个方法事实上采用的是手工编写的方法,在仪器驱动程序中是否可以引
入自动化生成工具,是设计人员进一步追求的目标。近年来,以NI公司为代表的
IVI (Interchangeable Virtual Instruments)协会推出的IVI规范,提出了可换式
仪器驱动程序的生成方法,为建立以面向对象技术为基础的仪器驱动程序的设计提
出了新思路。然而,根据实际研究,发现它能实现的可互换式仪器驱动程序只是有
限的几个,生成方法也比较复杂,工作量不小,其推广性并没有如它宣传的那么大
,并没有被业界所广泛接受。在国内,电子科技大学CAT室也推出了表格化设计的
虚拟仪器库,也推动了仪器驱动程序设计自动化。在本节中,同样基于面向对象程
序设计的技术,提出了一个虚拟仪器驱动程序生成工具的实现方法。
本设计模型采用了自顶向下层层细化的设计思路,在所有仪器的顶层,是一个基类
,定义为CInstrument,在基类中定义了基本成员变量与成员函数,所有成员函数
以纯虚函数的形式提供函数原型,不给出函数实体。在这些成员函数中,定义的均
是最基本的通用函数。
从基类CInstrument开始派生出基本仪器类型类,共分为VXI消息基器件类
CMessageVXI、VXI寄存器基器件类CRegisterVXI、GPIB器件类CGPIB及串行接口仪
器类CRS232,各仪器类均继承了基类的成员变量与成员函数,并以虚函数形式重写
成员函数并添加各自的成员函数,以供下一层类调用。在基本仪器类型类往下再进
行类派生,生成了具体仪器类,如VXI消息基器件派生出万用表器件类CVXIDMM与数
字信号发生器类CVXISIGP等,各自在继承了上层类的基础上加入了各自新的成员变
量与成员函数,成员函数仍以虚函数的形式给出。这样当仪器驱动设计人员进行程
序设计时,先确定自己仪器的类型,找到自己的上层类,如可编程数字输入/输出
模块dio找到了VXI寄存器基器件类下派生的输入/输出模块类作为派生类,就可以
得到了输入/输出模块的通用功能函数,这比第一种核心模块法提供的核心模块程
序要进步得多。利用虚拟仪器驱动程序生成工具,可以生成虚拟仪器驱动程序的大
部分代码,其它新的功能函数的添加与修改,也可以在这个生成工具中进行。最后
,利用转换工具,将特定的类定义转换成虚拟仪器驱动程序形式进行封装,可以提
高开发效率。仪器驱动程序的类派生结构图如图4.10所示。
图4.10 仪器驱动程序类派生基本结构图
根据生成工具,可以完成一部分编写工作,但是完全由计算机自动产生虚拟仪器驱
动程序的所有源代码,无乎是不可能,也是没有太大的实际效益的。真正的编写工
作是尽可能地利用现有的基础与工具,但必须意识到整个开发与调试工作还是由设
计人员一步步来完成的。在实际编写过程中,寄存器基器件的编写比消息基器件的
编写难度更大,更深入到仪器内部,因此依靠自动生成工具生成困难也就更大。如
一个简单的可编程数字输入/输出模块通讯协议中的握手模式与延时时间的设置,
使用消息基器件操作方式,因为只涉及两个SCPI命令,SCPI命令格式如下:(
[SOURce:] Digital: DATAn [:type]: HANDshake [:Mode] <mode>)与(
[SOURce:] Digital: DATAn [:type]: HANDshake: Delay <time>),所有输入/输
出模块的操作格式是一致的,可以用工具继承生成,但对于寄存器基编程方式而言
就会涉及到模块内部寄存器的读写操作,编程会复杂得多,因此用生成工具来完全
自动生成是不可能的。例程如下所示。
/*——————————————————————————————————
* 函数名:zde1458_handshake
* 函数描述:设置所有端口的握手模式与延时时间
* 参数描述:
* 输入参数:
* ViSession vi :仪器句柄
* ViInt16 mode :握手模式
* 宏 名 值 说明
* zde1458_HANDSHAKE_NONE 0 None
* zde1458_HANDSHAKE_LEAD 1 Leading
* zde1458_HANDSHAKE_TRA 2 Trailing
* zde1458_HANDSHAKE_PART 3 Partial
* zde1458_HANDSHAKE_PULS 4 Pulse
* zde1458_HANDSHAKE_STR 5 Strobe
* ViReal64 delay :握手延时时间
* MAX = zde1458_MAX_HAND_DEL 15.0000E-3(15ms)
* MIN = zde1458_MIN_HAND_DEL 2.0E-6(2us)
* 延时值与端口延时寄存器值关系:
* 2us--15us ===>0x20--0xf0
* 20us--150us ===>0x21--0xf1
* 200us--1.5ms ===>0x22--0xf2
* 2ms--20ms ===>0x23--0xf3
* 输出参数:
* 无
* 返回值:
* VI_SUCCESS :握手模式与延时设置完成
——————————————————————————————————*/
ViStatus _VI_FUNC zde1458_handshake(ViSession vi,
ViInt16 mode, ViReal64 delay)
{
ViStatus errStatus;
ViUInt8 handshake_mode_reg;
ViUInt8 handshake_delay_reg;
ViAddr address;
errStatus = VI_SUCCESS;
/* 检查输入握手模式是否合法 */
if ((mode < 0) || (mode > 5))
{
return VI_ERROR_PARAMETER2;
}
/* 检查输入延时值是否超界 */
if ((delay < zde1458_MIN_HAND_DEL) ||
(delay > zde1458_MAX_HAND_DEL))
{
return VI_ERROR_PARAMETER3;
}
/* 决定握手模式与握手延时寄存器 */
zde1458_handshake_reg(mode, delay, &handshake_mode_reg,
&handshake_delay_reg);
/* 映射内存空间 */
errStatus = viMapAddress(vi, VI_A16_SPACE, 0x00, 0x40,
VI_FALSE, VI_NULL, &address);
if (errStatus < VI_SUCCESS)
{
return errStatus;
}
/* 端口0-3 */
viPoke16(vi,(ViAddr)((ViUInt8 *)address+card_stat),bank_0);
/* 设置握手模式 */
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_0),
handshake_mode_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_1),
handshake_mode_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_2),
handshake_mode_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_3),
handshake_mode_reg);
/* 设置握手延时值 */
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_0),
handshake_delay_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_1),
handshake_delay_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_2),
handshake_delay_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_3),
handshake_delay_reg);
/* 端口4-7 */
viPoke16(vi,(ViAddr)((ViUInt8 *)address+card_stat),bank_1);
/* 设置握手模式 */
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_0),
handshake_mode_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_1),
handshake_mode_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_2),
handshake_mode_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_hand_3),
handshake_mode_reg);
/* 设置握手延时值 */
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_0),
handshake_delay_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_1),
handshake_delay_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_2),
handshake_delay_reg);
viPoke8(vi,(ViAddr)((ViUInt8*)address+port_del_3),
handshake_delay_reg);
/* 端口8-11 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -