Sign in Join
Wiki copytemporary

Hardware Access/ja: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## 概要
22
33このページはLazarusでハードウェアデバイスにアクセスを行うためのチュートリアルです。ここにはISA、PCI、USB、パラレルポート、シリアルポートの各デバイスについて書かれていますが、完全ではありません。
44
55ハードウェアデバイスへのアクセスはFree PascalランタイムライブラリやLCLをもってしても完全な移植性をもつことはできません。このチュートリアルは多くのプラットホームに適用できるハードウェアへアクセスの手法の基本的な部分をカバーします。コードを違った環境でコンパイルするためには以下のような条件付きコンパイルが必要となるでしょう。
66
7-<code>
8-
97`uses`\
108` Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,`\
119`{$IFDEF WIN32}`\
1210`  Windows;`\
1311`{$ENDIF}`\
1412`{$IFDEF Unix}`\
1513`  ports;`\
1614`{$ENDIF}`
1715
18-</code>
19-
2016x86プロセッサ上で動作するMac OS Xでのハードウェアアクセスが可能かどうかは現時点では不明です。
2117
2218## パラレルおよびシリアル接続
2319
2420ISAカード、PCIカードおよびパラレルポートでの通信ではコンピュータは**パラレル**プロトコルを使用します。シリアルポートやUSBデバイスでは**シリアル**プロトコルを使用します。このようにプロトコルを使い分けるのは、プロセッサやプログラミング言語はすべてデータにパラレルでアプローチするため、より簡単にするためにプロトコルはソフトウェア側で実装してやる必要があるのです。 例えばあなたがInteger変数にアクセスする時、それは一つのコマンドで行う事ができます。しかしそれは連続した手順によって一度に一ビットずつデータを取得しているだけなのです。ですから、その断片化したデータをくっつけてやる必要があります。
2521
2622シリアル通信を直接行う事は難しいですが、仮実装されたコンポーネントを使用する事により簡単に行う事もできます。また、ハードウェア側ではそれすらできないので、多くの場合それを実行するのに特化した装置が必要であり、ICやマイクロコントローラを使用する必要があります。
2723
2824ハードウェアアクセスプロトコルの簡潔な比較を以下に提示します。
2925
3026| | 速度 | 実装の難易度 |
3127|----------------|--------------------------|--------------|
3228| シリアルポート | 非常に遅い (\< E5 bit/s) | 普通 |
3329| パラレルポート | 遅い (~ E6 bit/s) | 簡単 |
3430| ISAカード | 普通 (~ E7 bit/s) | 普通 |
3531| USB | 普通 (~ E7 bit/s) | 難しい |
3632| PCIカード | 非常に速い (\> E9 bit/s) | 非常に難しい |
3733
3834## パラレル通信
3935
4036### Windows上でinpout32.dllを使用する
4137
4238Windowsではハードウェアデバイスへのアクセスを行う手順に9x系とNT系では違いがあります。9x系(95,98,Me)ではプログラムはDOSのように直接ハードウェアに対してアクセスすることができます。NT系(Windows NT,2000,XP)ではそのような方法は使えません。すべてのハードウェアポートはデバイスドライバによって通信する事ができます。これはセキュリティ上の問題からそうなっていますが、ドライバを作るためには時間とお金が必要で小さいプロジェクトは難しいでしょう。
4339
4440しかし、幸せな事にこの問題を解決するライブラリがあります。WIndowsNTが検出されるとそれはHWInterface.sysカーネルデバイスドライバを解凍して、インストールします。Window9xが検出されると、それはハードウェアデバイスにアクセスするのに単にアセンブラオペコードを使用します。
4541
4642でもそのライブラリをどうやって使ったらいいのでしょうか?簡単です!このライブラリはInp32とOut32という2つの関数しか持っていませんし、その使用は非常に直感的です。
4743
4844ライブラリを動的にロードすると、関数は次のように定義されます
4945
50-<code>
51-
5246`type`\
5347`  TInp32 = function(Address: ShortInt): ShortInt; stdcall;`\
5448`  TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;`
5549
56-</code>
57-
5850- Address represents the address of the port you desire to access
5951- Out32 sends Data to the port you specify by Address
6052- Inp32 returns a byte from the port you specify by Address
6153
6254わたしたちはこれでライブラリをロードする事ができます。あなたのプログラムのメインフォームのOnCreateメソッドのような場所でこれを実行する事が可能です:
6355
64-<code>
65-
6656`type`\
6757`  TMyForm = class(TForm)`\
6858`  .........`\
6959`  private`\
7060`    { private declarations }`\
7161`    Inpout32: THandle;`\
7262`    Inp32: TInp32;`\
7363`    Out32: TOut32;`\
7464`  .........`\
7565`implementation`\
7666`  .........`\
7767`procedure TMyForm.FormCreate(Sender: TObject);`\
7868`begin`\
7969`{$IFDEF WIN32}`\
8070`  Inpout32 := LoadLibrary('inpout32.dll');`\
8171`  if (Inpout32 <> 0) then`\
8272`  begin`\
8373`    // needs overtyping, plain Delphi's @Inp32 = GetProc... leads to compile errors`\
8474`    Inp32 := TInp32(GetProcAddress(Inpout32, 'Inp32'));`\
8575`    if (@Inp32 = nil) then Caption := 'Error';`\
8676`    Out32 := TOut32(GetProcAddress(Inpout32, 'Out32'));`\
8777`    if (@Out32 = nil) then Caption := 'Error';`\
8878`  end`\
8979`  else Caption := 'Error';`\
9080`{$ENDIF}`\
9181`end;`
9282
93-</code>
94-
9583もしOnCreateでライブラリをロードしたなら、OnDestroyでアンロードする事を忘れないで下さい:
9684
97-<code>
98-
9985`procedure TMyForm.FormDestroy(Sender: TObject);`\
10086`begin`\
10187`{$IFDEF WIN32}`\
10288`  FreeLibrary(Inpout32);`\
10389`{$ENDIF}`\
10490`end;`
10591
106-</code>
107-
10892これはInp32関数を使う単純な例です:
10993
110-<code>
111-
11294`{$IFDEF WIN32}`\
11395`  myLabel.Caption := IntToStr(Inp32($0220));`\
11496`{$ENDIF}`
11597
116-</code>
117-
11898このコードはカスタムISAカードのポート\$0200と、WindowsXP上のLazarus 0.9.10でテストされました。もちろんこのコードを実行するためにはuses節にWindowsが必要です。また、自分のアプリケーションと同じディレクトリに"input32.dll"も必要です。
11999
120100このホームページのライブラリはこちら: [www.logix4u.net/inpout32.htm](http://www.logix4u.net/inpout32.htm)
121101
122102### Linuxでiopermを使用する
123103
124104Linuxでハードウェアにアクセスする最適な方法はThroughtデバイスドライバを使用することですが、ドライバを作成するタスクは複雑なので整理されたメソッドを使えば楽にそれを行うことができます。
125105
126106あなたのLinuxプログラム上で "[[doc:rtl/ports|ports]]" ユニットを呼び出すためにはrootで実行する必要があり、またIOPermを呼び出すためにはポートにアクセスするための権限が必要です。 あなたは"[[doc:rtl/ports|ports]]"ユニットについての情報を[ここ](http://www.freepascal.org/docs-html/rtl/ports/index.html)で手に入れることができます。
127107
128108最初にやることは、(g)libcをリンクして、IOPermをコールすることです。すべての(g)libc(の関数)にリンクするユニットは、free pascal上にありますが、このユニットをアプリケーションから直接リンクすることは問題をひきおこします。(g)libcライブラリ全体を静的リンクをおこなう、ということはあまり良い方法とはいえません、なぜなら、それはバージョンの間で、しばしば変更されるからです。iopermといった関数はしかしながら、変更することはあまりないと思います。
129109
130-<code>
131-
132110`{$IFDEF Linux}`\
133111`function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';`\
134112`{$ENDIF}`
135113
136-</code>
137-
138114- "from" はアクセスする最初のポートを指定します。
139115- "num" は最初のポートから何ポートアクセスするかを指定します。
140116
141117たとえば、ioperm(\$220, 8, 1)はプログラムに\$220から\$227までのアクセス権限を与えます。
142118
143119IOPermをリンクしたあとで、ポートにアクセスするために、port\[\<Address\>\]配列を使うことができます。
144120
145-<code>
146-
147121`{$IFDEF Linux}`\
148122`  i := ioperm($220, 8, 1);`\
149123`  port[$220] := $00;`\
150124`  myLabel.Caption := 'ioperm: ' + IntToStr(i);`\
151125`  i := Integer(port[$220]);`\
152126`  myOtherLabel.Caption := 'response: ' + IntToStr(i);`\
153127`{$ENDIF}`
154-
155-</code>
156128
157129このコードは、Mandriva Linux 2005とDamn Small Linux 1.5上で、Lazarus 0.9.10を使って、自作のISAカードで\$0220にアクセスしてテストしました。
158130
159131### 一般的なUNIXでのハードウエアアクセス
160132
161133 {$IFDEF Unix}
162134 Uses Clib; // retrieve libc library name.
163135 {$ENDIF}
164136
165137 {$IFDEF Unix}
166138 function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib;
167139 {$ENDIF}
168140
169141**注意** FPCはin [[doc:rtl/x86/index.html|unit x86で]]"fpioperm"よ呼ばれる抽象的な機構を提供しています。そして、入出力機能を定義しています。 これらの関数はx86で動作するLinuxとFreeBSDで実装されています。
170142
171143配布と関数のポータビリティのため、必要な抽象化なしにlibcをリンクすることは推奨されていません。libcの手動リンク(つまり、どこからでも使えるように、libcをad hoc宣言をする方法)をおこなうことは推奨されません。
172144
173145(e.g. the above libc import line will unnecessarily fail if the standard C lib is not called libc, like e.g. libroot on BeOS, or on platforms with a non standard C symbol mangling). 訳注:うまいこと訳せないので、和訳せず、そのままのこしておきます。)
174146
175147**注意2** _unit_ libcを使うことはどんな状況下でもKylixの互換性の点では推奨されません。このユニットは相対的にポータブルではないからです。(due to excessive exposure of structures and other private symbols)
176148
177149そして、Kylixの互換性の問題からは、なるべく少なく変更すべきです。
178150
179151## シリアル通信
180152
181153[[Hardware Access/ja|外部リンクセクションにUNIXとWindowsのシリアルポートチュートリアルがあります]]。
182154
183155## 外部リンク
184156
185157通信プロトコルスピードの比較:
186158
1871591. <http://en.wikipedia.org/wiki/Serial_port#Speed>
1881602. <http://www.lvr.com/jansfaq.htm> - Jan Axelson's Parallel Port FAQ
1891613. <http://en.wikipedia.org/wiki/USB#Transfer_Speed>
1901624. <http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications>
191163
192164シリアル通信のリンク:
193165
1941661. On UNIX: [1](http://www.easysw.com/~mike/serial/serial.html)
1951672. On Windows: <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp>
1961683. Synaser component: <http://synapse.ararat.cz/>
197169
198170ISA デジタルオシロスコープ - 全ソースが含まれるハードウエアのアクセス例:
199171
200172[2](http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/)
201173
202174---
203175*From the Free Pascal wiki, page "Hardware Access/ja", as it stood on 2006-08-20 after a change by Saeka-jp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history