Arduinoで8x8ドットマトリクスLEDをつかって日本語を表示したいと思い、
美咲フォントを使おうと考えています。
この場合、次に列挙するハードウェア的、ソフトウェア的制約を解決する必要があります。
1)Arduino IDEでは文字のコード系にUTF-8を採用している。一方、美咲フォントは
JISコードで管理されている。
2)記憶領域の制約
Arduino UNO で使える内部記憶領域は、
フラッシュメモリ 32kバイト、SRAM 2kバイト、EEPROM 1kバイト であり
美咲フォント(半角・全角 7120文字) 56kバイトが格納できない。
コード系は何とかなるとして、フォントデータ格納領域は確保しなければなりません。
そこで、I2Cバスで接続するEEPROMに格納することにしました。
EEPROM は
AT24C1024B (容量 128kバイト 5V動作)を選択しました。
AT24C1024Bを使った回路図
回路図はデータシートおよび、先人さんのブログを参考にしました。
SLC、SDAのプルアップ抵抗に2.2kΩの抵抗を入れています。
パスコンとして、10μFの電解コンデンサを1つ入れています。
ACT24C1024Bは1つのみの利用で、デバイスアドレスは0x50で利用するため
A1とA2をGNDに接続して0、0とします。
当初、何故かデータが正常に読み書きできずハマりました。
プログラムでは、AT24C1024BからNAKが帰ってきて読み書きに失敗する現象が
発生し、一週間近く悩みました。
最終的に「とりあえず、パスコンを入れてみるか」と、VCCとGNDの間に
0.1μFのセラミックコンデンサを入れると読込ではACKが帰るようになり、
10μFの電解コンデンサに変えたら正常に動作するようになりました。
実際の回路
テストプログラム1)I2Cバスデバイスアドレスについて
データシートでは、デバイスアドレスは次のようになっています。

arduinoのI2Cライブラリ(Wire)では、デバイスアドレスとして7ビットを指定します。
その7ビットが1010[A2][A1][P0] に対応します。
このうち[A2][A1]はICのA2、A1ピンで指定します。回路ではGNDに接続しているので
0、0となります。
つぎに[P0]はページ指定となります。ACT24C1024Bの容量は128kバイトあります。
このメモリ領域をアクセスするには17ビット必要ですが、この17ビットの最上位が
このP0となります。
(ようするに、内部的には64kバイトのメモリが2つあって使いたい方の領域を、P0で
指定することになります)。
さらに[A2][A1]に異なる設定をすることで、ACT24C1024Bを最大4個つかうことが
できます。
2)メモリ領域のアドレス指定
[A2][A1][P0] 00000000 の19ビットで最大4つのACT24C1024Bを使った512kバイトの
連続空間を指定することができます。
19ビットの上位3ビットはデバイスアドレスで指定し、下位16ビットはI2Cライブラリの
アドレス指定で利用します。
3)書込み・読込み
データシートでは、1バイト単位の読み書きモードと、ページ単位の読み書きモード
があるようですが、今回は1バイト単位でのみテストします。
4)実際のテストプログラム
//
// AT24C1024B 書込/読込テスト
//
#include <Wire.h>
#define DEVICE_ADDRESS 0x50 // AT24C1024B I2Cデバイスアドレス
// 1バイト書込
// address: アドレス(19ビット 0x00000 - 0x7FFFF)
// [A2][A1][P0] + 16ビットメモリ空間
// data : 書込データ
//
void write(unsigned long address, byte data) {
uint8_t devaddr = (uint8_t)DEVICE_ADDRESS | (uint8_t)(address>>16);
uint16_t addr = address & 0xFFFF;
int rc;
Wire.beginTransmission(devaddr);
Wire.write((byte)(addr >> 8)); // アドレス上位
Wire.write((byte)(addr & 0xFF)); // アドレス下位
Wire.write(data);
rc = Wire.endTransmission();
#ifdef MyDEBUG
Serial.print("write Transmission rc="); Serial.println(rc,DEC);
#endif
delay(6);
}
// 1バイト読込
// address: アドレス(19ビット 0x00000 - 0x7FFFF)
// [A2][A1][P0] + 16ビットメモリ空間
//
byte read(unsigned long address) {
uint8_t devaddr = (uint8_t)DEVICE_ADDRESS | (uint8_t)(address>>16);
uint16_t addr = address & 0xFFFF;
byte data = 0xFF;
int rc;
Wire.beginTransmission(devaddr);
Wire.write((byte)(addr >> 8)); // アドレス上位
Wire.write((byte)(addr & 0xFF)); // アドレス下位
rc = Wire.endTransmission();
#ifdef MyDEBUG
Serial.print("read Transmission rc="); Serial.println(rc,DEC);
#endif
rc = Wire.requestFrom(devaddr,(uint8_t)1);
data = Wire.read();
#ifdef MyDEBUG
Serial.print("read request rc="); Serial.println(rc,DEC);
#endif
return data;
}
// 書込みテスト
// 取りあえず10バイトだけ書込み後、読んで値をチェックする
//
void write_test() {
unsigned long addr =0;
byte data;
Serial.println("Start Writeing test.");
for (int i=0; i< 10; i++) {
write(addr, (byte)i);
data = read(addr) ;
Serial.print("data="); Serial.println(data,DEC);
if (data != (byte)i) {
Serial.println("Error!");
}
addr++;
}
Serial.println("Done.");
}
void setup()
{
Serial.begin(19200);
Wire.begin();
write_test();
}
void loop() {
}
実行結果

読み書きは出来たので、次の課題は56kバイトの美咲フォントデータを
このEEPROMに書き込むことです。これについてはTeraTermのファイル送信機能を利用を
考えています。
最近のコメント