第 3 章 GP-IB I/O モジュール制御の第一歩 20
3.5 GP-IB機器からのサービスリクエスト(SRQ)を捉えるプログラム
srqevent.oを組み込むと、コンソールに以下のメッセージが出力され、 Agilent34401Aからのサービ
スリクエストの検知とコールバック処理が行われたことがわかります。# insmod srqevent.o init_module called
Board open success!! [0]
send_task called arg=0 send_data called [*RST]
send_data success!! [ret=0]
send_data called [*CLS]
send_data success!! [ret=0]
send_data called [*SRE 16]
send_data success!! [ret=0]
send_data called [MEASure:VOLTage:DC?]
send_data success!! [ret=0]
srq_callback called [0x4000000, 0]
Serial poll success!!
no.0 status byte=50 addrss=22
PciGpibExRecvData [0, 15, +5.98390000E-05]
次に、組み込んだRTLinuxモジュールを取り外しは、rmmodコマンドで行います。
# rmmod srqevent
(121〜141行目:GP-IBの初期化)
ここでは、
GP-IB I/Oモジュールのオープンと初期化、 IFCの送出と RENの設定が行われています。
この処理は定形的なものです。
(144行目:コールバック関数の登録とイベントマスクの設定)
PciGpibExSetEventMask関数により、コールバック関数の登録とイベントマスクの設定を行います。
ここでは、SRQイベントをとらえるために、イベントマスクを設定する第2引数に、
GPIB_DETECT_SRQを指定しています。
★イベントマスクについて
ここでは SRQ イベントのみを使用するため、GPIB_DETECT_SRQ のみを指定しましたが、複数のイベ ントを使用する場合は、各識別子をPciGpibExSetEventMask関数の第2引数にORで指定します。
SRQ検出とIFC検出を指定する場合>
PciGpibExSetEventMask( GPIB_BOARDNO,
GPIB_DETECT_SRQ | GPIB_DETECT_IFC, srq_callback, GPIB_BOARDNO);
第3引数はコールバック関数のアドレス値を、第4引数にはコールバック関数が呼び出させた際に 渡すユーザ定義の値を指定します。
ここでは、デバイス番号をユーザ定義の値として渡しています。
(154行目:pthread_create関数)
pthread_create関数では、GP-IB機器へのデータ送信を行うRTLinuxスレッド(send_task)を生成して
います。(87〜98行目:電圧測定の指示)
81行目から始まるsend_task関数は、Agilent34401Aに対して電圧測定を行わせるためのコマンドを
順次送信しています。Agilent34401Aはデータ送信された内容に従って、何らかの処理を行います。
行 送信内容 処理内容
87行目
"*RST"
Agilent34401Aを電源投入時の状態にリセットします。90行目
"*CLS"
Agilent34401A内の各レジスタをクリアします。93行目
"*SRE 16"
SRQ割り込みを有効にします。ここでは、ステータスバイトレジスタの、メッセージアベイラ ブルビットを有効にしています。
98行目
"MEASure:VOLTage:
DC?"
Agilent34401Aに対し、電圧測定を行うよう指示します。各行のsend_data関数は、データ送信を行うサブルーチン(64〜78行目)です。プログラムの記述を簡 素化するために定義しています。
List3-1のデータ送信部分のコードと比較してみてください。
98行目のデータ("MEASure:VOLTage:DC?")を送信すると、Agilent34401Aは電圧の計測を行います。
計測が完了すると、Agilent34401Aは内部バッファに測定したデータを格納します。
この時、
93行目の指示("*SRE 16")により有効にされた、割り込みマスク(ステータスバイトレジス
タのメッセージアベイラブルビット)により、Agilent34401AはSRQを発行します。
(動作の詳細は、Agilent34401A付属のマニュアル「SCPIステータスモデル」を参照してください)
Agilent34401Aの動き
電圧の計測
出力バッファへ 計測データを格納
ステータスバイトの メッセージアベイラブル
ビットをチェック
サービスリクエスト発行 ON
OFF
Agilent34401Aの電圧計測時の動き
(16〜61行目:発生したイベントの判別,シリアルポール実行,データ受信)
Agilent34401AからSRQが発行されると、ドライバモジュールは登録されたコールバック関数 (srq_callback)を呼び出します。
コールバック関数の第1引数にはコールバック関数が呼び出されたイベント要因を示す値が、第2 引数にはPciGpibExSetEventMask関数で指定したユーザ定義の値(このプログラムでは、デバイス番 号の値)が引き渡されます。
28行目は、第1引数で渡されたイベント要因が、SRQ割り込みによるものかチェックしています。
30行目のPciGpibExExecSpoll関数は、どのGP-IB機器がSRQを発行したかチェックを行うシリアル
ポールを行っています。SRQを発行したGP-IB機器は、シリアルポールを行った後、第3引数のス テータスバイト中の第6ビット(リクエストサービスビット)が、必ず1になります。
★PciGpibExExecSpoll関数について
PciGpibExExecSpoll関数によりシリアルポールを行います。PciGpibExExecSpoll関数の第2引数には、
PciGpibExSendData関数と同じように、シリアルポールの対象となる機器のアドレスを、int型(整数型)
の配列で指定します。この第2引数には、複数の機器アドレスが指定できます。配列の終端には必ず-1 を付加してください。
取得したステータスバイトは、第 3 引数で指定する配列に格納され、有効なステータスバイトを持って いた機器のアドレスは、第4引数に格納されます。
GP-IB 機器アドレスが、それぞれ1,2,3の機器が接続されていて、アドレス2の機器からSRQが発行さ
れた場合は、以下のようになります。
呼び出し例>
int ret;
int adrs̲tbl[4] = {1, 2, 3, ‑1}; /* アドレスが 1、2、3 の 3 つの機器を指定します */
int stb̲tbl[4];
int stb̲adrs[4];
ret = PciGpibExExecSpoll(0, adrs̲tbl, stb̲tbl, stb̲adrs);
if(ret == 0){ /* 関数正常終了時 */
/* アドレス 2 の機器から SRQ が発行されていた場合、配列要素の内容は stb̲tbl[0] = アドレス 2 の機器のステータスバイト
stb̲tbl[1] = ‑1 (終端)
stb̲adrs[0] = 2 (SRQ を発行した機器のアドレス) stb̲adrs[1] = ‑1 (終端)
となります。
*/
}