back Last Update 2000/1/24 誤字脱字の訂正; Update 1999/12/20 誤字脱字の訂正; New 1999/11/29=新規作成

C言語 - 外部とのデータ交換 ... inportb, outportb 命令

この Web page の利用方法は,
ここ...最低限のプログラム実行例... (Windows 版 Visual C++ を利用している人)
で確認しよう!!
もくじ

3.0 メモリの性質
3.1 特殊なメモリ - 入力ポート,出力ポート(入出力ポート)
3.2 入出力ポートの例(PIO,タイマ,A/Dコンバータ,D/Aコンバータ)
3.3 スイッチの入出力と,実用(風)プログラムの例
3.4 タイマと,実用(風)プログラムの例
3.5 A/D,D/A コンバータと,実用(風)プログラムの例
3.6 その他ちょっと実用的(風な)プログラムの例

この Web Page を作るに際し,下記の文献を参考にしました。
サイエンス社 NSライブラリ(4) ザ・C [第2版] -ANSI C 準拠- 戸川隼人 1997年



3.0 メモリの性質


注意
  1. コンピュータには,必ず CPU(中央演算装置)と,メモリが存在する。
  2. メモリにはアドレスが振られており, CPUから指定されたアドレスの情報をアクセス(読み書き)できる。
  3. 通常,アクセスの単位は,1バイト(=8ビット)である。
  4. 16ビットCPUの場合は,2バイト(=16ビット)を一度にアクセスすることも可能。
    32ビットCPUの場合は,4バイト(=32ビット)を一度にアクセスすることも可能。
    注意:8ビットCPUであっても, 16ビットや32ビットのように8ビットを超えるデータを扱うことは可能。 ただし,一つのデータを8ビットずつに分割処理するため,処理速度が遅くなる。
  5. たとえは C 言語で,「 a = b; (どちらも16ビット int とする)」 という代入文があったとするならば,それは次にしめす処理と同一である。
  • 上記の箇条書きでも触れたが, 変数の割当先は,何番地でもかまわない。 単に,必要なメモリ容量さえ確保されていればよい。
  • 通常,メモリIC一つには,何百万ビットものデータが記憶される。
  • メモリには,ROM と呼ばれる素子もある。 ROM とは Read Only Memory の略であり, データを読み込むことは可能だが書き込みが出来ないという素子である。 ROM は,電源を切っても情報を失わないし, 1ビットあたりの単価は普通のメモリよりも安価である。
    普通のコンピュータの場合, ROM には電源を入れて最初に走るプログラムを格納してある。 また,例えば組み込み用コンピュータのように, プログラムを書きかえる必要がないコンピュータの場合, 全てのプログラムが ROM に格納されていることがある。

    3.1 特殊なメモリ - 入力ポート,出力ポート(入出力ポート)


    注意
    1. コンピュータは,特殊なメモリを備えている。
    2. そのメモリは,入力ポート または 出力ポートと呼ばれるものであり, 入出力,I/O などと呼ばれる。
    3. I/O は,基本的には Read Only か,または Write Only である。
      • Read Only 型の場合,そのメモリのデータは,外部の信号によって決められる。
      • Write Only 型の場合,そのメモリのデータによって,外部の信号が変化する。
    4. 外部配線があることにより, コンピュータは外部信号とアクセスできる。 外部配線とつながっている I/O アドレスのことを, I/O ポートと呼ぶことがある。
    5. I/O は,普通のメモリと違う性質を持つ:
      • どのアドレスのデータが,どの情報につながっているか決まっている。
      • みんなが自由にそのデータにアクセスできると,システムがとまってしまう可能性がある。
      • ハードウエア的に,普通のメモリ空間と I/O空間を別にする場合がある。
    6. そのため,特殊な命令を使って I/O をアクセスする。
      • Turbo C ++ for MS-DOS の場合,次のようになる。
      • a 番地に 1 というデータを書き込む場合
        outportb(a,1);
      • a 番地の内容を読み込み,変数 b に代入する場合
        b=inportb(a);
    7. 通常,メモリIC一つには,何百万ビットものデータが記憶されるが, I/O 用のIC一つは、一つから 十数個のアドレス範囲分を受け持つ。 その理由は,入出力用のピン数が必要であり, 一つのICで大きな I/O 空間を占めることが出来ないからである。
    8. メモリアドレスは,通常 32ビットで指定されるのに対し, I/O アドレスは通常 8ビットから16ビット程度で指定される。
    9. 上記の図の場合,各アドレスへのアクセスによって何か行われるか考えよう。


    3.2 入出力ポートの例(PIO,タイマ,A/Dコンバータ,D/Aコンバータ)


    注意
    1. 3.1 節のような構成によって外部情報をアクセスすることはできるが, 実用的には更なる工夫がある。
    2. コンピュータは,もともと同じハードウエアであっても, プログラムさえ変えれば別の働きができた。 しかし,3.1 節のような構成にすると, 入力が 8( or 4)本,出力が 8( or 4)本 と決まってしまう。 もしも合計 16本の 入出力ピンがあるならば, 実行時に各ピンの働きを選択できると, コンピュータは自由度が増える。
      この要求に応えたのが,PIO ( = i8255) と呼ばれる IC である。
      I/O 空間のうち 4バイト分を,一つの PIO が受け持つ。
      入出力用のピンは24本 = 3バイト ぶん存在する。
      IC 内部に 1バイト = 8ビット のコントロールレジスタがあり, 実行時にその値を設定することにより, 24本ある各ピンを入力にも出力にも設定できる。
      なお,電源を入れた直後には, 24本の入出力用のピンは全て入力用に設定されている。
    3. I/O によってアクセスできる情報は, 単なるスイッチにとどまらない。
    4. たとえば,タイマICにより,時刻の情報を読み取ることができる。
    5. たとえば A/D コンバータを使うと, アナログ信号をディジタル化して読み込むことができる。
    6. たとえば D/A コンバータを使うと, ディジタル値をアナログ信号にして出力できる。


    3.3 スイッチの入出力と,実用(風)プログラムの例


    V-C

    #include ...; main() { int ai,ao; int b,i; ai=0x50; ao=0x60; while(1){ b=inportb(ai); if( ( (b && 1)!= 0) & ( (b && 2)!= 0) & ( (b && 4)== 0 ) ){ i=0; }else{ i=1; } outportb(ao, i); } }
    注意
    1. このプログラムは, 2人乗り自動車の室内灯の点灯制御プログラムである。
    2. ハードウエアは,3.1節の結線に準じている。
      ただし,
      • SW-a は,運転席ドアが閉じていることを示す。
      • SW-b は,助手席ドアが閉じていることを示す。
      • SW-c は,室内灯スイッチがonであることを示す。
      • LED-p を室内灯とみなすこととする。
    3. 室内灯が消灯する条件は,次の3行のすべてが満たされたときである。
      • 運転席ドアが閉じている ... SW-a == 1
      • 助手席ドアが閉じている ... SW-b == 1
      • 室内灯スイッチがoffである ... SW-c == 0
    4. if 文は,次のように書き換えてもよい:
      if( (b && 7)== 3 ){


    3.4 タイマと,実用(風)プログラムの例


    V-C

    #include <stdio.h> main() { int a; int h,m,s; a=0x70; // 略 h=inportb(a); m=inportb(a+1); s=inportb(a+2); printf("time = %d:%d:%d\n", h, m, s); // 略
    注意
    1. ここでは次の仮定をしてプログラムを作った。
      ・0070(16)番地からタイマICが組み込まれている
      ・+0 番地には時間のデータがはいる
      ・+1 番地には分のデータがはいる
      ・+2 番地には秒のデータがはいる


    3.5 A/D,D/A コンバータと,実用(風)プログラムの例


    V-C

    #include <stdio.h> main() { int a1,a2; int va,vb,vc,vd,vmax,vmean; int s; a1=0x80; a2=0x90; // 略 while(1){ va=inportb(a1); s=va; vmax=va; vb=inportb(a1+1); s=s+vb; if(vb>vmax){ vmax=vb: } vc=inportb(a1+2); s=s+vc; if(vc>vmax){ vmax=vc: } vd=inportb(a1+3); s=s+vd; if(vd>vmax){ vmax=vd: } vmean=s/4; if(vmax>vmean+20){ /* 一個所高温→火事!? */ printf("KaJiNoOSoReGaARiMaSu!\n"); outportb(a2, 0); }else if(vmean<36){ /* 摂氏18度以下 */ printf("SaMuIDeSu!\n"); outportb(a2, 40); }else if(vmean<40){ /* 摂氏20度以下 */ printf("ChoUDo DeSu!\n"); outportb(a2, 20); }else{ /* 摂氏20度を超える */ printf("TaKaME DeSu!\n"); outportb(a2, 0); } } // 略
    注意
    1. ここでは次の仮定をしてプログラムを作った。
    2. ・0080(16)番地から8bitの A/Dコンバータが組み込まれている
      ・+0 番地には A/D-a のデータがはいる
      ・+1 番地には A/D-b のデータがはいる
      ・+2 番地には A/D-c のデータがはいる
      ・+3 番地には A/D-d のデータがはいる
    3. 各A/Dコンバータは温度センサとつながっており,
      データが 0 の時は 0.0 ℃,
      データが 1 の時は 0.5 ℃,
      データが 2 の時は 1.0 ℃,
      データが 3 の時は 1.5 ℃,
      (略)
      データが 40 の時は 20.0 ℃,
      データが 41 の時は 20.5 ℃,
      (略)
      データが 100 の時は 50.0 ℃,
      という関係になっているとする。
    4. 0090(16)番地に 8bitの D/Aコンバータが組み込まれている
    5. D/Aコンバータはヒータとつながっており, D/Aコンバータの設定値とヒータの発熱量は、
      データが 0 の時は 0.0 kcal,
      データが 1 の時は 0.1 kcal,
      データが 2 の時は 0.2 kcal,
      (略)
      データが 40 の時は 4.0 kcal,
      データが 41 の時は 4.1 kcal,
      (略)
      という関係とする。


    3.6 その他ちょっと実用的(風な)プログラムの例

    工事中 //