1 FT24C128Aの概要
1.1 特徴
特長
● 低電圧・低消費電力動作:
● FT24C128A:VCC = 1.8V ~ 5.5V
● 64バイト・ページ書き込みモード。
● 部分ページ書き込み動作が可能。
● 内部構成:16,384 × 8ビット(128Kビット)。
● 標準的な2線式双方向シリアルインターフェース。
● ノイズ対策用シュミットトリガおよびフィルタ付き入力。
● セルフタイミング書き込みサイクル(最大5ms)。
● 1MHz(2.5~5V)、400kHz(1.8V)対応。
● 書き込み前の自動消去機能。
● ハードウェアによるデータ保護用ライトプロテクト(WP)ピン。
● 高信頼性:標準で100万回の書き換え耐性。
● 100年のデータ保持期間。
● 産業用温度範囲(-40℃~85℃)。
● 標準的な8ピンDIP/SOP/MSOP/TSSOP/UDFN Pbフリーパッケージ。
● 低電圧・低消費電力動作:
● FT24C128A:VCC = 1.8V ~ 5.5V
● 64バイト・ページ書き込みモード。
● 部分ページ書き込み動作が可能。
● 内部構成:16,384 × 8ビット(128Kビット)。
● 標準的な2線式双方向シリアルインターフェース。
● ノイズ対策用シュミットトリガおよびフィルタ付き入力。
● セルフタイミング書き込みサイクル(最大5ms)。
● 1MHz(2.5~5V)、400kHz(1.8V)対応。
● 書き込み前の自動消去機能。
● ハードウェアによるデータ保護用ライトプロテクト(WP)ピン。
● 高信頼性:標準で100万回の書き換え耐性。
● 100年のデータ保持期間。
● 産業用温度範囲(-40℃~85℃)。
● 標準的な8ピンDIP/SOP/MSOP/TSSOP/UDFN Pbフリーパッケージ。
1.2 構造
概要
FT24C128Aシリーズは、131,072ビットのシリアルEEPROM(電気的消去・書き換え可能読み出し専用メモリ)です。
本製品は、16,384ワード×8ビット(1バイト)の構成となっています。
低消費電力および低電圧動作が求められる用途向けに、独自の高度なCMOSプロセスを用いて製造されています。
パッケージは、標準的な8ピンDIP、8ピンSOP、8ピンMSOP、8ピンTSSOP、および8ピンUDFNが用意されています。
読み出しおよび書き込みの全機能へのアクセスには、標準的な2線式シリアルインターフェースが使用されます。
また、VCC動作範囲が1.8V~5.5Vと広いため、幅広い用途に対応可能です。
Packages

本製品は、16,384ワード×8ビット(1バイト)の構成となっています。
低消費電力および低電圧動作が求められる用途向けに、独自の高度なCMOSプロセスを用いて製造されています。
パッケージは、標準的な8ピンDIP、8ピンSOP、8ピンMSOP、8ピンTSSOP、および8ピンUDFNが用意されています。
読み出しおよび書き込みの全機能へのアクセスには、標準的な2線式シリアルインターフェースが使用されます。
また、VCC動作範囲が1.8V~5.5Vと広いため、幅広い用途に対応可能です。
Packages

| ピン名 | 内容 |
|---|---|
| A2,A1,A0 | スレーブアドレス |
| SDA | シリアルデータ入力 / オープンドレイン出力 |
| SCL | シリアルクロック入力 |
| WP | 書込保護 |
1.3 スレーブアドレス
スレーブアドレスは 7bit で表すことになっている。
D6~D3までは固定(1010)になっており、D2がA2端子、D1がA1端子、D0がA0端子の印加電圧に対応している。
このため、スレーブアドレスは0x50~0x57になり、8個の同じメモリーを搭載出来ることが判る。
D6~D3までは固定(1010)になっており、D2がA2端子、D1がA1端子、D0がA0端子の印加電圧に対応している。
このため、スレーブアドレスは0x50~0x57になり、8個の同じメモリーを搭載出来ることが判る。
| No | Control Code | A2 | A1 | A0 | Slave Address | |||
|---|---|---|---|---|---|---|---|---|
| D6 | D5 | D4 | D3 | D2 | D1 | D0 | ||
| 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0x50 |
| 2 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0x51 |
| 3 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0x52 |
| 4 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0x53 |
| 5 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0x54 |
| 6 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0x55 |
| 7 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 0x56 |
| 8 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0x57 |
1.4 I2C信号フォーマット
1.4.1 I2Cの信号線の回路
I2Cの信号線にはSDAとSCLがありますが、この信号線はSDA(データ線)とSCL(クロック線)の回路は、「オープンドレイン(またはオープンコレクタ)」と呼ばれる、2本の線をみんなで共有できるシンプルな仕組みでできています。
SDAは特にデータ線としての信号が入出力できようにするための回路になります。
回路は非常にシンプルで、主に以下の3つで構成されています。
プルアップ抵抗(外付けの抵抗)SDA線とSCL線にそれぞれ1つずつ配置され、電源(VCC)に繋がっています。
マスター(マイコンなど)の内部回路線を「Lo(接地)」に引き下げるためのスイッチ(MOSFETなど)を持っています。
スレーブ(FT24C128など)の内部回路マスターと同様に、線を「Lo」に引き下げるためのスイッチを持っています。
1.4.2 信号のフォーマットは
(1) スタート
(2) 制御バイト
(3) メモリー内アドレスHiバイト
(4) メモリー内アドレスLoバイト
(5) データバイト
(6) ストップ
(2) 制御バイト
(3) メモリー内アドレスHiバイト
(4) メモリー内アドレスLoバイト
(5) データバイト
(6) ストップ
1.4.3 ACK
書バイトの後ろに『ACK』と言うものがありますが、これは
2線式シリアルバス・プロトコルでは、アクノレッジ・ポーリング(ACKNOWLEDGE polling)と言います。
アクノレッジ・ポーリングは、自己タイミング方式の内部書き込み動作中に、書き込み(プログラミング)のステータスを確認するために使用できます。
有効な読み出しまたは書き込みアドレス・コマンドを発行した際、デバイスがまだ自己タイミング方式の書き込みモードにある場合、EEPROMは9番目のクロック・サイクルでアクノレッジ(ACK)を返しません。
簡単に言うと
デバイスに「次の仕事ができる?」と何度もノックして確認する動作です。
2線式シリアルバス(I2Cなど)では、信号の電圧が高い状態をHi、低い状態をLoと呼び、アクノレッジ(返事)の場面では以下のように言います。
Hi(ハイ)= NACK(ナック / 否定応答)
Lo(ロー)= ACK(アック / 肯定応答)
で示されます。
2線式シリアルバス・プロトコルでは、アクノレッジ・ポーリング(ACKNOWLEDGE polling)と言います。
アクノレッジ・ポーリングは、自己タイミング方式の内部書き込み動作中に、書き込み(プログラミング)のステータスを確認するために使用できます。
有効な読み出しまたは書き込みアドレス・コマンドを発行した際、デバイスがまだ自己タイミング方式の書き込みモードにある場合、EEPROMは9番目のクロック・サイクルでアクノレッジ(ACK)を返しません。
簡単に言うと
デバイスに「次の仕事ができる?」と何度もノックして確認する動作です。
2線式シリアルバス(I2Cなど)では、信号の電圧が高い状態をHi、低い状態をLoと呼び、アクノレッジ(返事)の場面では以下のように言います。
Hi(ハイ)= NACK(ナック / 否定応答)
Lo(ロー)= ACK(アック / 肯定応答)
で示されます。
ACKを出力したのは誰?
例として、スタートや制御バイトはマスターのMCU が出力しています。
さて次のACKは誰の信号か?
答えは、スレーブであるEEPROM(FT24C128)自身が出力した信号です。
マスター(マイコンなど)から送られてきたアドレスが自分自身のものと一致した場合、FT24C128がSDA線を「Lo」に引き下げることでACKを返します。
ACKになった事をマスターが知ることが出来るので、次の処理、メモリーの上位アドレスバイトを送ります。
なお該当するスレーブアドレスが無い場合は、誰も「Lo」に引き下げるスレーブがいないので、信号線は「Hi」状態なので、NACKだと言うことで、マスターによりその時の処理を実行させることになります。
NACKの場合の処理例としては表示器があるなら、赤ランプを点灯して「メモリーが検出されない」など表示させ、次の処理に移る(表示リセットスイッチ押し下げ処理含む)様にする。
など考えられます。
さて次のACKは誰の信号か?
答えは、スレーブであるEEPROM(FT24C128)自身が出力した信号です。
マスター(マイコンなど)から送られてきたアドレスが自分自身のものと一致した場合、FT24C128がSDA線を「Lo」に引き下げることでACKを返します。
ACKになった事をマスターが知ることが出来るので、次の処理、メモリーの上位アドレスバイトを送ります。
なお該当するスレーブアドレスが無い場合は、誰も「Lo」に引き下げるスレーブがいないので、信号線は「Hi」状態なので、NACKだと言うことで、マスターによりその時の処理を実行させることになります。
NACKの場合の処理例としては表示器があるなら、赤ランプを点灯して「メモリーが検出されない」など表示させ、次の処理に移る(表示リセットスイッチ押し下げ処理含む)様にする。
など考えられます。
1.4.4 制御バイトフォーマット
この制御バイトは信号の先頭にあり(1)スタートビット
(2)制御コード
(3)スレーブアドレス
(4)読み書きビット
で構成されています。
制御コード、スレーブアドレスについては、『1.3 スレーブアドレス』を確認下さい。
スタート ビット
SCLがHiの状態において、SDAがhiからLoへ遷移することで START条件として解釈されます。すべての有効なコマンドは、START条件で開始する必要があります。
読み書きビット
読込でHi、書込でLoの信号を出します。1.4.5 書込
バイト書込
書込動作では、デバイスアドレスワードと応答(ACK)信号に続いて、**2つの8ビットデータワードアドレス(計16ビットのアドレス)**が必要となります。
アドレス指定とデータ入力
このアドレスを受信すると、EEPROMは**「0」(ACK)を返し、その後、最初の8ビットデータワードをクロック同期で取り込みます。
8ビットデータワードの受信完了後、EEPROMは再び「0」(ACK)**を出力します。
書込の終了と内部処理
マイコンなどの制御側デバイスは、STOP条件を発行して書込シーケンスを終了させる必要があります。
STOP条件が発行された時点で、EEPROMは内部タイマーによる書込サイクル(内部書込状態)に入ります。
この書込サイクル中はすべての入力が無効になり、EEPROMは書込が完了するまで応答しません(図3)。

Notes: 1) * = Don’t Care bits
アドレス指定とデータ入力
このアドレスを受信すると、EEPROMは**「0」(ACK)を返し、その後、最初の8ビットデータワードをクロック同期で取り込みます。
8ビットデータワードの受信完了後、EEPROMは再び「0」(ACK)**を出力します。
書込の終了と内部処理
マイコンなどの制御側デバイスは、STOP条件を発行して書込シーケンスを終了させる必要があります。
STOP条件が発行された時点で、EEPROMは内部タイマーによる書込サイクル(内部書込状態)に入ります。
この書込サイクル中はすべての入力が無効になり、EEPROMは書込が完了するまで応答しません(図3)。

Notes: 1) * = Don’t Care bits
ページ書込
128K EEPROMは、64バイトのページ書込に対応しています。
ページ書込の開始と手順
ページ書込はバイト書込と同じ方法で開始されます。
ただし、マイコンは最初のデータワードが取り込まれた後にSTOP条件を送信しません。
EEPROMが最初のデータワードの受信応答(ACK)を返した後、マイコンはさらに最大63個のデータワードを送信できます。
EEPROMは、各データワードを受信するたびに「0」(ACK)を返します。
マイコンは、STOP条件を発行してページ書込シーケンスを終了させる必要があります(図4参照)。
アドレスのインクリメントとロールオーバー
データワードを受信するたびに、データワードアドレスの下位6ビットが内部でインクリメント(加算)されます。
上位のアドレスビットはインクリメントされず、メモリのページ行位置をそのまま保持します。
もし、64個を超えるデータワードがEEPROMに送信された場合、データワードアドレスは「ロールオーバー(循環)」し、前に書き込まれたデータが上書きされます。

Notes: 1) * = Don’t Care bits
ページ書込の開始と手順
ページ書込はバイト書込と同じ方法で開始されます。
ただし、マイコンは最初のデータワードが取り込まれた後にSTOP条件を送信しません。
EEPROMが最初のデータワードの受信応答(ACK)を返した後、マイコンはさらに最大63個のデータワードを送信できます。
EEPROMは、各データワードを受信するたびに「0」(ACK)を返します。
マイコンは、STOP条件を発行してページ書込シーケンスを終了させる必要があります(図4参照)。
アドレスのインクリメントとロールオーバー
データワードを受信するたびに、データワードアドレスの下位6ビットが内部でインクリメント(加算)されます。
上位のアドレスビットはインクリメントされず、メモリのページ行位置をそのまま保持します。
もし、64個を超えるデータワードがEEPROMに送信された場合、データワードアドレスは「ロールオーバー(循環)」し、前に書き込まれたデータが上書きされます。

Notes: 1) * = Don’t Care bits
ACKNOWLEDGEポーリング
ACKNOWLEDGEポーリングは、セルフタイミング方式の内部書き込み動作中に、書き込みステータスを確認するために使用できます。
有効な読み出しまたは書き込みアドレスコマンドを発行した際、デバイスがまだセルフタイミング書き込みモードにある場合、EEPROMは9番目のクロックサイクルでACKNOWLEDGE信号を返しません。
一方、書き込みが完了し、チップがスタンバイモードに復帰している場合は、9番目のクロックサイクルで有効なACKNOWLEDGE信号が返されます。
有効な読み出しまたは書き込みアドレスコマンドを発行した際、デバイスがまだセルフタイミング書き込みモードにある場合、EEPROMは9番目のクロックサイクルでACKNOWLEDGE信号を返しません。
一方、書き込みが完了し、チップがスタンバイモードに復帰している場合は、9番目のクロックサイクルで有効なACKNOWLEDGE信号が返されます。
1.4.6 読込
readコマンドは、アドレスワード内の8番目のread/writeビットが「1」に設定される点を除き、writeコマンドと同様です。
3つの読み出し動作モードは以下の通りです。
3つの読み出し動作モードは以下の通りです。
カレントアドレス・リード
EEPROMの内部アドレスワードカウンタは、デバイスへの電源供給が遮断されていない限り、最後に読込または書込を行ったアドレスに「1」を足した値を保持します。
読込の開始
現行アドレス読込処理を開始するには、マイコンがSTARTビットを発行し、読込/書込ビット(8番目)を「1」に設定した有効なデバイスアドレスワードを送ります。
EEPROMは、9番目のシリアルクロックサイクルで応答(ACK)信号を返します。
データの出力と終了
その後、8ビットのデータワードがシリアル出力されます。
このとき、内部アドレスワードカウンタは自動的に「1」インクリメント(加算)されます。
現行アドレス読込の場合、マイコンは18番目のクロックサイクルで応答(ACK)信号を発行しません。
マイコンは18番目のクロックサイクルの後に有効なSTOPビットを発行して、読込処理を終了します。
その後、デバイスはスタンバイ(STANDBY)モードに戻ります(図5参照)。
読込の開始
現行アドレス読込処理を開始するには、マイコンがSTARTビットを発行し、読込/書込ビット(8番目)を「1」に設定した有効なデバイスアドレスワードを送ります。
EEPROMは、9番目のシリアルクロックサイクルで応答(ACK)信号を返します。
データの出力と終了
その後、8ビットのデータワードがシリアル出力されます。
このとき、内部アドレスワードカウンタは自動的に「1」インクリメント(加算)されます。
現行アドレス読込の場合、マイコンは18番目のクロックサイクルで応答(ACK)信号を発行しません。
マイコンは18番目のクロックサイクルの後に有効なSTOPビットを発行して、読込処理を終了します。
その後、デバイスはスタンバイ(STANDBY)モードに戻ります(図5参照)。
シーケンシャル・リード
シーケンシャル読込は、現行アドレス読込と非常によく似ています。
最初のデータ読込
マイコンはSTARTビットを発行し、読込/書込ビット(8番目)を**「1」に設定した有効なデバイスアドレスワードを送ります。
EEPROMは、9番目のシリアルクロックサイクルで応答(ACK)信号を返します。
その後、8ビットのデータワードがシリアル出力されます。
このとき、内部のアドレスワードカウンタは自動的に「1」インクリメント(加算)**されます。
連続データの読込
現行アドレス読込とは異なり、マイコンは18番目のクロックサイクルで応答(ACK)信号を送信し、さらに別のバイトデータを要求していることをEEPROMデバイスに伝えます。
ACK信号を受信すると、EEPROMはインクリメントされた内部アドレスカウンタに基づいて、次の8ビットデータワードをシリアル出力します。
マイコンがさらに別のデータを必要とする場合は、27番目のクロックサイクルでACK信号を送信します。これにより、もう一つの8ビットデータワードがシリアル出力されます。
読込の終了とロールオーバー
このシーケンシャル読込は、マイコンが新しいデータワードを受信した後にACK信号を送信し続ける限り継続します。
内部アドレスカウンタが最大有効アドレスに達すると、メモリアレイアドレスの**先頭へとロールオーバー(循環)**します。
現行アドレス読込と同様に、マイコンは最後に受信したデータワードに対して応答を返さず(NO ACK)、その後にSTOPビットを送信することで、シーケンシャル読込を終了できます(図6)。
最初のデータ読込
マイコンはSTARTビットを発行し、読込/書込ビット(8番目)を**「1」に設定した有効なデバイスアドレスワードを送ります。
EEPROMは、9番目のシリアルクロックサイクルで応答(ACK)信号を返します。
その後、8ビットのデータワードがシリアル出力されます。
このとき、内部のアドレスワードカウンタは自動的に「1」インクリメント(加算)**されます。
連続データの読込
現行アドレス読込とは異なり、マイコンは18番目のクロックサイクルで応答(ACK)信号を送信し、さらに別のバイトデータを要求していることをEEPROMデバイスに伝えます。
ACK信号を受信すると、EEPROMはインクリメントされた内部アドレスカウンタに基づいて、次の8ビットデータワードをシリアル出力します。
マイコンがさらに別のデータを必要とする場合は、27番目のクロックサイクルでACK信号を送信します。これにより、もう一つの8ビットデータワードがシリアル出力されます。
読込の終了とロールオーバー
このシーケンシャル読込は、マイコンが新しいデータワードを受信した後にACK信号を送信し続ける限り継続します。
内部アドレスカウンタが最大有効アドレスに達すると、メモリアレイアドレスの**先頭へとロールオーバー(循環)**します。
現行アドレス読込と同様に、マイコンは最後に受信したデータワードに対して応答を返さず(NO ACK)、その後にSTOPビットを送信することで、シーケンシャル読込を終了できます(図6)。
RANDOM READ
ランダム読込は、2つのステップからなるプロセスです。
第1ステップでは、「ダミー書込」命令を使用して、内部アドレスカウンタに対象の読込アドレスを初期設定します。
第2ステップでは、現行アドレスの読込を行います。
内部アドレスカウンタに対象の読込アドレスを初期設定するために、マイコンはまずSTARTビットを発行し、続いて読込/書込ビット(8番目)を**「0」に設定した有効なデバイスアドレスを送ります。
その後、EEPROMが応答(ACK)を返します。次に、マイコンは2つのアドレスワードを送信します。
ここでもEEPROMが応答(ACK)**を返します。
マイコンは、EEPROMに有効な書込データを送信する代わりに、現行アドレス読込命令を実行してデータを読み込みます。
注意点として、STARTビットが発行されると、EEPROMは内部の書き込み処理をリセットし、新しい命令(図7の現行アドレス読込)の実行を継続します。
第1ステップでは、「ダミー書込」命令を使用して、内部アドレスカウンタに対象の読込アドレスを初期設定します。
第2ステップでは、現行アドレスの読込を行います。
内部アドレスカウンタに対象の読込アドレスを初期設定するために、マイコンはまずSTARTビットを発行し、続いて読込/書込ビット(8番目)を**「0」に設定した有効なデバイスアドレスを送ります。
その後、EEPROMが応答(ACK)を返します。次に、マイコンは2つのアドレスワードを送信します。
ここでもEEPROMが応答(ACK)**を返します。
マイコンは、EEPROMに有効な書込データを送信する代わりに、現行アドレス読込命令を実行してデータを読み込みます。
注意点として、STARTビットが発行されると、EEPROMは内部の書き込み処理をリセットし、新しい命令(図7の現行アドレス読込)の実行を継続します。
2 データの書込・読込
24C128にデータを書込場合、1回につき、5(ms)待つ事が必要なため、データはバイト書込より、ページ書込(1回で64バイト書込)の方が早く書込できます。
MCU側として単独の変数より配列に入れた方が良い事が判ります。
しかし値と配列名に関連性が無いため、プログラム上ではわかりにくくなります。
この問題をきれいに解決する最もおすすめの方法は、C言語の「構造体(struct)」と「共用体(union)」を組み合わせる方法です。
この方法を使えば、プログラム内では分かりやすい変数名でアクセスでき、EEPROMに書き込むときは一発でバイト配列として扱えます。
具体的な実装パターンと、EEPROM特有の注意点を解説します。
MCU側として単独の変数より配列に入れた方が良い事が判ります。
しかし値と配列名に関連性が無いため、プログラム上ではわかりにくくなります。
この問題をきれいに解決する最もおすすめの方法は、C言語の「構造体(struct)」と「共用体(union)」を組み合わせる方法です。
この方法を使えば、プログラム内では分かりやすい変数名でアクセスでき、EEPROMに書き込むときは一発でバイト配列として扱えます。
具体的な実装パターンと、EEPROM特有の注意点を解説します。
2.1 構造体と共用体
C言語の構造体(struct)と共用体(union)は、複数の変数を1つにまとめるためのデータ型です。もっとも大きな違いは、メモリの共有方法にあります。
2.1.1 構造体(struct)とは
構造体は、異なる型のデータを並べて1つにまとめる機能です。
[ メンバーA ] [ メンバーB ] [ メンバーC ]
メモリ管理: メンバーごとに独立したメモリ領域が割り当てられます。
同時利用: すべてのメンバーの値を同時に保持・使用できます。
主な用途: 住所録(名前、電話番号、郵便番号)や、ゲームのキャラクター情報(座標、HP、名前)など、関連する複数のデータをひとかたまりで扱いたいとき。
同時利用: すべてのメンバーの値を同時に保持・使用できます。
主な用途: 住所録(名前、電話番号、郵便番号)や、ゲームのキャラクター情報(座標、HP、名前)など、関連する複数のデータをひとかたまりで扱いたいとき。
構造体のイメージ
【構造体のメモリ空間】全体サイズ = 各メンバーの合計(+パディング)[ メンバーA ] [ メンバーB ] [ メンバーC ]
2.1.2 共用体(union)とは
共用体は、複数のメンバーで同じメモリ領域を共有(使い回し)する機能です。
[ メンバーA ]
[ メンバーB (同じ場所を共有) ]
[ メンバーC (同じ場所を共有) ]
メモリ管理: 最もサイズが大きいメンバーに合わせてメモリが確保されます。
同時利用: 値を保存できるのは、常にどれか1つのメンバーだけです。新しいメンバーに代入すると、前のデータは上書きされます。
主な用途: メモリ容量が極めて限られている組み込み開発や、同じメモリ領域を異なるデータ型として解釈したいとき(例: 4バイトのデータを、1バイト×4個としても扱いたい場合)。
同時利用: 値を保存できるのは、常にどれか1つのメンバーだけです。新しいメンバーに代入すると、前のデータは上書きされます。
主な用途: メモリ容量が極めて限られている組み込み開発や、同じメモリ領域を異なるデータ型として解釈したいとき(例: 4バイトのデータを、1バイト×4個としても扱いたい場合)。
共用体のイメージ
【共用体のメモリ空間】全体サイズ = 最大メンバーのサイズ[ メンバーA ]
[ メンバーB (同じ場所を共有) ]
[ メンバーC (同じ場所を共有) ]
2.1.3 違いのまとめ
| 項目 | 構造体(struct) | 共用体(union) |
| メモリの配置 | メンバーごとに別々の場所 | 全メンバーで同じ場所を共有 |
| 全体サイズ | 各メンバーのサイズの合計 | 最大のメンバーのサイズ |
| 同時アクセス | すべてのメンバーに同時に可能 | 最後に書き込んだ1つだけ可能 |
2.2 プログラミング
プログラミングの環境としてMounRiver Studio ⅡでHC32V203を使用したものを想定しています
2.2.1 変数の構造体を定義する
まず、保存したいデータを分かりやすい変数名で定義します。
2.2.2 Byte配列と共用体(Union)
次に、上記で定義した構造体と、EEPROM送信用の配列(uint8_t 型)を共用体にします。
2.2.3 プログラム内での使い方
この方法を使うと、プログラム内では配列を使わずに、分かりやすい変数名で直接読み書きができます。
配列のインデックス(何番目か)を気にする必要は一切ありません。
配列のインデックス(何番目か)を気にする必要は一切ありません。
2.2.4 保存・読み出し方法
ページ書き込みを使用します。
実際の使い方のイメージ
読み出し(Read)のときは待ち時間は不要ちなみに、EEPROMからデータを読み出す(Read)ときは、物理的な高電圧書き換えが発生しないため、1バイトずつ読もうが、まとめて読もうが5msの待ち時間は一切不要です。
一瞬で終わります。読み出しも同様に、以下のように途中でストップをかけずに連続してクロックを送り、EEPROMからデータを連続で受け取る「シーケンシャルリード」を行うのが一般的です。
このように、書き込み時だけ「データを連続で送り、最後にストップをかけ、5ms待つ」という手順を踏むことで、配列のデメリット(名前が分からなくなる問題)と、EEPROMのデメリット(1バイトずつだと遅い問題)の両方をきれいにクリアできます。
実際の使い方のイメージ
読み出し(Read)のときは待ち時間は不要ちなみに、EEPROMからデータを読み出す(Read)ときは、物理的な高電圧書き換えが発生しないため、1バイトずつ読もうが、まとめて読もうが5msの待ち時間は一切不要です。
一瞬で終わります。読み出しも同様に、以下のように途中でストップをかけずに連続してクロックを送り、EEPROMからデータを連続で受け取る「シーケンシャルリード」を行うのが一般的です。
このように、書き込み時だけ「データを連続で送り、最後にストップをかけ、5ms待つ」という手順を踏むことで、配列のデメリット(名前が分からなくなる問題)と、EEPROMのデメリット(1バイトずつだと遅い問題)の両方をきれいにクリアできます。
2.2.5 構造体の重要な注意点
CH32V203は32bit(RISC-V)マイコンです。
C言語の構造体は、マイコンがアクセスしやすいように自動的にデータの間に隙間(パディング)を入れてしまいます(4バイト境界アライメント)。
これにより、sizeof(SettingData_t) のサイズが想定より大きくなり、EEPROM内に無駄な空きスペース(ゴミデータ)が書き込まれたり、データ位置がズレたりします。
これを防ぐために、構造体を定義する際は必ず __attribute__((packed)) を付与して、隙間を詰め(パック化)してください。
C言語の構造体は、マイコンがアクセスしやすいように自動的にデータの間に隙間(パディング)を入れてしまいます(4バイト境界アライメント)。
これにより、sizeof(SettingData_t) のサイズが想定より大きくなり、EEPROM内に無駄な空きスペース(ゴミデータ)が書き込まれたり、データ位置がズレたりします。
これを防ぐために、構造体を定義する際は必ず __attribute__((packed)) を付与して、隙間を詰め(パック化)してください。
2.2.6 24C128を扱う際の2つの罠
構造体を使って配列問題を解決しても、24C128のハードウェア特性による以下の制限に注意する必要があります。
(1)ページバウンダリ(64バイトの壁)
24C128は一度に最大64バイトまで連続書き込み(ページ書き込み)ができますが、アドレスの64バイトの境界(0x003Fから0x0040など)をまたいで連続書き込みすると、データが先頭にラップアラウンド(上書き)して壊れます。
構造体の合計サイズが64バイトを超える場合や、書き込み開始アドレスが64の倍数でない場合は、ページをまたがないように小分けにして書き込む関数(ページング処理ルーチン)を実装してください。
構造体の合計サイズが64バイトを超える場合や、書き込み開始アドレスが64の倍数でない場合は、ページをまたがないように小分けにして書き込む関数(ページング処理ルーチン)を実装してください。
(2)書き込み完了待ち(約5ms)
EEPROMにデータを書き込んだ後、内部で物理的な書き込みが完了するまで約5ミリ秒かかります。
書き込み直後に連続して次のデータを書き込んだり読み出したりする場合は、必ず Delay_Ms(5); を入れるか、I2Cのアックポーリング(応答確認)を行ってください。
書き込み直後に連続して次のデータを書き込んだり読み出したりする場合は、必ず Delay_Ms(5); を入れるか、I2Cのアックポーリング(応答確認)を行ってください。
