秋月電子通商で売られているUV-EPROMの NMC27C512AQ200 (I-11327) に書き込んでみる実験を行った。
仕様の確認
まずはこのデバイスの仕様を確認した。
NMC27C512AQ200
でググることで、データシートを入手できた。
データシートより、以下のピンがあることがわかる。
- VCC
- GND
- アドレス入力 A0~A15
- データ入出力 O0~O7
- ~OE/VPP
- ~CE
VCCに5Vを供給し、~OE/VPP と ~CE にLOWを入力すると、入力したアドレスに対応するデータが出力される。
また、書き込み(現在「1」になっているビットを「0」にする)は以下の手順でできることがわかる。
- VCCに6.25Vを供給する。
- ~OE/VPPに0Vを、~CEにHIGHを入力する。
- 書き込みたいアドレスそれぞれについて、以下を行う。
- 書き込むアドレスを入力する。
- 以下を繰り返す。
- 書き込む側のデバイスを出力モードにし、書き込むデータを入力する。
- ~OE/VPPに12.75Vを入力する。
- ~CEを100μsの間LOWにする。
- 書き込む側のデバイスを入力モードにする。
- ~OE/VPPに0Vを入力する。
- ~CEをLOWにする。
- データを読み取る。
- ~CEをHIGHにする。
- 読み取ったデータが書き込むデータと一致したら、繰り返しを終了する。
書き込みには6.25Vと12.75Vという電圧を用意することが要求されることがわかる。
指定の電圧の用意
今回は、5Vから16V程度に昇圧し、これを半固定抵抗で分圧してオペアンプに入力することで指定の電圧を用意することにした。
後にArduino向けシールドの形にすることを考えつつ、今回の実験用に以下の回路を作製した。
LM358Nは、EPROMが要求する電流が30mA程度のようだったので、40mA出せるとなっていたHTC製のもの (秋月 I-13213) を用いた。
オシロスコープ FNIRSI-1013D で確認した結果、~VPPEN を切り替えてから VPP の変化が完了するまで20μsくらいかかるようだった。
CH1が ~VPPEN、CH2がVPPを表す。
EPROMの出力電圧の確認
今回のEPROMのVCCに書き込み用の(約)6.25Vを供給した状態で、データ出力のHIGHの電圧をチェックすると、
VCCに供給した電圧に近い値となっていた。
また、出力端子を抵抗でGNDに接続すると、出力電圧が下がった。
抵抗値と出力電圧の関係は、以下のようになった。
抵抗値 [Ω] | 出力電圧 [V] |
---|---|
抵抗なし | 6.22 |
20k | 6.17 |
10k | 6.12 |
5k (10kを2本並列) | 6.02 |
1k | 5.32 |
510 | 4.66 |
約6.25Vの電圧を5Vで動作するマイコンに入力することは、規定の最大入力電圧を上回る場合があり、避けるべきであると考えられる。
そのため、EPROMの出力電圧を以下のように抵抗で分圧してマイコンに入力するのがいいだろう。
EPROMの出力電圧が6.25Vのとき、このように3.3kΩと10kΩの抵抗を使うとマイコンへの入力電圧は約4.7Vとなる。
実験結果より、10kΩ以上の抵抗を使うことで、今回のEPROMの出力電圧の降下は小幅に抑えられるだろう。
また、マイコンの出力をEPROMに入力する場合、EPROM側はハイインピーダンスとなっているため、
マイコンの出力電圧がほぼそのままEPROMに入力されるはずである。
今回のEPROMの入力のHIGHの電圧の最小は2.4Vなので、5Vを入力して問題ないだろう。
EPROMへの書き込み
今回は、USB Micro-Bに対応したArduino UNO互換機のMaker UNO (秋月 M-16285) を用いてEPROMへの書き込みを行った。
マイコン・電圧生成基板・EPROMなどを以下のように配線した。
抵抗は手元にあるものを使用したため、EPROMの出力を分圧する抵抗が前述の「3.3kΩと10kΩ」と異なっている。
今回は簡単のため、アドレスは(とりあえず)下位3ビットのみを手動で切り替える形とし、
書き込むデータは1ビットのみとした。
使わないアドレスはHIGHを入力し、データは抵抗を介してHIGHにプルアップした。
配線の手間を減らすため、隣り合うピンへの同じ値の入力がやりやすくなる以下の配線具を作製・使用した。
データの読み込み機能と書き込み機能を持つ以下のスケッチを作成し、マイコンへ書き込みを行った。
データの読み書きを行うスケッチ
// 3 -> CE
// 4 -> ~VPPEN
// 5 -> data
// commands
// r : read data
// w : write zero
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, INPUT);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
Serial.begin(9600);
}
void loop() {
int c = Serial.read();
if (c == 'r') {
// read data
digitalWrite(3, LOW); // CE = LOW
delayMicroseconds(10);
int data = digitalRead(5); // read data
digitalWrite(3, HIGH); // CE = HIGH
delayMicroseconds(10);
Serial.print("data read = ");
Serial.print(data);
Serial.println();
} else if (c == 'w') {
const int maxtry = 25;
for (int i = 1; i <= maxtry; i++) {
// write zero
digitalWrite(4, LOW); // enable VPP
delayMicroseconds(50);
pinMode(5, OUTPUT); // set data to write
digitalWrite(5, LOW);
delayMicroseconds(10);
noInterrupts(); // send CE pulse
digitalWrite(3, LOW);
delayMicroseconds(97);
digitalWrite(3, HIGH);
interrupts();
delayMicroseconds(10);
pinMode(5, INPUT); // unset data
delayMicroseconds(10);
digitalWrite(4, HIGH); // disable VPP
delayMicroseconds(50);
// verify
digitalWrite(3, LOW); // CE = LOW
delayMicroseconds(10);
int data = digitalRead(5); // read data
digitalWrite(3, HIGH); // CE = HIGH
delayMicroseconds(10);
Serial.print("try ");
Serial.print(i);
Serial.print(" / ");
Serial.print(maxtry);
Serial.print(" data read = ");
Serial.print(data);
Serial.println();
if (data == 0) {
Serial.println("success!");
break;
}
}
}
}
オシロスコープで確認した結果、 digitalWrite
と delayMicroseconds
によりパルスを生成すると、
delayMicroseconds
に渡した時間より3μs程度長くなるようだったので、その分書き込み用のパルスの設定を3μs減らした。
(パルスの長さの規定は95~105μsなので、97μsでも規定内である)
さらに、繰り返しパルスを生成してオシロスコープで観察すると、時々パルスの長さが伸びる時があった。
そこで、 noInterrupts
と interrupts
により対策を行った。
このスケッチを用い、読み込み → 書き込み → 読み込み を行った結果、
書き込みに成功し、0が読み込まれるようになるのが確認できた。
この実装で今回のEPROMへの書き込みが行えることがわかったので、
プログラムによるアドレスの指定を実装したり、1ビットだけでなく8ビット全てを書き込むようにしたりすることで、
より実用的な書き込みも行えるようになると考えられる。
投稿者の人気記事
-
mikecat
さんが
2022/03/06
に
編集
をしました。
(メッセージ: 初版)
-
mikecat
さんが
2022/03/06
に
編集
をしました。
(メッセージ: トップの画像を追加)
ログインしてコメントを投稿する