第 5 章 チュートリアル(DLL編) 61
5.4 SRQイベント
・同様にしてOnDestroy関数を開き、(List 2-14)の網掛けの部分を記述してください。
(List 2-14:CGpibEventDllDlgクラスのOnCreate関数の追加コード)
// TODO: この位置にメッセージ ハンドラ用のコードを追加してください INT nRet; // 関数の実行結果
CString szErrMsg; // エラーメッセージ
// コールバックイベントの解除を行います nRet = PciGpibExKillSrqEvent(BoardNo);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("イベントの解除に失敗しました(%d)", nRet);
MessageBox(szErrMsg, "コールバック解除エラー", MB̲ICONERROR);
}
// I/Oモジュールの終了処理をします nRet = PciGpibExFinishBoard(BoardNo);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("I/Oモジュールアクセス番号%dのI/Oモジュールの終了処理に失敗しました(%d)",BoardNo, nRet);
MessageBox(szErrMsg, "クローズエラー", MB̲ICONERROR);
}
・GpibEventDllDlg.cppを開き、先頭部分に(List 2-15)の網掛けの部分を記述してください。
(List 2-15:GpibEventDllDlg.cppの追加コード)
// GpibEventDllDlg.cpp : インプリメンテーション ファイル //
#include "stdafx.h"
#include "GpibEventDll.h"
#include "GpibEventDllDlg.h"
#include "gpc4304.h"
#ifdef ̲DEBUG
#define new DEBUG̲NEW
#undef THIS̲FILE
static char THIS̲FILE[] = ̲̲FILE̲̲;
#endif
#define BoardNo 0 // I/Oモジュールアクセス番号
INT gnDevAdrsTbl[2] = {22,‑1}; // 入力機器アドレステーブル
void CALLBACK lpOnSrqProc(int, DWORD );// SRQ信号によるコールバック関数
3. SRQイベントの開始を行うためのボタンの設定を行います。
・ResourceViewを表示し、「Dialog」フォルダを展開して「IDD_GP-IBEVENTDLL_DIALOG」を ダブルクリックします。
表示されたダイアログボックスから必要のないボタン,スタティックテキストを削除します。
・「OK」ボタン,「キャンセル」ボタン,「TODO:ダイアログのコントロールをここに配置」とい うスタティックテキストをそれぞれ選択して、Deleteキーを押してください。
・コントロールから「ボタン」を選択し、ダイアログに貼り付けます。
・配置した「ボタン」のプロパティを表示させ、以下のように設定します。
ID IDC_ACTION キャプション 実行開始
4. SRQイベントの実装を行います。
・先程ダイアログボックスに貼り付けたボタンにカーソルを合わせ、右クリック→「ClassWizard」
を選択し、以下のように設定した後、「関数の追加」をクリックします。
プロジェクト GpibEventDll
クラス名 CGpibEventDllDlg オブジェクト IDC_ACTION
メッセージ BN_CLICKED
・メンバ変数名を決定するダイアログボックスが表示されますので、“OnAction”になっているこ とを確認して「OK」をクリックします。
・そのまま「コード編集」ボタンをクリックして、“OnAction”関数を実装します。以下のように コード(List 2-16)を記述してください。
(List 2-16:CGpibEventDllDlgクラスのOnAction関数の追加コード)
void CGpibEventDllDlg::OnAction() {
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください INT nRet; // 関数の実行結果
char SendBuf[32]; // 送信コマンドを格納する変数 CString szErrMsg; // エラーメッセージ
//‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑
// SRQ信号の発行を行います
// スタンダード・イベント・レジスタのBit0に1を立て、オペレーション完了をイネーブルにします sprintf(SendBuf,"*ESE 1");
nRet = PciGpibExMastSendData(BoardNo, gnDevAdrsTbl, strlen(SendBuf), SendBuf, WM̲NULL);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("データ送信に失敗しました(%d)", nRet);
MessageBox(szErrMsg, "送信エラー", MB̲ICONERROR);
}
// ステータス・バイト・サマリ・レジスタのBit5に1を立て、
// スタンダード・イベントをイネーブルにします sprintf(SendBuf,"*SRE 32");
nRet = PciGpibExMastSendData(BoardNo, gnDevAdrsTbl, strlen(SendBuf), SendBuf, WM̲NULL);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("データ送信に失敗しました(%d)", nRet);
MessageBox(szErrMsg, "送信エラー", MB̲ICONERROR);
}
// *OPCコマンドを実行してオペレーション完了を知らせます sprintf(SendBuf,"*OPC");
nRet = PciGpibExMastSendData(BoardNo, gnDevAdrsTbl, strlen(SendBuf), SendBuf, WM̲NULL);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("データ送信に失敗しました(%d)", nRet);
MessageBox(szErrMsg, "送信エラー", MB̲ICONERROR);
} }
5. コールバック関数の実装を行います。
先程編集したGpibSrqDllDlg.cppを開き、最後の部分に(List 2-17)の関数を記述します。
(List 2-17:GpibSrqDllDlg.cppのコールバック関数のコード)
void CALLBACK lpOnSrqProc(int nBoardNo, DWORD dwUser) {
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください INT nRet; // 関数の実行結果
INT nStbTbl[2]; // ステータス・バイト格納テーブル INT nStbAdrs[2]; // SRQ送出機器アドレス格納テーブル INT nSrqRet; // SRQ割り込み確認の実行結果
INT nSpRet; // シリアルポールの実行結果 char SpStatus[256]; // シリアル・ポーリングステータス char SendBuf[32]; // 送信コマンドを格納する変数 CString szErrMsg; // エラーメッセージ
// コールバックイベントで使用するメッセージボックス //AfxMessageBox("SRQ信号が発生しました");
//‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑
// シリアルポーリングを行います
// SRQ信号の有無を確認します
nSrqRet = PciGpibExCheckSrq(BoardNo);
switch(nSrqRet){
case GP‑IB̲SUCCESS̲ACTIVE̲SRQ: // SRQ信号が有効な場合の処理 // シリアル・ポーリングを実行します
nSpRet = PciGpibExExecSpoll(BoardNo, gnDevAdrsTbl, nStbTbl, nStbAdrs);
if(nSpRet != GP‑IB̲SUCCESS){
szErrMsg.Format("シリアル・ポーリングに失敗しました(%d)", nSpRet);
AfxMessageBox("ポーリングエラー");
} else{
// シリアルポールで得たステータスバイトデータをエディットボックスに表示します sprintf(SpStatus, "%Xh", nStbTbl[0]);
AfxMessageBox(SpStatus);
} break;
case GP‑IB̲SUCCESS̲NOT̲ACTIVE̲SRQ: // SRQ信号が無効な場合の処理 AfxMessageBox("SRQ信号無効エラー");
break;
default: // エラーが発生した場合の処理 szErrMsg.Format("エラーが発生しました(%d)", nSrqRet);
AfxMessageBox("SRQ信号確認エラー");
break;
}
//‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑‑
// SRQ信号のクリアを行います
// GP‑IB機器のレジスタをクリアします sprintf(SendBuf,"*CLS");
nRet = PciGpibExMastSendData(BoardNo, gnDevAdrsTbl, strlen(SendBuf), SendBuf, WM̲NULL);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("レジスタクリアに失敗しました(%d)", nRet);
AfxMessageBox("レジスタクリアエラー");
}
// SRQ信号をクリアします(PCI‑4301では必要ありません) nRet = PciGpibExClearSrq(BoardNo);
if(nRet != GP‑IB̲SUCCESS){
szErrMsg.Format("SRQクリアに失敗しました(%d)", nRet);
AfxMessageBox("SRQクリアエラー");
} }
以上でSRQ割り込みによるコールバックイベントのプログラムが完成です。セーブをした後で、
機器の電源が入っていることを確認してプログラムを実行してください。「実行開始」ボタンを 押すと、SRQイベントが発行されてコールバック関数が呼び出されて、メッセージボックスが表 示されます。(表示画面については『26ページ 第4章 チュートリアル(高機能版ActiveXコント ロール)』のSRQイベントと同じとなりますので、そちらを参照してください。)
では、これより使用したDLL関数についての説明をしていきます。
List 2-11では、PciGpibExCheckSrq関数を使用してSRQ信号の確認を行い、SRQ信号の有効・無効 の判定を行っています。また、SRQ信号が有効であった場合に、PciGpibExExecSpoll関数を使用し て機器に対してシリアル・ポーリングを行っています。このシリアル・ポーリングで接続された 機器の状態を順番に調べて行き、SRQ信号を発行した機器を特定して、その機器のステータス・
バイト・レジスタの値を用意した変数に取得しています。
「使用例」
nRet = PciGpibExCheckSrq(BoardNo);
関数が失敗するとエラーコードが格納されます。
SRQの確認を行うI/Oモジュールのアドレス番号を指定します。
「使用例」
nRet = PciGpibExExecSpoll(BoardNo, gnDevAdrsTbl, nStbTbl, nStbAdrs);
関数が失敗するとエラーコードが格納されます。
シリアル・ポールを行うボードのアドレス番号を指定します。
シリアル・ポールを行う機器のアドレステーブルへの ポインタを指定します。
シリアル・ポーリングを行い受信した各機器の有効なステータス・バイ トを格納するテーブルへのポインタを指定します。
SRQを送出し、有効なステータス・バイトを持っていた各機器のアド レスを格納するテーブルへのポインタを指定します。
List 2-12では、PciGpibExMastSendData関数を使用して接続された機器にコマンドを送信して、SRQ
信号の設定を行っています。ここでは、オペレーションの完了によりSRQ信号を発行するように しています。実際に使用する機器でSRQイベントとして取得したい条件を設定してください。
List 2-13では、PciGpibExClearSrq関数を使用してSRQ信号の受信状態解除を行い、接続された機器
にコマンドを送信してレジスタのクリアを行っています。このSRQ信号受信状態の解除とレジス タのクリアによりSRQ信号を再び有効にすることができます。
「使用例」
nRet = PciGpibExClearSrq(BoardNo);
関数が失敗するとエラーコードが格納されます。
SRQ受信状態の解除を行うI/Oモジュールのアドレス番 号を指定します。
List2-14~List2-17ではSRQ信号によるコールバックイベントの登録を行っています。
PciGpibExSetSrqEvent関数によって、コールバックイベントへのポインタを登録することで、SRQ
信号が発生した際に登録したイベントを実行することができます。また、PciGpibExKillSrqEvent 関数を使用することで設定したイベントの解除を行っています。このコールバックイベントのな かで、前述したシリアル・ポーリング処理を行うことで、SRQ割り込みが発生した際に、自動的 にSRQ信号を発生させた機器を調べる処理を行わせることが可能になります。
「使用例」
nRet = PciGpibExSetSrqEvent(BoardNo, (PLPSRQCALLBACK)lpOnSrqProc, dwUser);
関数が失敗するとエラーコードが格納されます。
コールバックイベントの設定を行うI/Oモジュ ールのアクセス番号を指定します。
コールバック関数のアドレスを指定します。
コールバック関数に渡す任意の32ビットデー
タを指定します。
「使用例」
nRet = PciGpibExKillSrqEvent(BoardNo);
関数が失敗するとエラーコードが格納されます。
SRQの解除を行うI/Oモジュールのアクセス 番号を指定します。