Windows98/2000におけるDelphi (Pascal) によるGPIBの制御
02/01/16 Takayuki Goto
1.準備
1-1 Delphi パーソナル版を Borland WEB から無償ダウンロード
http://www.borland.co.jp/delphi/personal/
普通にインストール、WEB で登録して、コードキー取得
1-2 インストールディレクトリ中の bin から、DCC32.EXEとDCC32.CFG を抜き出し
DCC32.CFG でユニットファイル (*.DCU) の場所を指定する -u".";"c:\tp32\lib"
同じく lib ディレクトリから、SYSTEM.DCU 及び、Windows.dcu, Sysutils.dcu 等の
ライブラリユニットを抜き出す。
1-3 National Instruments WEB から GPIB ボードのドライバをダウンロードして
普通にインストール,
http://www.ni.com/support/ja/download.htm
1-4 NI 社のサンプルプログラムの Delphi 版を印刷して読む
C:\Program Files\National Instruments\NI-488.2\Languages\Delphi にある。
同じく NI 社の Readme.TXT を印刷して読む
(定数や型について重要なことが書かれている)
1-5 NI 社の定数・型定義ファイル Decl-32.h を印刷して読む
C:\Program Files\National Instruments\NI-488.2\Languages\DLL Direct Entry
にある
2 プログラミング
2-1 {$apptype console} をプログラムの先頭に書いてコンソールオンリーモードにする。
2-2 DLL (gpib-32.dll) を動的リンクするためのコードを書く。
このリンクのために、Windows.dcu が必要。
2-3 グローバル変数・手続き・関数のアドレスをゲット、アサイン たとえば SendIFC は
まず型定義 TSendIFC = procedure(boardID: integer); stdcall;
をして、変数定義
SendIFC :TSendIFC;
で、プロシージャの「頭」を確保して、本体のアドレスを
@SendIFC:= GetProcAddress(Gpib32Lib, 'SendIFC');
で強制的に代入してしまう。
なお、状態変数 ibsta, エラー変数 iberr, 転送バイト数変数 ibcntl の三つのみは、
gpib-32.dll のエキスポート名が、user_ibsta と少し違っているので、
型定義
Tibsta = function : integer ; stdcall; では function としておいて、その後、
変数定義では
一旦、AddrIbsta : Tibsta; として、ポインタ Pibsta : ^integer; も作っておく。
そして、本体のアドレスも一旦、AddrIbsta に代入しておいてから、
@AddrIbsta := GetProcAddress(Gpib32Lib, 'user_ibsta');
最後に、Pibsta := @AddrIbsta; と
代入する。
注意としては、@AddrIbsta への代入はなぜか省略できない。(つまり、このワンステップを
踏んだ手順が必ず必要)。
2-4 「アドレスリスト」は単純な配列 array[0..31]of SmallInt; で、最後に NOADR(=smallint($FFFF))
が入る。アドレスリストは REN 制御等に使う。詳しくは Readme.txt を見る(1-4)。
2-5 GPIB バッファへのパラメタ引渡しは packed array of pchar で行う。
string では read_only の属性がついてしまいエラーを引き起こす。
2-6 packed array of pchar への文字列代入は strcopy(buf, 'abc')
文字列長は strlen(buf) で得る。
2-7 strcopy で代入した際は、buf[0]~buf[N-1] にデータが入り、最後はヌル
2-8 他の型への変換は、例えば、pchar の配列 buf から 2-byte integer へは、
Pi:^shortint; で
ポインタを作り、
Pi=@buf[0]; でアドレスをゲットし、
i:=shortint (Pi^); のように目的の型へキャストで
送り込めばよい。
2-9 GPIB でデータを取り込んだ際は、バッファ配列に、最後のヌルは入らない。よって、Pibcntl^ で
実転送データ数を調べる必要がある。
2-10 タイムアウトは 1,3,10 秒など、とびとびの特定の値しか取れない。
2-11 App488.2 でプログラミングする際は、
link-LIB, Send-IFC, Enable-REN…local-REN, Free-lib
の通常手順でよい。
(App488 では IFC や REN は不要らしいので注意)
2-12 App488.2 の FindListner は、全ての機器が 488-2 対応であれば使えるが、古い機器が
混じっている場合は使えない。要するに、488-2 では、*IDN など、必ず応答すべき、共通のコマンドが
定義されているのである。
2-13 ボード No. は 0 (デバイス名が GPIB0 ならば)
2-14 送信デリミタは、EOI か特定文字 1 文字のみ。
CRLF が必要ならば、データとして送る。
2-15 受信デリミタは、文字数指定か、EOI か Nlend のみ。
CRLF を送ってくる場合は LF をデリミタにして、CR を捨てる。
2-16 丸善の実験物理学講座に掲載されているコマンド類の殆どは、GPIB32.dcu に収めてある。
3 Cryogenic 社超伝導マグネットの電源プログラミング
一番の問題点は 3−3 で記載されているように、前ぶれ無く突然、一方的にサインオンメッセージを送って
くることである。これを取りこぼすと、その後、動作が不安定になったりするし、また、この意味の無い
サインオンメッセージと、重要なデータを取り違えたりすると、事故に発展することも有り得る。よって、要点は、
サインオンメッセージの sign を見逃さない、ということに尽きる。一般の GPIB 装置は、PC からコマンドを
送らない限り返答しないので、かなりプログラミングの勝手が異なる。
3-1 デリミタは LF のみ。
EOI-only ではうまくいかないようである。
3-2 すべてのコマンドの実行前に、トーカ指定して文字列データ読み込みを行う。
トーカ指定して
読み込みを実行するとたとえデータが無くとも、必ず、LF だけは送ってくる筈である。
もし、タイムアウトするのであれば、多くの場合デリミタ設定を間違えていると思われる。
ただ、たまに、LF デリミタ指定でも反応が無くなる場合がある。対処としては、一旦完全にローカルに
してやるか、又はデバイスクリヤ DCL を送る。(セレクテッドデバイスクリヤでは効果が無いようである)。
3-3 IFC と REN の間に、2秒以上の間があると、サインオンメッセージが自動的に流れ出す。
これは、ハンドシェークを無視して送り出される (GPIB インタフェースを備えた旧式のイメージスキャナ等
と同じ動作)。
なお、リモートのランプが点灯していれば、一旦 REN-OFF にしてもサインオンメッセージは出ない。
リモートランプが消えて完全にローカルモードになるのは、REN-OFF の状態で、IFC を送ったときである。
よって、他のプログラムと組み合わせてバッチ処理する際は、かならずサインオンメッセージを出させて
から次の処理に移ることになる。
3-4 意味のある命令データを PC から送った直後に電源をトーカー指定しても、直ちにレスポンスがある
とは限らない。しばらくは、空行のみ (LF) を送り返してくるかもしれない。意味のあるレスポンスが
あるまで、トーカ指定 +input+ 入力文字列チェックを数回繰り返す。