マイコンのプログラミング

実験用CPUボードの概要

この演習では、写真のようなボードを使います。

このボードには、次のようなものが載っています。 (LED:える・いー・でぃー; Light Emitting Diode=発光ダイオード)

これらが、次の図のように接続されています。

まずはここでは、この全体構成図の詳細までみる必要はありません。 載っているLEDやスイッチなどが、CPUが実行する プログラムによって制御できるんだ、ということだけ、 頭に入れておいてください。

メモリマップドI/O

では、LEDやスイッチなどは、CPUが実行するプログラムからは どのように操作すればよいのでしょうか。

「CPUがプログラムを実行する」とは、メモリに入っている プログラム(作業手順書)を順に「読み出し」、解釈して 実行し、必要に応じて結果をメモリに「書き込む」こと、 と言うことができます。

そしてメモリから命令やデータを読み書きするときには、 メモリの中の場所を「アドレス(address)」という数値によって 指定をするのでした。

このボードでは、LEDやスイッチなどの、入出力装置(Input/Output; I/Oと略記します)も、この「メモリに対する読み書き(アクセス)」と 同様に行うことができるようになっています。 このような仕組みを メモリマップドI/O (Memory-mapped I/O)と呼びます。

具体的には、それぞれのI/O装置が、次のように 割り当て(memory-mapped)されています。
I/O装置 アドレス(16進数表記) アクセス方法
7セグメントLED(0桁目) 0x4000番地 書き込み
7セグメントLED(1桁目) 0x4001番地 書き込み
7セグメントLED(2桁目) 0x4002番地 書き込み
7セグメントLED(3桁目) 0x4003番地 書き込み
スイッチ(8個) 0x4004番地 読み出し
LED(8個) 0x4005番地 書き込み
ちなみに0x***という表記は、***が16進数であることを表すC言語風の表記です。 つまち0x4000とは、16進数で「4000」であることを表します。(よんせん、ではない)

例えば、0x4004番地を「読み出す」と、スイッチの状態がわかり、 0x4000番地に数値を「書き込む」と、7セグメントLEDの0桁目(右端)の 表示を設定できる、というわけです。

なお、書き込み用のものを読み出そうとしても、 正しい値を読み出すことはできません。 つまり右端の7セグメントLEDに表示されている値を調べようと思って、 次のような記述をしても、正しい値は得られません。 (正しくない値が代入される可能性が高い。 偶然表示されている値が得られることもあるが、 得られないことも多い。)

  i = num0; /* NG (read)  */

LED・SWの操作

メモリマップドI/O装置は、プログラムを書くときには次のような 表記によって、「変数」として定義をすることになっています。 (volatile, BYTE xdata, _at_は「おまじない」と思っておいてかまいません。)
volatile BYTE xdata num0       _at_ 0x4000;  // 0 digit of 7seg.LED
volatile BYTE xdata num1       _at_ 0x4001;  // 1 digit of 7seg.LED
volatile BYTE xdata num2       _at_ 0x4002;  // 2 digit of 7seg.LED
volatile BYTE xdata num3       _at_ 0x4003;  // 3 digit of 7seg.LED
volatile BYTE xdata sw         _at_ 0x4004;  // SWs
volatile BYTE xdata led        _at_ 0x4005;  // LEDs
例えば、「led」というBYTE型(1バイト=8ビット)の変数が 0x4005番地に割り当てられています。 この0x4005番地の内容は、先のとおり「LED(8個)の点灯・消灯を決める メモリマップドI/O」でした。 そのため、変数ledに値を書き込むと、実際には0x4005番地に 書き込まれ、結果としてその値に応じて各LEDが点灯・消灯することに なります。 なおここで、変数ledの値は1バイト=8ビット、つまり 8組の「0または1の値」ですが、 その各桁が、8個のLEDそれぞれの点灯・消灯に対応していることに 注意しましょう。

例えばこの変数ledに、次のように値0x81を代入するとします。

  led = 0x81;
ここで代入している値0x81は、2進数で書くと"10000001"ですから、 値が1になっている、一番左端のLED(LED7)と一番右端のLED(LED0)のみが 点灯し、それ以外は消灯することになります。

同様に例えば、 1バイトの変数swの値を読み出すと 8個のスイッチそれぞれの状態がわかることになります。 つまり8ビットのそれぞれが8個のスイッチに対応し、 最上位が左端のSW7、最下位が右端のSW0の値をあらわし、 各スイッチが押されていれば、その桁(ビット)の値が1に、 押されていなければ0になります。 そこで、例えばSW3の値をif文で調べたければ、 次のように書けばよいでしょう。

  if ((sw & 0x08) != 0){
    ..

プログラムの作成・編集・コンパイル

では早速、実際に実験ボード上でプログラムを実行し、 スイッチやLEDを操作してみましょう。

まず実験用のフォルダを作成します。 マイコンピュータ→Zドライブの中、または、「マイ ドキュメント」の中に、 実験第1用のフォルダを作成します。 今後の作業はすべてこの中で行うことにします。 なお、「Zドライブ」または「マイ ドキュメント」に置いたファイルは どのパソコンでも共有されます。

まず、先ほどのフォルダ内に、適当な名称で、これからの作業用の フォルダを作成します。 そこにサンプルプログラムとして、 sample.csample.Uv2 をダウンロードします。 今後、別のプログラムを作成するときは、適宜別のフォルダを作成し、 その中にこの2つをダウンロードして、それを編集するようにします。 また、作成したプログラムを残しながら、かつ、それを変更していきたい場合には、 フォルダをまるごとコピーします。 単にsample.cをコピーして、 コピー先の新しいファイルを編集しようとしてもうまくいきません

その中にあるsample.Uv2の次のアイコンをダブルクリックすると、 コンパイラなどが統合された開発環境uVision2が起動します。


この左側のウインドウ内の、Target1→SourceGroup1と順に +マークをクリックすると、sample.cが見つかるはずですので、 それをダブルクリックすると、右側のウインドウに、 プログラムsample.cの内容が表示されます。

#include "Fx2.h"
#include "Fx2regs.h"

// definition of memory-mapped I/O devices and external memories
volatile BYTE xdata num0       _at_ 0x4000;  // 0 digit of 7seg.LED
volatile BYTE xdata num1       _at_ 0x4001;  // 1 digit of 7seg.LED
volatile BYTE xdata num2       _at_ 0x4002;  // 2 digit of 7seg.LED
volatile BYTE xdata num3       _at_ 0x4003;  // 3 digit of 7seg.LED
volatile BYTE xdata sw         _at_ 0x4004;  // SWs
volatile BYTE xdata led        _at_ 0x4005;  // LEDs

main()
{
  // initialization
  CKCON |= 0x07; OEE = 0xef;
  led = 0; num0 = 10; num1 = 10; num2 = 10; num3 = 10;

  while(1){
    // write your code here
  }
}
最後のほうに、while文がありますが、while(1)ですので、 {}内が無限ループになっています。 そこでこの{}内に、実行するべきプログラムを書くことにします。 今回は、例として次のように書いてみましょう。
  while(1){
    // write your code here
    led = sw;
  }
プログラムを記述したら、保存した後、 メニューからProject→Build Target(F7)を 選んで、プログラムのコンパイルを行います。 (ファンクションキーのF7を押してもかまいません) コンパイルの過程が下のウインドウに表示されますので、 エラーなどがないか確認します。

プログラムの転送・実行

無事コンパイルが完了したら、 ボード上のCPUに転送し、実行させます。

ボードとパソコンのUSBポートをケーブルで接続します。 (このとき、最初だけドライバのインストールが行われることがあります) このとき、8個のLEDのすべてまたは一部が点灯することがありますが、 ここでは気にしなくてかまいません。

その後、 デスクトップ上にある"EZ-USB Control Panel"をダブルクリックして EZ-USB Control Panel(以下、ControlPanelと略記)を起動します。 起動すると、次のような画面になっているはずです。 なおControlPanelの中央上の「Target」のところが"FX2"となっていることを 確認しておいてください。

もしこのようになっていないときや、"No EZ-USB Device Found"と 表示されるときは、 ボードの接続を確認し、[Open All]ボタンを押してみましょう。

続いて、コンパイルしたプログラムを、ボードに転送します。 [Download]ボタンを押すと、転送するプログラムファイルを選ぶ 画面が現れますので、さきほど作成したフォルダ内の sample.hexを選択します。

すると転送が行われ、直ちにプログラムの実行が開始されます。

なお2回目以降プログラムを転送するとき、 同じプログラムファイルを修正しただけであれば、 uVision2でコンパイル後に、ControlPanelで[Re-Load]ボタンを 押すだけで転送・実行が行われます。 (つまり毎回転送するプログラムファイルを選択する必要がない) ちなみに[HOLD]ボタンでCPUをリセットさせることができます。 また[RUN]ボタンで、プログラムの実行を停止・再開することができます。

演習

このプログラムの動作を確認し、その動作原理を理解しましょう。 (ヒント:スイッチSW0〜SW7を押してみる)

7セグメントLEDの操作

ボード上にある4個の7セグメントLEDは、4桁の数値を表示することが できますが、これらは、CPLD(Complex Programmable Logic Device)と 呼ばれるIC(集積回路)による専用の制御回路によって 制御されています。

そしてプログラム側から見えるのは、 それぞれの桁に表示させたい値(0〜9)を、 それぞれのメモリマップドI/Oのアドレスに書き込むだけで その値が表示されます。 例えば0桁目に「3」と表示させたければ、 次のように記述すればよいことになります。

  num0 = 3;
なお書き込む値が0〜9の範囲外のときは、数値が表示されません。 また前述のように、値を読み出すこともできません。

演習

-9999〜9999の値を表示させるプログラムを記述し、 いろいろな数値を表示させて動作を確認しましょう。 絶対値を4個の7セグメントLEDに表示させ、 符号 (±) はLEDから判別できるようにします。 例えば、マイナスであればLED7が点灯し、 プラスであれば消灯するようにします。 int型の変数から符号と各桁の値を計算し、 それらを表示させるようにします。 int型の引数を持つ関数を
void ShowInt(int d)
{
  // write your code here
}
のように作成しておくと、後で再利用できるので便利です。

ヒント:

演習

0〜9999の値を順に表示するプログラムを記述してみましょう。 数値を増加させるタイミングは、(1)一定時間ごと、および (2)スイッチによって制御、の2通りを実装してみましょう。 ((2)では、例えばスイッチSW0を押している間は数値が増加する、 あるいはスイッチSW0を押している間は1ずつ増加、 SW1を押している間は10ずつ増加する、など)

ただし、 表示させる0〜9999の数値は 内部ではint型の変数一個に保持させることとし、 その変数の値から千の位〜一の位をそれぞれ求め、 それらを7セグメントLEDに表示させることとします。

ヒント:

変数の型とビット数と数値の限界

変数にはchar型やint型などの「型」がありますが、 これはその変数に割り当てられたメモリのビット数に対応します。 例えば、一般にchar型は8ビット(1バイト)となります。

一般には、ある型が何ビット(何バイト)であるかは、一定ではなく、 CPUの種類や用いるコンパイラに依存します。 変数の型が何バイトであるかはsizeofという演算子で得ることができます。 「sizeof (データ型)」という式は、 「データ型」が必要とするバイト数を与えます。 「sizeof 変数名」は、「変数名」のバイト数を与えます。

このバイト数は、その変数に代入できる数値の限界に関係してきます。 例えば符号なし8ビット(unsigned char型)では0〜255の数値を表現できます。 代入できる数値の限界には、符号の有無も関係しています。 同じ8ビット(1バイト)であっても、 符号つき8ビット(char型)では-128〜127になります。 このように変数がプログラム中でとりうる値に 注意する必要があります。

演習

次のような記述を含むプログラムを実行し、 整数型char, short, int, longが それぞれ何バイトになるのかを確認しましょう。 また、整数型char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long型が とりうる値の範囲を求めましょう。
  num3 = sizeof(long);
  num2 = sizeof(int);
  num1 = sizeof(short);
  num0 = sizeof(char);

演習

とりうる値の範囲を超えた際にどのような結果が得られるのかを確認しましょう。 例えば、
  unsigned char x;
  char y;
である時に、
  x = 255;
  x = x + 1;

  y = 128;

  y = 16 * 17;

  y = 16 * 16;

  y = 16 * 15;

  y = 16 * 8;
などを計算してみましょう。

D/A変換器・A/D変換器

この節では、ディジタルシステムであるCPUボードが、 例えば2.1Vというようなアナログ値の電圧を扱うための デバイスとその扱い方をみていくことにしましょう。

I/Oポート

このボードに載っているCPUには、メモリやメモリマップドI/Oに対する アクセス以外にも、1ビットのディジタル値(0または1)に応じた 電圧(1=高い電圧3V、0=低い電圧0V)を出力するための I/Oポートという端子があります。 このEZ-USB FX2にはポートA(PA)からポートE(PE)までの5種類の I/Oポートがあり、それぞれのポートは8本(8ビット)の0または1の値を 出力、あるいは入力できるピンから成り立っています。 もちろんその出力したい値、または入力した値は、 プログラムで設定したり、読み出したりすることができます。 ここでは、ポートE(PE)を使ってみることにしましょう。

I/Oポートを使用するときには、プログラムの最初に、 各ピンを入力あるいは出力のどちらとして使用するかを 設定する必要があります。 この設定はOEE(Output Enable E)という特殊な変数(実際には メモリマップドされた1バイト変数)に値を書き込むことで行います。 具体的には、出力として使用したいピンの桁を1、 入力として使用したいピンの桁を0とした8ビットの2進数(1バイト)の 値を設定します。

演習

ポートE(PE)の0番(PE0)、PE1、PE6、PE7だけを出力、 残りのPE2, PE3, PE4, PE5を入力として使うときに OEEに書き込むべき値はいくつになるでしょうか。

I/Oポートの操作

I/Oポートの各ピンに0または1の値を出力したり、 入力ピンの値を読み取るためには、IOEという特殊な変数を用います。

例えばPE0が出力として設定されているとして、 IOEの0ビット目を1にすると、PE0の値が1(つまり高い電圧3V)となります。

逆にPE3が入力として設定されているとすると、 IOEの3ビット目を読み取ると、PE3に加えられている電圧が 高い(3V=1)か低い(0V=0)かを知ることができます。

ビット演算・シフト

このように特にI/Oポートを操作するときには、特定のビットのみを 1または0にしたり、特定のビットの値のみを知る必要が生じます。 このようなときには、ビット演算と呼ばれる方法が便利です。

ビット操作は、AND演算子(&)やOR演算子(|)やNOT演算子(~)を用いて 変数の中の特定のビットのみを操作する技法で、 例えば次のような記述によって行うことができます。
変数aの0ビット目(最下位ビット)のみを1にする a = a | 0x01;
変数aの2ビット目のみを1にする a = a | 0x04;
変数aの4ビット目のみを0にする a = a & ~0x10;
変数aの6ビット目が0であるかを調べる (a & 0x40)==0
また数ビットだけ左または右にシフトするための 演算子として、「<<」と「>>」があります。 例えば「a >> 1」は、変数aの値を1ビットだけ右にシフトした 値をあらわすことになります。 したがって例えば a = 0x32; であれば、 「a >> 1」は0x19となることになります。 なお、「a >> 1」自体は、変数aの値を1ビット右にシフトした値を計算しますが、 変数aに格納されている値自体は変化させないことに注意してください。

演習

これらのビット演算・シフト演算の内容を理解しましょう。 ビット演算やシフト演算を行った結果をLEDに表示させるプログラムを 作成、実行してみると良いでしょう。

演習

unsigned char型変数 (8ビット) の値を調べ、 上位ビットから順に0であるか1であるかを LEDに表示するプログラムを作りましょう。

D/A変換器のいじり方

アナログ値の電圧を出力するための装置を D/A変換器 (Digital-to-Analog Converter)と呼びます。 このボードには、TLV5626という型番のD/A変換器が載っていますので これを扱うことにしましょう。

このD/A変換器の扱い方を知るためには、 D/A変換器TLV5626のデータシートを 読むことになります。 要点は、次のようなことになります。

p.6の図1を見ると、D/A変換器TLV5626に与えるデータは 1ビットずつ、D15からD0までの16個を、この順に SCLKに変化にあわせて与えること、そして最初に/CSを0にし、 最後に/CSを1にすること、を読み取ることができます。
p.6の図1の解説
具体的には、
  1. /CS=1, SCLK=1の状態から始める
  2. まず/CS=0とする
  3. 最初のデータ(ビット)をDINに設定し、SCLK=0とする
  4. 少し待つ
  5. SCLK=1とする
  6. 少し待つ
  7. 3.〜6.を16回繰り返す
  8. /CS=1とする

つまりD/A変換器TLV5626へのデータの転送は16ビット(2バイト)を 単位として行うことになります。

そして送るべきデータは、次の2組の16ビット(2バイト)となることが 記述されています。

(この動作はD/A変換器の設計者が決めた「仕様」です。) ここで「出力値」とは、D/A変換器から出力したい電圧を示す数値で、 次のような対応関係となっています。
出力値 出力電圧[V]
0 0.00
.. ..
128 2.048
.. ..
255 4.096
つまり出力値=0(0x00)の0.00V、出力値=255(0xff)の4.096Vが両端で、 その間は、出力値と出力電圧が比例していることになります。 つまり出力値xに応じた出力電圧は、 (x ÷ 255) × 4.096 [V]と表すことができます。

この「出力値」を、上位4ビットと下位4ビットにわけ、 D/A変換器に送ることになるわけですが、 例えば値0x12を送る場合には、2回目の転送で 次のような2バイトを送ることになります。

演習

出力値0x12をD/A変換器に送るとき、 送るべき2バイトのデータがこのようになることを確認しましょう。

(ヒント:出力値が、どのように2バイトのデータに埋め込まれているか、 を考えるのがポイント。 1バイト目の上位4ビット (16進数の上位桁) 「0xc」は、 おまじないと考えてかまいません。 何故「0xc」になるのかを考える必要はありません。)

D/A変換器への値の転送プログラム

D/A変換器を操作する、次のような3つの関数があった仮定をしましょう。 この3つの関数を使うと、D/A変換器から出力値d(d=0x00〜0xff)の電圧を出力する ためには、次のようなプログラムを記述すればよいことになります。 (わかりやすいように日本語でコメントを書いてありますが、 実際のエディタでは日本語は文字化けします。)
void DACwrite(unsigned char d)
{
  /* 内部参照電圧を設定するおまじない */
  CS_DAC(1); CK(1); /* 初期状態 */
  CS_DAC(0);
  DACwrite_byte(0xd0); DACwrite_byte(0x02);
  CS_DAC(1);

  /* 出力値dに対応する電圧を発生させる */
  CS_DAC(0);
  DACwrite_byte(0xc0 | (d >> 4));
  DACwrite_byte(d << 4);
  CS_DAC(1);
}
なお「>>」は、指定したビット分だけ右にシフトする演算子で、 例えば"0x53 >> 4"は0x05となります。 同様に「<<」は、指定したビット分だけ左にシフトする演算子です。

演習

このプログラムの動作を解読して、 D/A変換器から出力値dに対応した出力電圧が得られることを確認しましょう。

(第1日目はこのあたりまでを目安とするとよいでしょう。 もっと先まで進んでおくと第2日目が楽になります。)


D/A変換器の操作

先ほどののI/Oポート操作とビット演算を用いると、 D/A変換器TLV5626を操作するための、最低限の関数を 記述することができます。 D/A変換器TLV5626は、最終的には、SCLK, DIN, /CSという3本の信号線で 制御されますが、 これらは、次のような対応で、ポートEの各ピンに接続されています。 そこで、これらの値を0(低い電圧0V)または1(高い電圧3V)とするための 関数を次のように記述しておくと便利でしょう。
/* CK(d): D/A変換器のSCLKをd (d=0 or 1)に設定する関数 */
void CK(char d)    {if (d == 1) IOE |= 0x01; else IOE &= ~0x01;}

/* CS_DAC(d): D/A変換器の/CSをd (d=0 or 1)に設定する関数 */
void CS_DAC(char d){if (d == 1) IOE |= 0x04; else IOE &= ~0x04;}

/* DO_DAC(d): D/A変換器のDINをd (d=0 or 1)に設定する関数 */
void DO_DAC(char d){if (d == 1) IOE |= 0x08; else IOE &= ~0x08;}

演習

これらの関数・ビット演算子などを活用し、 D/A変換器に出力値dに対応した電圧を出力するための 関数void DACwrite(unsigned char d)を完成させましょう。 CK(), CS_DAC(), DO_DAC()は前述の通りです。 関数void DACwrite_byte(unsigned char d) の中身を作成します。

演習

D/A変換器に出力する電圧をスイッチで制御でき、 またそのときの出力値を7セグメントLEDに数値として表示するプログラムを記述し、 実行させてみましょう。 (例えば電圧値が、スイッチSW0を押すと1ずつ増加、SW1を押すと10ずつ増加、 SW2を押すと1ずつ減少、SW3を押すと10ずつ減少する、など) D/A変換器から出力される電圧は、ボード上の「Aout」端子に現れます。 テスターを用いて、 こことGND(グランド=基準電圧)との間の電圧を計測して記録しましょう。 テスター接続用ケーブルを使用すると便利です。

A/D変換器

アナログ値の電圧を、ディジタル値に変換し、コンピュータに 取り込むための装置をA/D変換器 (Analog-to-Digital Converter)と呼びます。 このボードには、TLC548という型番のA/D変換器が載っていますので これを扱うことにしましょう。 このA/D変換器は、 与えられたアナログ電圧を 次のような1バイトのディジタル値に変換する ことができます。
与える電圧[V] 変換値
0.0 0x00
.. ..
2.5 0x80
.. ..
5.0 0xff
このA/D変換器の扱い方を知るためには、 A/D変換器TLC548のデータシートを 読むことになりますが、要点は以下のとおりです。 p.3の図を見ると、A/D変換器TLC548に与えるデータは、 /CS=1の状態から始めて、 まず/CS=0とした後にクロックCLOCKを0→1の変化を8回与え、 その後/CS=1とします。 そしてしばらく待ち、 再び/CS=0とした後でCLOCKの0→1の変化を8回与えながら、 A/D変換器から出力されてくるDATAOUTを1ビットずつ読み取り、 最後に/CS=1とすることになります。 このA/D変換器がディジタル値に変換した値は1バイト(8ビット)の 数値で、DATAOUTに最上位ビット(B7)から最下位ビット(B0)の順に 現れることがわかります。
p.3の図の解説
これらの3つの信号線は、ポートE(PE)に以下のように接続されています。 このうちDATAOUTが接続されているPE4だけは、 A/D変換器から出力される値を読み取る必要がありますから、 「入力」に設定する必要がありますが、 その他のPE0, PE1, PE2, PE3は「出力」と設定することにしましょう。

なお/CS=0の期間にCLOCKを8回与える箇所が2回ありますが、 この1回目でアナログ電圧をディジタル値に変換だけ行われ、その結果を2回目に読み出しているためです。 そのため必ず2回必要です。

演習

PEの各ピンの入出力を上記のように設定するためには、 OEEにどのような値を設定すればよいでしょうか。

A/D変換器の操作

上記のことをふまえ、D/A変換器およびA/D変換器を操作するために 最低限必要な5本の信号線の値を0(低い電圧0V)または1(高い電圧3V)に 設定したり、A/D変換器から出力される値を読み取るための 関数を、次のように定義しておくことにしましょう。
/* CK(d): D/A変換器のSCLKをd (d=0 or 1)に設定する関数 */
void CK(char d)    {if (d == 1) IOE |= 0x01; else IOE &= ~0x01;}

/* CS_ADC(d): A/D変換器の/CSをd (d=0 or 1)に設定する関数 */
void CS_ADC(char d){if (d == 1) IOE |= 0x02; else IOE &= ~0x02;}

/* CS_DAC(d): D/A変換器の/CSをd (d=0 or 1)に設定する関数 */
void CS_DAC(char d){if (d == 1) IOE |= 0x04; else IOE &= ~0x04;}

/* DO_DAC(d): D/A変換器のDINをd (d=0 or 1)に設定する関数 */
void DO_DAC(char d){if (d == 1) IOE |= 0x08; else IOE &= ~0x08;}

/* DI_ADC(): A/D変換器のDATAOUTを読み取る関数 */
char DI_ADC(){if ((IOE & 0x10) == 0) return(0); else return(1);}

演習

これらの関数・ビット演算子などを活用し、 A/D変換器に与えられている アナログ電圧を1バイトのディジタル値に変換した値を返す 関数unsigned char ADCread(void)を記述し、実行させてみましょう。 続いて、A/D変換器の入力に、先ほどのD/A変換器の出力を与え、 D/A変換器から適当なアナログ電圧を出力し、それをA/D変換器で 取り込んで、その値を7セグメントLEDなどに表示させて、 両者を記録して対応関係を調べましょう。 なおこのとき、D/A変換器の出力(Aout)とA/D変換器の入力(Ain)を 接続することになりますが、 この接続では テスター接続用ケーブル を用います。 テスター接続用ケーブルは、AoutとAinを接続し、 かつ、テスターでAoutの電圧を測定できるようになっています。

インバータの入出力電圧特性の計測

A/D変換器・D/A変換器を活用し、ディジタル論理ICである SN7404の入出力特性を計測してみましょう。

SN7404はインバータ(否定ゲート)が6個入ったICです。

このボードのVDDを電源電圧(+5V)、GNDをグランド(0V)に接続し、 INに与える電圧を変えたときにOUTに現れる電圧の 関係を調べてみることにします。

インバータでは、入力が0(低い電圧)のときには出力が1(高い電圧)、 入力が1(高い電圧)のときには出力が0(低い電圧)となるはずですので、 おおまかには次のようなグラフとなると考えられます (図の横軸はかなりいい加減です)。
インバータの入出力特性
そこでD/A変換器の出力である「Aout」をインバータのINに、 またインバータの出力をA/D変換器の入力である「Ain」に、 ケーブルを用いて接続します。

演習

D/A変換器に出力する電圧をスイッチによって制御し、 A/D変換器で読み取った電圧を7セグメントLEDに表示する プログラムを記述し、インバータSN7404の入出力特性を 計測してみましょう。 なお7セグメントLEDには、D/A変換器から実際に出力されている電圧と A/D変換器で読み取った電圧を、それぞれディジタル値から実際の電圧に 換算し、小数点以下1桁で表示をするよいでしょう。 なおインバータSN7404は、フラットケーブルで接続しますが、 接続する向き(VDD・GNDどうしが接続されているか、など)、 ケーブルがつながっている箇所などに注意します。

注意とヒント:


戻る