本文以一實例介紹了如何利用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
轉換控制。