本文以一实例介绍了如何利用VC
运行时间库里提供的端口输入函数_inp、端口输出函数_outp
以面向对象的方式实现AD/DA 转换控制的编程方法。
我们以所使用的PS-2104A 12 位多功能AD/DA
卡为例,先对该卡的工作方式、端口地址等作个介绍,再对VC5.0
用于访问端口的两个函数作个介绍,然后详细说明控制程序的设计和使用方法。
1 .AD/DA 卡简介
我们使用的PS-2104A AD/DA 转换卡具有32 路12 位A/D 转换通道和2 路12
位D/A 转换通道。该卡口地址可以在0 ~03FFH 间设置。
A/D 操作为:
N +0 地址写操作选择A/D 通道;
N +1 地址读操作查询A/D 转换状态,值为"0"
表示转换结束;
N +1 地址写操作启动A/D 转换,写"0" 开始A/D 转换;
N +2 地址读操作获取转换结果高8 位数据;
N +3 地址读操作获取转换结果低4 位数据。
D/A 操作为:
N +1 地址写操作启动D/A 转换;
写"1" 启动D/A 通道1;
写"2" 启动D/A 通道2;
N +2 地址写操作送D/A 高8 位数据;
N +3 地址写操作送D/A 低4 位数据。
尽管本文的程序例子是针对这种卡编写的,但大多A/D、D/A
卡的接口方式是类似的,只是在操作口地址上稍有差别,因此只要针对你所使用的卡的具体情况对本文的例子稍作修改便可以同样采用了。
2 ._inp、_outp 函数介绍
VC5.0 提供了对控制台(console)和端口(port)进行读写访问的例程,_inp
和_outp
是其中的两个。它们的原型在头文件中定义,要在程序中使用它们必须包含该头文件。
_inp 原型为:
int _inp(unsigned short port);
port 参数为指定的输入端口号。调用后,它从port
参数指定的端口读入并返回一个字节,输入值可以是在0-255
范围内的任意无符号整数值。
_outp 原型为:
int _outp(unsigned short port, int databyte );
port 参数为指定的输出端口号,databyte
参数为输出的值。调用后,它将databyte 参数指定的值输出到port
参数指定的端口并返回该值。databyte 可以是0-255
范围内的任何整数值。
这两个函数都没有错误值返回。
我们将利用这两个函数来对AD/DA 卡进行读入和输出操作。
3 .A/D 控制类的设计
在VC5 中用MFC AppWizard[exe] 方式建立新工程,把它命名为AdDaControllApp,在第一步中选择Dialog
based,采用中文[ 中国] 字库,按下Finish 按钮,选择OK,建立起应用程序的框架。
建立A/D 类,选择Insert 菜单的New Class 选项,在New Class
对话框中选择Class type 为Generic Class,并将类命名为CAdControll,按OK。在FileView
窗口中双击Source Files, 双击AdControll.cpp, 在该文件的第一行加入#include
语句。选择在ClassView 窗口中选择CAdControll
类,为它加入下列成员变量:
protected:
unsigned short m_unBaseAddress;
// 存放A/D 转换卡基地址
BYTE m_byChannelAddress;
// 存放A/D 通道基本偏移地址
BYTE m_byHighEightBits; // 存放高8 位数据
BYTE m_byLowFourBits; // 存放低4 位数据
BYTE m_byADState; // 存放A/D 转换器状态
BYTE m_byStart; // 存放开始A/D 转换的信号
float m_fResult; // 存放最终结果
在缺省构造函数CAdControll:: CAdControll()
中添入它们的缺省初始化语句:
m_unBaseAddress=0x0100; // 我们的AD/DA 卡基地址
m_byChannelAddress=0x20; // 通道基本偏移地址
m_byStart=0x00; // 开始A/D 转换的信号
加入带参数的构造函数:
CAdControll:: CadControll
(unsigned short unBaseAddress, BYTE
byChannelAddress)
{
m_unBaseAddress= unBaseAddress;
m_byChannelAddress= byChannelAddress;
m_byStart=0x00; // 开始A/D 转换的信号
}
添加设置A/D 卡基地址的方法:
void CAdControll::SetBaseAddress
(unsigned short unBaseAddress)
{
m_unBaseAddress= unBaseAddress;
}
添加设置转换通道基本偏移地址的方法:
void CAdControll::SetChannelBaseAddress
(BYTE byChannelAddress)
{
m_byChannelAddress= byChannelAddress;
}
添加读A/D 转换结果的方法:
float CAdControll::ReadAD(BYTE byChannel=0)
// 缺省为第0 通道
{
// 向A/D 转换器送通道号
_outp(m_unBaseAddress, m_byChannelAddress +byChannel);
// 发出启动转换信号
_outp(m_unBaseAddress +1,m_byStart);
// 循环查询直到转换结束
do{
m_byADState=_inp(m_unBaseAddress +1);
// 读转换器状态
m_byADState=m_byADState &0x01;
}while(m_byADState);
// 正在转换则继续查询,
转换结束则退出循环
m_byHighEightBits= -_inp(m_unBaseAddress +2);
// 读取转换结果的高8 位
m_byLowFourBits=_inp(m_unBaseAddress +3);
// 读取转换结果的低4 位
// 计算A/D 转换结果
m_fResult= (m_byHighEightBits *16 +(float)
m_byLowFourBits/16)/4096;
return m_fResult; // 返回A/D 转换结果
}
4 .D/A 控制类的设计
选择Insert 菜单的New Class 选项,在New Class 对话框中选择Class type
为GenericClass,并将类命名为CDaControll,按OK。在FileView 窗口中双击Source
Files, 双击DaControll.cpp, 在该文件的#include "DaControll.h"
语句后面加入#include 语句。在ClassView 窗口中选择CDaControll
类,为它加入下列成员变量:
protected:
unsigned short m_unBaseAddress;
// 存放DA 转换卡基地址
BYTE m_byHighEightBits; // 暂存高8 位数据
BYTE m_byLowFourBits; // 暂存低5 位数据
在缺省构造函数CDaControll::CDaControll() 中添加下面的初始化语句:
m_byHighEightBits=0x00;
m_byLowFourBits=0x00;
m_unBaseAddress=0x0100;
添加带参数的构造函数:
CDaControll::CdaControll
(unsigned short unBaseAddress)
{
m_unBaseAddress= unBaseAddress;
}
添加设置基地址的方法:
CdaControll::SetBaseAddress
(unsigned short unBaseAddress)
{
m_unBaseAddress= unBaseAddress;
}
添加进行D/A 输出的方法:
void CDaControll::DaOut(unsigned int unOutData,
BYTE byStartDAChannel=0x01)
// 缺省通道为第一个A/D 转换通道
{
m_byHighEightBits=unOutData>>4;
// 获取输出数据的高8 位值
m_byLowFourBits= (BYTE)(unOutData &0x000F);
// 获取输出数据的低4 位值
_outp(m_unBaseAddress +2, m_byHighEightBits);
// 送D/A 的高8 位数据
_outp(m_unBaseAddress +3, m_byLowFourBits);
// 送D/A 的低4 位数据
_outp(m_unBaseAddress +1, byStartDAChannel);
// 启动D/A 转换
}
5 .A/D、D/A 控制类的使用
在AdDaControllAppDlg.h 文件中包含AdControll.h 和DaControll.h
文件,便可在CadDaControllAppDlg 类中定义CAdControll、CDaControll
类的对象,通过对A/D、D/A 控制类的访问可以方便地实现A/D、D/A
转换控制。
下面是A/D 控制类使用方法的演示例子:
在ResourceView 窗口中双击IDD_ADDACONTROLLAPP_DIALOG
项编辑对话框,添加一个Static Text 控件并将字符串内容改为"A/D
转换结果",添加一个Edit Box 控件并为该编辑框定义一个名为m_AdResult
的float 型变量。
在CadDaControllAppDlg 类中添加名为m_Ad 的CAdControll
类的成员变量。在CAdDaControllAppDlg::OnInitDialog() 中添加语句:
SetTimer(0,2 00,NULL);
利用ClassWizard 添加响应WM_TIMER 消息的OnTimer 函数,在OnTimer
函数中加入如下内容:
m_AdResult=m_Ad.ReadAD();
UpdateData(FALSE);
单击运行图标,工程被编译并运行,其结果是在编辑框中显示A/D
转换的结果( 如果安装了A/D 卡的话),并且转换结果会每隔0.2
秒刷新一次。
由于CAdControll 和CDaControll
类是独立定义的类,你也可以将定义它们的文件包含到其他应用工程中,通过对象引用方便地实现AD/DA
转换控制。