H8/3048/3052を使って、I2C−BUS仕様のEEPROMをイエローソフト(YellowSoft)で、ソフトウェアを組んでみました!
|
H8/3048/3052は、弊社の多目的マザーボードを仕様で説明していますが、秋月電子通商のAKI−H8でも簡単に構築できます。
|
ポイント! I2C−BUSを学ぶに当たって、ローム社のBR24L64シリーズのマニュアルが解りやすかったです。
尚、このソフトの使用は自由ですが、動作の責任は一切、負い兼ねます。
また、リンクを貼る際は、御一報下さい。
|
I2C−BUSとは
|
I2C−BUSとは、フィリップス社が提唱した通信方式で、SCL(Serial
CLock)と、SDA(Sirial DAta) の2本の信号から成っています。
SCLの立ち上がり、立ち下がり時に、SDAの状態で、入力モードや出力モードなどを決定するので、通常のメモリのRD、WR端子が無いため
少し複雑なロジックタイミングですが、一度取り入れれば、2つのポートだけで、128個のI2C−BUS仕様のチップを制御する事が出来るので、非常に効率的で便利なものです。
|
注意点
|
1.接続
I2C−BUSは、パラレル接続ですので基本的には、プルアップ抵抗を用いてオープンドレインで接続していきます。
今回は、H8/3048/3052のポートを直接接続しますので、出力同士が衝突しない様に(メモリ側が、”L”出力時に、CPU側が”H”出力等)
ポートの出力は、”L”のみとして、ポートの入力で、プルアップ抵抗を利用して、”H”と定義しました。
2.プルアップ抵抗の定数の求め方 |
 |
回路図
|
|
※H8/3052の25MHzを用いて動作確認しましたが、3048でも、また、25MHz以下のクロックでも問題なく動作します。
但し、Vccは、5Vとしています。3Vでもこの速度では、 問題ないと思いますが、プルアップ抵抗に注意してください。 |
 |
|
ソフト仕様
|
このソフトウェアは、イエローソフト(YellowSoft)の
コンパイラ、YCH8 Ver.4.17を元に紹介しています。
I2C−BUS仕様のEEPROMのアクセスについて、簡単に、解りやすく、C言語で独特のポインタや構造体を
出来るだけ用いずに、他の言語より移り変わり安く、また、移植しやすく解説していきます。
(本人だけがそう思っているかも知れませんが・・・)
|
1.コンパイラの環境
・YellowSoftのデフォルト(標準のまま)で、基本的に説明します。
インクルードパスは、別にC:¥I2ceeprom¥includeを設定してください。
2.ここで使用するソフトは、次の4つのファイルに分かれています。
|
|
イエローソフト環境での一括ダウンロードです。
解凍後 C:¥へ配置してください。(c:¥I2ceepromのフォルダです)
標準インストールしていれば、後はインクルードパスを解凍後のフォルダ内の
「Include」を追加するだけで動くと思います。 |
I2CEEPROM.LZH |
圧縮ファイルを解凍後に、「R_w_test.s」をイエローソフトが無償で
提供している「FWRITE2」で、書き込んでみてください。
右より、ダウンロードできます。(’05−5現在) |
FWRITE2 |
|
それでは、実際のソフトウェアへと参ります・・・・
私のソフト紹介で多く使用する記述は、省略して記述する様にしています。
unsignd char → ucharなど、「3048_52.H」で宣言しています。
ST3048.ASMについて
- イエローソフトの説明同様、@〜Bを必要に応じて変更してください。
デフォルトでは、クロック25MHzで、38400bps仕様です。
16MHzでは、#21行目をコメントに、#22行目のコメント’;’を外す。
それ以外は、#12〜18行目の表を参考に #21、22行目をコメントにして、
同じように値を入れてプログラムを加えると良い。
3048_52.Hについて
- ルネサステクノロジのハードウェアマニュアル、H8/3048/3052の
レジスタ名に合わせて宣言しています。
また、変数と区別するため、ソースファイルでは、’*’を付けて大文字で使用します。
MAIN.Cについて
- ここでは、I2CEEPROM.Cの関数(サブルーチン)を呼び出し、32バイトのデータを
書き込んで、またそのデータを読み出し、一致確認しています。
その一致内容が解る様に、RS−232Cを使って、状況を送信するものです。
通信は、調歩同期、19200kbps、8ビット、ストップ・1、パリティ・なしです。
RS−232Cが使用できない場合は、次の様な方法でビットに出力する方法もあります。
if (i == 32){
transsmit_1(ok_eep,28); /* 最後まで一致すれば、Good送信 */
*PBDR |= 0x80; /* 〃 ポートBのbit7’H’ */
}
else{
transsmit_1(ng_eep,28); /* 一致しなければ、N.G.送信 */
*PBDR &= ~0x80; /* 〃 ポートBのbit7’L’ */
}
※但し、予めポートのイニシャライズ時に、ポートBのbit7を出力にする必要があります。
*PBDDR = PB_DDR = 0x80; /* *PBDDR = PB_DDRとするため */
I2CEEPROM.C
- デバイスアドレスは、全て’0’としていますので、変更が必要なら、
static void eepstart(uchar rw)の最終行の 0xA0の値を変えてください。
- ここでは、Microchip社のM24LC256を使用して説明していますが、他社製品や
これよりも容量の小さいメモリにも対しています。
通常、このメモリは書き込みページとして、64バイト単位ですが、他のメモリで
32バイトタイプが多いので、1ページを32バイトとして説明しています。
また、アドレス設定ではなく、ページの指定としてページ単位のアクセスをします。
つまりは、256kbitでは、0〜7FFFhのアドレス空間であり、A0〜A14で示されます。
その内、A0〜A4が32バイト空間で、1ページになります。
- ※×は、無効ビット 〇は、ページを指定する有効ビット ●は、32バイト一括書込可能ビット
A15 |
A14 |
A13 |
A12 |
A11 |
A10 |
A 9 |
A 8 |
A 7 |
A 6 |
A 5 |
A 4 |
A 3 |
A 2 |
A 1 |
A 0 |
× |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
● |
● |
● |
● |
● |
よって、各ページを指定するには、A5〜A14の10ビットで、
下位に詰めると、次の様になります。
A 9 |
A 8 |
A 7 |
A 6 |
A 5 |
A 4 |
A 3 |
A 2 |
A 1 |
A 0 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
〇 |
結果、256kbitのメモリでは、ページ指定は、0〜3FFhの範囲となります。
(因みに、64kbitでは、A0〜A7迄で、ページ指定範囲は、0〜FFhでとなります。)
この様に、ページ指定しているのは、アドレスを直接書き込んで、バイト単位で書き込むと、
ライトサイクルタイムが、非常に大きくなり時間がかかるためです。
それでは、実際のソフトについての説明です。
001 #include <3048_52.H>
002 #define SCL_H (*PBDDR = PB_DDR = PB_DDR &= ~4)
003 #define SCL_L (*PBDDR = PB_DDR = PB_DDR |= 4)
004 #define SDA_H (*PBDDR = PB_DDR = PB_DDR &= ~8)
005 #define SDA_L (*PBDDR = PB_DDR = PB_DDR |= 8)
006 #define WR_CYC 5000 /* ページ書き込み後の待ち時間 5mS以上 */
007 #define CYCLE 0 /* [SCL]パルス幅(約10uS) */
008 extern uchar PB_DDR; /* PBDDR値 変数 */
- 001行目の #include <3048_52.H>は、3048_52.Hの内容を
このファイルへ取り込む為の表記です。
この1行の変わりに、3048_52.Hの内容を全て書き込んでも同じ事です。
-
002〜005の#defineですが、「スペース」や「タブ」で区切った次のグループを@とし、
次の「スペース」や「タブ」で区切ったグループをAとすると、
「Aのグループの内容を今後、@と定義します」と、言った意味になります。
つまりは、「SCL_H;」と、記述するだけで、PB_DDRと、4の反転(11111011)の&を
PB_DDRと、PBDDRレジスタへ格納することになります。
他のビットはそのままで、ビット2のみ、クリアする内容です。
- 006行目は、WR_CYCLEを ’5000’としています。
これは、EEPROM書き込みのライトサイクルタイムで、データを書き込んだ後、
チップがライトモードになるため、待たなければならない時間です。
大体のチップは、5mSですので、6mS程待つ様に設定しています。
25MHzで、「5000」 16MHzでは、5000×(16[MHz]÷25[MHz])=3200です。
- 007行目は、CYCLEを ’0’としています。
これは、クロックの幅を決めるものであり、25MHz時で ’0’でも、10uSあります。
周波数にすると、50kHzなのでこのまま変更せず使用してください。
- 008行目は、メインで宣言した変数をこのファイルでも使用できる様にしています。
※何故、PBDDRレジスタに直接データを格納せずに、PB_DDR変数を使用するのか?
・それは、H8の、P*DRレジスタはデータを書き込み、そのままのデータを読み出す事が出来ますが、
P*DDRレジスタは、書き込んだデータは、読み出せず全て、’1’に成ってしまうため、
他のルーチンで、同じポートのビットを変化させても分からないのです。
よって、特定の変数に設定値を置く事によって、他のビット状態を把握でき、かつ状態を保持
する事が可能になるのです。
P*DDRレジスタは、全てこの様に使用する事を心がけると、ソフトの変更追加時も対応できるでしょう!
- 各、関数について
static void writeb(uchar dat) |
I2CEEPROM.C内部のみで使用する 1バイト書き込みの関数 |
static void readb(uchar *dat, uchar f) |
I2CEEPROM.C内部のみで使用する 1バイト読み出しの関数 |
static void eepstart(uchar rw) |
I2CEEPROM.C内部のみで使用するスタートコンディション |
void eepstop(void) |
通信終了時、イニシャル時に用いるストップコンディション |
void eepread(uint page, uchar *buf) |
MAIN()など、他の関数からページと読込先頭番地を指定して
呼び出すと、32バイトのデータを読み込める |
void eepwrite(uint page, uchar *buf) |
MAIN()など、他の関数からページと書込先頭番地を指定して
呼び出すと、32バイトのデータを書き込める |
void eepreset() |
イニシャル時やスタンバイより復帰の時などに使用
(各社の製品に使用できるかは確認していません) |
詳しくは、ソースを見てください。
|