Sign in Join
Wiki copytemporary

Hardware Access/ja: what changed

Revision 2 to 3. 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-`uses`\
8-` Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,`\
9-`{$IFDEF WIN32}`\
10-`  Windows;`\
11-`{$ENDIF}`\
12-`{$IFDEF Unix}`\
13-`  ports;`\
14-`{$ENDIF}`
7+``` pascal
8+uses
9+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
10+{$IFDEF WIN32}
11+ Windows;
12+{$ENDIF}
13+{$IFDEF Unix}
14+ ports;
15+{$ENDIF}
16+```
1517
1618x86プロセッサ上で動作するMac OS Xでのハードウェアアクセスが可能かどうかは現時点では不明です。
1719
1820## パラレルおよびシリアル接続
1921
2022ISAカード、PCIカードおよびパラレルポートでの通信ではコンピュータは**パラレル**プロトコルを使用します。シリアルポートやUSBデバイスでは**シリアル**プロトコルを使用します。このようにプロトコルを使い分けるのは、プロセッサやプログラミング言語はすべてデータにパラレルでアプローチするため、より簡単にするためにプロトコルはソフトウェア側で実装してやる必要があるのです。 例えばあなたがInteger変数にアクセスする時、それは一つのコマンドで行う事ができます。しかしそれは連続した手順によって一度に一ビットずつデータを取得しているだけなのです。ですから、その断片化したデータをくっつけてやる必要があります。
2123
2224シリアル通信を直接行う事は難しいですが、仮実装されたコンポーネントを使用する事により簡単に行う事もできます。また、ハードウェア側ではそれすらできないので、多くの場合それを実行するのに特化した装置が必要であり、ICやマイクロコントローラを使用する必要があります。
2325
2426ハードウェアアクセスプロトコルの簡潔な比較を以下に提示します。
2527
2628| | 速度 | 実装の難易度 |
2729|----------------|--------------------------|--------------|
2830| シリアルポート | 非常に遅い (\< E5 bit/s) | 普通 |
2931| パラレルポート | 遅い (~ E6 bit/s) | 簡単 |
3032| ISAカード | 普通 (~ E7 bit/s) | 普通 |
3133| USB | 普通 (~ E7 bit/s) | 難しい |
3234| PCIカード | 非常に速い (\> E9 bit/s) | 非常に難しい |
3335
3436## パラレル通信
3537
3638### Windows上でinpout32.dllを使用する
3739
3840Windowsではハードウェアデバイスへのアクセスを行う手順に9x系とNT系では違いがあります。9x系(95,98,Me)ではプログラムはDOSのように直接ハードウェアに対してアクセスすることができます。NT系(Windows NT,2000,XP)ではそのような方法は使えません。すべてのハードウェアポートはデバイスドライバによって通信する事ができます。これはセキュリティ上の問題からそうなっていますが、ドライバを作るためには時間とお金が必要で小さいプロジェクトは難しいでしょう。
3941
4042しかし、幸せな事にこの問題を解決するライブラリがあります。WIndowsNTが検出されるとそれはHWInterface.sysカーネルデバイスドライバを解凍して、インストールします。Window9xが検出されると、それはハードウェアデバイスにアクセスするのに単にアセンブラオペコードを使用します。
4143
4244でもそのライブラリをどうやって使ったらいいのでしょうか?簡単です!このライブラリはInp32とOut32という2つの関数しか持っていませんし、その使用は非常に直感的です。
4345
4446ライブラリを動的にロードすると、関数は次のように定義されます
4547
46-`type`\
47-`  TInp32 = function(Address: ShortInt): ShortInt; stdcall;`\
48-`  TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;`
48+``` pascal
49+type
50+ TInp32 = function(Address: ShortInt): ShortInt; stdcall;
51+ TOut32 = procedure(Address: ShortInt; Data: ShortInt); stdcall;
52+```
4953
5054- Address represents the address of the port you desire to access
5155- Out32 sends Data to the port you specify by Address
5256- Inp32 returns a byte from the port you specify by Address
5357
5458わたしたちはこれでライブラリをロードする事ができます。あなたのプログラムのメインフォームのOnCreateメソッドのような場所でこれを実行する事が可能です:
5559
56-`type`\
57-`  TMyForm = class(TForm)`\
58-`  .........`\
59-`  private`\
60-`    { private declarations }`\
61-`    Inpout32: THandle;`\
62-`    Inp32: TInp32;`\
63-`    Out32: TOut32;`\
64-`  .........`\
65-`implementation`\
66-`  .........`\
67-`procedure TMyForm.FormCreate(Sender: TObject);`\
68-`begin`\
69-`{$IFDEF WIN32}`\
70-`  Inpout32 := LoadLibrary('inpout32.dll');`\
71-`  if (Inpout32 <> 0) then`\
72-`  begin`\
73-`    // needs overtyping, plain Delphi's @Inp32 = GetProc... leads to compile errors`\
74-`    Inp32 := TInp32(GetProcAddress(Inpout32, 'Inp32'));`\
75-`    if (@Inp32 = nil) then Caption := 'Error';`\
76-`    Out32 := TOut32(GetProcAddress(Inpout32, 'Out32'));`\
77-`    if (@Out32 = nil) then Caption := 'Error';`\
78-`  end`\
79-`  else Caption := 'Error';`\
80-`{$ENDIF}`\
81-`end;`
60+``` pascal
61+type
62+ TMyForm = class(TForm)
63+ .........
64+ private
65+ { private declarations }
66+ Inpout32: THandle;
67+ Inp32: TInp32;
68+ Out32: TOut32;
69+ .........
70+implementation
71+ .........
72+procedure TMyForm.FormCreate(Sender: TObject);
73+begin
74+{$IFDEF WIN32}
75+ Inpout32 := LoadLibrary('inpout32.dll');
76+ if (Inpout32 <> 0) then
77+ begin
78+ // needs overtyping, plain Delphi's @Inp32 = GetProc... leads to compile errors
79+ Inp32 := TInp32(GetProcAddress(Inpout32, 'Inp32'));
80+ if (@Inp32 = nil) then Caption := 'Error';
81+ Out32 := TOut32(GetProcAddress(Inpout32, 'Out32'));
82+ if (@Out32 = nil) then Caption := 'Error';
83+ end
84+ else Caption := 'Error';
85+{$ENDIF}
86+end;
87+```
8288
8389もしOnCreateでライブラリをロードしたなら、OnDestroyでアンロードする事を忘れないで下さい:
8490
85-`procedure TMyForm.FormDestroy(Sender: TObject);`\
86-`begin`\
87-`{$IFDEF WIN32}`\
88-`  FreeLibrary(Inpout32);`\
89-`{$ENDIF}`\
90-`end;`
91+``` pascal
92+procedure TMyForm.FormDestroy(Sender: TObject);
93+begin
94+{$IFDEF WIN32}
95+ FreeLibrary(Inpout32);
96+{$ENDIF}
97+end;
98+```
9199
92100これはInp32関数を使う単純な例です:
93101
94-`{$IFDEF WIN32}`\
95-`  myLabel.Caption := IntToStr(Inp32($0220));`\
96-`{$ENDIF}`
102+``` pascal
103+{$IFDEF WIN32}
104+ myLabel.Caption := IntToStr(Inp32($0220));
105+{$ENDIF}
106+```
97107
98108このコードはカスタムISAカードのポート\$0200と、WindowsXP上のLazarus 0.9.10でテストされました。もちろんこのコードを実行するためにはuses節にWindowsが必要です。また、自分のアプリケーションと同じディレクトリに"input32.dll"も必要です。
99109
100110このホームページのライブラリはこちら: [www.logix4u.net/inpout32.htm](http://www.logix4u.net/inpout32.htm)
101111
102112### Linuxでiopermを使用する
103113
104114Linuxでハードウェアにアクセスする最適な方法はThroughtデバイスドライバを使用することですが、ドライバを作成するタスクは複雑なので整理されたメソッドを使えば楽にそれを行うことができます。
105115
106116あなたのLinuxプログラム上で "[[doc:rtl/ports|ports]]" ユニットを呼び出すためにはrootで実行する必要があり、またIOPermを呼び出すためにはポートにアクセスするための権限が必要です。 あなたは"[[doc:rtl/ports|ports]]"ユニットについての情報を[ここ](http://www.freepascal.org/docs-html/rtl/ports/index.html)で手に入れることができます。
107117
108118最初にやることは、(g)libcをリンクして、IOPermをコールすることです。すべての(g)libc(の関数)にリンクするユニットは、free pascal上にありますが、このユニットをアプリケーションから直接リンクすることは問題をひきおこします。(g)libcライブラリ全体を静的リンクをおこなう、ということはあまり良い方法とはいえません、なぜなら、それはバージョンの間で、しばしば変更されるからです。iopermといった関数はしかしながら、変更することはあまりないと思います。
109119
110-`{$IFDEF Linux}`\
111-`function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';`\
112-`{$ENDIF}`
120+``` pascal
121+{$IFDEF Linux}
122+function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';
123+{$ENDIF}
124+```
113125
114126- "from" はアクセスする最初のポートを指定します。
115127- "num" は最初のポートから何ポートアクセスするかを指定します。
116128
117129たとえば、ioperm(\$220, 8, 1)はプログラムに\$220から\$227までのアクセス権限を与えます。
118130
119131IOPermをリンクしたあとで、ポートにアクセスするために、port\[\<Address\>\]配列を使うことができます。
120132
121-`{$IFDEF Linux}`\
122-`  i := ioperm($220, 8, 1);`\
123-`  port[$220] := $00;`\
124-`  myLabel.Caption := 'ioperm: ' + IntToStr(i);`\
125-`  i := Integer(port[$220]);`\
126-`  myOtherLabel.Caption := 'response: ' + IntToStr(i);`\
127-`{$ENDIF}`
133+``` pascal
134+{$IFDEF Linux}
135+ i := ioperm($220, 8, 1);
136+ port[$220] := $00;
137+ myLabel.Caption := 'ioperm: ' + IntToStr(i);
138+ i := Integer(port[$220]);
139+ myOtherLabel.Caption := 'response: ' + IntToStr(i);
140+{$ENDIF}
141+```
128142
129143このコードは、Mandriva Linux 2005とDamn Small Linux 1.5上で、Lazarus 0.9.10を使って、自作のISAカードで\$0220にアクセスしてテストしました。
130144
131145### 一般的なUNIXでのハードウエアアクセス
132146
133147 {$IFDEF Unix}
134148 Uses Clib; // retrieve libc library name.
135149 {$ENDIF}
136150
137151 {$IFDEF Unix}
138152 function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external clib;
139153 {$ENDIF}
140154
141155**注意** FPCはin [[doc:rtl/x86/index.html|unit x86で]]"fpioperm"よ呼ばれる抽象的な機構を提供しています。そして、入出力機能を定義しています。 これらの関数はx86で動作するLinuxとFreeBSDで実装されています。
142156
143157配布と関数のポータビリティのため、必要な抽象化なしにlibcをリンクすることは推奨されていません。libcの手動リンク(つまり、どこからでも使えるように、libcをad hoc宣言をする方法)をおこなうことは推奨されません。
144158
145159(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). 訳注:うまいこと訳せないので、和訳せず、そのままのこしておきます。)
146160
147161**注意2** _unit_ libcを使うことはどんな状況下でもKylixの互換性の点では推奨されません。このユニットは相対的にポータブルではないからです。(due to excessive exposure of structures and other private symbols)
148162
149163そして、Kylixの互換性の問題からは、なるべく少なく変更すべきです。
150164
151165## シリアル通信
152166
153167[[Hardware Access/ja|外部リンクセクションにUNIXとWindowsのシリアルポートチュートリアルがあります]]。
154168
155169## 外部リンク
156170
157171通信プロトコルスピードの比較:
158172
1591731. <http://en.wikipedia.org/wiki/Serial_port#Speed>
1601742. <http://www.lvr.com/jansfaq.htm> - Jan Axelson's Parallel Port FAQ
1611753. <http://en.wikipedia.org/wiki/USB#Transfer_Speed>
1621764. <http://en.wikipedia.org/wiki/PCI#Conventional_PCI_bus_specifications>
163177
164178シリアル通信のリンク:
165179
1661801. On UNIX: [1](http://www.easysw.com/~mike/serial/serial.html)
1671812. On Windows: <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnfiles/html/msdn_serial.asp>
1681823. Synaser component: <http://synapse.ararat.cz/>
169183
170184ISA デジタルオシロスコープ - 全ソースが含まれるハードウエアのアクセス例:
171185
172186[2](http://eletronicalivre.incubadora.fapesp.br/portal/english/oscilloscope/)
173187
174188---
175189*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