微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > MCU和DSP > VxWorks下AD/DA驱动系统设计及测试

VxWorks下AD/DA驱动系统设计及测试

时间:01-11 来源: 点击:

相对于其他嵌入式操作系统,VxWorks以其高可靠性、微内核、可裁减性以及高效的硬实时任务调度、中断管理等优点,被广泛地应用在通信、军事、航空、航天等高精尖技术和实时性要求极高的领域[1]。工程中实际应用的嵌入式系统通常包括以下几个部分:串口、并口、CAN总线和AD/DA等。对于前三种嵌入式硬件,VxWorks内核本身已提供了完备的驱动支持并给出了相应驱动的参考例程,但目前还未包括对A/D及D/A设备的支持;此外,由于相关技术资料的保密性,相应驱动设计的参考文献也较少。因此,本文结合实际系统需要(利用12位D/A输出可调模拟量控制电机转速,利用12位A/D对压电陀螺所敏感的电机转速进行数据采集),对AD/DA设备的驱动进行了相关研究,研究结果具有实际工程应用价值。

本文在简要分析了VxWorks I/O系统及设备驱动基础之上,将A/D与D/A两者整合为一个完整的字符设备挂接到VxWorks的I/O系统中,成功实现了该设备的硬件驱动并附上对应的核心驱动代码,最后在驱动程序测试过程中简要说明了应用层软件的设计方法,为工程应用提供了完善的解决办法。

1 VxWorks I/O系统与设备驱动

了解和掌握VxWorks的I/O系统及设备的驱动结构,是成功设计AD/DA设备驱动的前提和基础。具体来说:VxWorks是一个层次化分明的操作系统,每层各负其责,层与层之间又紧密相连。通常所说的驱动程序属于底层的范畴,而用户的应用程序则属于上层,位于这两层之间的是中间层,无需用户开发,由VxWorks进行维护和管理。这样,操作系统把各层有机地连接在一起,使代码紧凑而高效。VxWorks的I/O系统正是这样的中间层,以本文所要研究的AD/DA驱动系统设计为例,图1详细介绍了三者的关系。

图1中的最底层就是所要编写的设备驱动程序,包括对具体硬件的初始化和各种操作,以及与上层I/O系统的接口;中间层为I/O系统层,VxWorks的I/O系统不但向上提供了7个基本的I/O接口,以供应用程序调用,而且还向下提供与各种设备驱动程序的接口;最顶层为应用层,用户根据实际应用需要编写应用程序,并通过应用程序向下调用I/O系统。与UNIX类似,VxWorks所有的I/O设备都被当作文件来存取。关于VxWorks I/O系统驱动机制的更多内容请参考文献[2][3]。

  针对系统需要,选择7个基本I/O接口函数中的open()、read()、write()以及ioctl()进行驱动系统设计,各层函数与相应实现的功能对应关系如表1所示。

此外,D/A输出通道在应用程序中选择,下面给出AD/DA驱动系统的具体设计过程。

2 AD/DA驱动系统设计

2.1 驱动系统开发环境

与其他嵌入式系统开发类似,VxWorks也采用主机-目标机模式[4],如图2所示。

硬件平台中主机使用CPU为迅驰的PC机,运行VxWorks开发环境Tornado2.2;目标机依照系统应用要求选用基于PC104 总线的嵌入式CPU卡MSMP586SEV,该CPU是VxWorks所支持的Intel x86系列CPU。VxWorks自带的板级支持包(BSP)支持该CPU,使得在驱动开发过程中无须过多考虑CPU部分的代码设置。外扩AD/DA采用的同样是PC104总线的数据转换卡ADT-650。开发调试过程中,主机通过网络方式下载VxWorks映像至目标机中,目标机设定为CF卡启动。

2.2 PC104-AD/DA卡硬件结构[5]

PC104-AD/DA卡主要由A/D转换控制器(AD1674)和D/A转换控制器(ADC7724)两个核心器件组成,可提供的硬件资源为12位分辨率的8通道A/D转换和同分辨率的4通道D/A转换;CPU卡通过I/O映射方式对其进行访问,可通过硬件开关选通该卡的I/O映射基地址,为了避免与其他器件地址冲突,在此选择其基地址为:BA=0x240(可根据实际情况选择),其余各寄存器采用偏移地址访问的方式。为便于后续说明,简要将卡上其他寄存器地址及功能列于表2。

在传统非嵌入式实时操作系统(比如DOS)下应用该卡,实际上是在应用程序中对板卡进行初始化和设置相应功能寄存器以完成硬件功能。但由前面对VxWorks的I/O系统和设备驱动结构分析可知,该部分工作在VxWorks操作系统下由底层硬件驱动完成,应用程序中通过调用相应I/O接口函数来实现硬件功能,由此实现分层结构以达到隔离硬件的目的。因此,AD/DA驱动的开发就是依照I/O系统传递过来的应用层各调用接口函数完成对相应寄存器的不同设置。

2.3 AD/DA驱动程序实现

AD/DA驱动的实现方式主要是完成以下6个函数的编写:

设备驱动程序安装函数adcDrv();设备创建函数adcDevCreate();设备打开函数adcOpen();设备读函数(A/D转换) adcRead();设备写函数(D/A转换)adcWrite();I/O控制函数adIoctl()。

其中前三个函数的设计与具体硬件关联较少,与VxWorks下其他字符型设备驱动开发基本类似,不做过多介绍,仅需按照标准代码形式编写即可,具体详细代码可见参考文献[6]。下面详细介绍A/D转换驱动、D/A转换驱动以及设备控制驱动等部分的程序设计,给出核心代码。

2.3.1 A/D转换驱动

A/D转换驱动实际是完成adcRead()函数的编写,在该函数编写之前,首先应明确A/D转换驱动实现过程:当应用程序调用read()函数时,VxWorks的I/O系统将调用底层驱动adcRead()函数,该函数随即依照程序设定对表2所列卡上各相关寄存器进行设置来实现A/D转换的硬件功能,从而实现底层驱动。

A/D转换驱动具体实现的核心代码如下(伪指令为代码说明,以下同):

int adcRead(int adcDevId,char *pBuf,int nBytes)
{…/*触发AD转换*/
sysOutByte(BA+0, 0x00);
while(1)
{/*判断AD转换状态*/
status=sysInByte(BA+5);
if((status&0x01)==0)
{
/*存储A/D转换结果*/
pBuf[1]=sysInByte(BA+0);
pBuf[2]=sysInByte(BA+1);

}
}
}
首先选择一个输入通道(通过ioctl选择)并触发A/D转换,随后查询A/D转换状态信息直到A/D转换过程结束,最终将转换结果保存在pBuf[]数组中传送到应用层,应用程序使用得到的数字量信息,至此,A/D驱动完毕。其中sysOutByte()和sysInByte()为VxWorks下对寄存器操作的标准函数。

2.3.2 D/A转换驱动

与上述驱动实现过程类似,D/A转换驱动是完成对adcWrite()函数的编写,转换过程是A/D转换的逆过程,由于其不涉及查询判断,代码相对简化。D/A转换驱动具体实现的核心代码如下:

int adcWrite(int adcDevId, char *pBuf,int nBytes)
{…/*将数据写入缓冲区*/
sysOutByte(BA+2, pBuf[2]);
sysOutByte(BA+1, pBuf[1]);

}

首先将应用程序中设定的待转换数字量的低4位和高8位分别存放在pBuf[1]、pBuf[2]中,随后依照先高后低的顺序写入D/A转换缓冲区内,当低位数据写入完成后,硬件将自动开始更新D/A输出的模拟量,至此,D/A驱动完毕。需要说明的是:D/A通道选择是在应用程序中的编码过程中实现的。

2.3.3 设备控制驱动

设备控制驱动用于完成A/D通道选择,实现过程是对BA+3寄存器进行设置,当该寄存器高低位不同时,通道进行自动扫描,每当AD转换完成时切换到下一个通道。以控制A/D对通道0至通道3循环扫描为例,具体代码如下:

int adcIoctl(int adcDevId, int cmd, int arg)
{…/*CH30控制字控制通道0-3转换*/
case CH30:
sysOutByte(BA+3, 0x30);

}

通过定义控制参数CH30,实现通道扫描的范围为0、1、2、3、0、1、2、3……,利用该方法的好处是可以省去置通道的软件操作时间,这个功能在高速多通道切换时起很关键作用,同样可定义其他通道的控制参数,如CH20、CH00等等。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top