Hobby Lab 趣味のモノ作り実験のサイトです。
部品 プロセッサー他 Memory 24C128
1 FT24C128Aの概要
 1.1 特徴
 1.2 構造
 1.3 スレーブアドレス
 1.4 I2C信号フォーマット
 1.4.1 I2C信号の回路
 1.4.2 信号のフォーマットは
 1.4.3 ACK
 1.4.4 制御バイトフォーマット
 1.4.5 書込
 1.4.6 読込
2 データの書込・読込
 2.1 構造体と共用体
 2.1.1 構造体(struct)とは
 2.1.2 共用体(union)とは
 2.2.3 違いのまとめ
 2.2 プログラミング
 2.2.1 変数の構造体を定義する
 2.2.2 Byte配列と共用体にする
 2.2.3 プログラム内での使い方
 2.2.4 保存・読出し方法
 2.2.5 構造体の重要な注意点
 2.2.6 24C128を扱う際の2つの罠

PrO:Si4735関係  Si4735について
 Si4735ラジオを作って見よう1
 Si4735テスト中に判ったこと1
 v コマンド & パラメータ解説 v
 コマンド・プロパティー一覧
 0x01. POWER_UP
 0x10. GET_REV
 0x11. POWER_DOWN
 0x12. SET_PROPERTY
 0x13. GET_PROPERTY
 0x14. GET_INT_STATUS
 0x20. FM_TUNE_FREQ
 0x21. FM_SEEK_START
 0x22. FM_TUNE_STATUS
 0x23. FM_RSQ_STATUS
 0x24. FM_RDS_STATUS
 0x27. FM_AGC_STATUS
 0x28. FM_AGC_OVERRIDE
 0x40. AM_TUNE_FREQ
 0x41. AM_SEEK_START
 0x42. AM_TUNE_STATUS
 0x43. AM_RSQ_STATUS
 0x47. AM_AGC_STATUS
 0x48. AM_AGC_OVERRIDE
 0x80. GPIO_CTL
 0x81. GPIO_SET
 v プロパティ解説 v
 0x0001.GPO_IEN
 0x0102. DIGITAL_OUTPUT・・
 0x0104. DIGITAL_OUTPUT・・
 0x0201. REFCLK_FREQ
 0x0202. REFCLK_PRESCALE
 0x1100. FM_DEEMPHASIS
 0x1102. FM_CHANNEL_FILTER
 0x1107. FM_ANTENNA_INPUT
 0x1108. FM_MAX_TUNE_ERR・・
 0x1200. FM_RSQ_INT_SOURCE
 0x1201. FM_RSQ_SNR_HI_T・・
 0x1202. FM_RSQ_SNR_LO_T・・
 0x1203. FM_RSQ_RSSI_HI・・
 0x1204. FM_RSQ_RSSI_LO・・
 0x1205. FM_RSQ_MULTIPA・・
 0x1206. FM_RSQ_MULTIPA・・
 0x1207. FM_RSQ_BLEND_TH・・
 0x1300. FM_SOFT_MUTE_RATE
 0x1301. FM_SOFT_MUTE_SL・・
 0x1302. FM_SOFT_MUTE_M・・
 0x1303. FM_SOFT_MUTE_S・・
 0x1304. FM_SOFT_MUTE_R・・
 0x1305. FM_SOFT_MUTE_A・・
 0x1400. FM_SEEK_BAND_B・・
 0x1401. FM_SEEK_BAND_TOP
 0x1402. FM_SEEK_FREQ_S・・
 0x1403. FM_SEEK_TUNE_S・・
 0x1404. FM_SEEK_TUNE_R・・
 0x1500. FM_RDS_INT_SOU・・
 0x1501. FM_RDS_INT_FIF・・
 0x1502. FM_RDS_CONFIG
 0x1503. FM_RDS_CONFIDE・・
 0x1800. FM_BLEND_RSSI_S・・
 0x1801. FM_BLEND_RSSI_M・・
 0x1802. FM_BLEND_RSSI_A・・
 0x1803. FM_BLEND_RSSI_R・・
 0x1804. FM_BLEND_SNR_ST・・
 0x1805. FM_BLEND_SNR_M・・
 0x1806. FM_BLEND_SNR_A・・
 0x1807. FM_BLEND_SNR_R・・
 0x1808. FM_BLEND_MULTI・・
 0x1809. FM_BLEND_MULTI・・
 0x180A. FM_BLEND_MULTI・・
 0x180B. FM_BLEND_MULTI・・
 0x1A00. FM_HICUT_SNR_H・・
 0x1A01. FM_HICUT_SNR_L・・
 0x1A02. FM_HICUT_ATTAC・・
 0x1A03. FM_HICUT_RELEA・・
 0x1A04. FM_HICUT_MULTI・・
 0x1A05. FM_HICUT_MULTI・・
 0x1A06. FM_HICUT_CUTOF・・
 0x3100. AM_DEEMPHASIS
 0x3102. AM_CHANNEL_FIL・・
 0x3103. AM_AUTOMATIC_V・・
 0x3104. AM_MODE_AFC_SW・・
 0x3105. AM_MODE_AFC_SW・・
 0x3200. AM_RSQ_INT_SOU・・
 0x3201. AM_RSQ_SNR_HI_T・
 0x3202. AM_RSQ_SNR_LO_T・
 0x3203. AM_RSQ_RSSI_HI・・
 0x3204. AM_RSQ_RSSI_LO・・
 0x3300. AM_SOFT_MUTE_R・・
 0x3400. AM_SEEK_BAND_B・・
 0x3401. AM_SEEK_BAND_TOP
 0x3402. AM_SEEK_FREQ_S・・
 0x3403. AM_SEEK_TUNE_S・・
 0x3404. AM_SEEK_TUNE_R・・
 0x4000. RX_VOLUME
 0x4001. RX_HARD_MUTE

Pr:OPAMP オペアンプ関係
PrO:送受信機  Si4735
PrO:オペアンプ  LM324
 LM358
Pr:Prプロセッサ関係
PrP:プロセッサ
動作比較
 STM32F動作比較
 CH32V203&STM32F 動作比較
 arduino動作比較
raspberrypi関係
 RaspberryPiハード
CH32V関係
 -CH32V開始
 -203K8T6(32Pin)開始
 -203C8T6(48P)開始
 -003J4M6(8Pin)開始
 -003F4P6(20Pin)開始
 -Moun River StudioⅡ
 プログラミング!
  203_GPIO関係
  203_TIME関係
  203_TIME Encoder
  203_I2C関係
  203_1-Wire関係
  003_DS18B20テスター
  USART(UART)関係
  DS18B20をModBus制御
 -マニュアル
 203データシート
 203取説
  MBA メモリとバス方式
  PWR 電力制御
  RCC リセット・拡張・クロック
  BKP バックアップレジスタ
  CRC 巡回冗長検査
  RTC リアルタイムクロック
  GPIO GPIOと代替機能
  DMA ダイレクトメモリアクセス制御
  ADTM 高度な制御タイマー
  GPTM 汎用タイマー
  BCTM 基本タイマー
  USART 同期非同期通信
arduino関係
 ESP12関係
 (a)ESP-8266D1mini注意
PrP:その他  RS485ドライバー
 CP2102 BRIDGE
 WCH-LinkEエミュレーター
Pr:Wire 電線関係
Pr:Resistance 抵抗
Pr:Capacitor コンデンサ
Pr:Coil コイル
Pr:PassiveElmt 受動素子
Pr:Diode ダイオード関係
Pr:Tr トランジスタ関係
2SC1815
 リレードライバー設計
 アンプ設計
 発振器
TLP152
 TLP152テスト
TLP2361
 TLP2361テスト
TLP5754
 TLP5754テスト
Pr:Source 電源関係  ツェナーダイオード
 TL431
 LM317
PrS:Downモジュール
 EGS002_IR2110S
 SKU011012
 ACDC02
 XH_M299
 LM2596
 Mini360_MP23070N
 DROK
 WH140
PrS:UPモジュール
 MT3608
PrS:充電モジュール
 TP4056
Pr:Sensor_AD_時計等
PrS:電圧、電流
ADS1115 16bit4CH I2C A/D
 Hardware
 RaspberryPi_コマンド接続
 RaspberryPi_Python
 Arduino
 CH23V203 MounRiverStudioⅡ
INA226 I2C 直流電圧電流
 Hardware
 Arduino
 RaspberryPi_Python
WCS 電流ホール素子
 Hardware
PrS:温度、気圧、湿度、照度
BNE280 I2C 気圧,湿度,気温
 Hardware
 Arduino
 RaspberryPi_Python
BH1750 I2C 照度
 Hardware
 Arduino
 RaspberryPi_Python
DS18B20 1-Wire 温度計
 Hardware
 Arduino
 RaspberryPi_Python
PrS:時間、日時
DS3231 I2C 時計
 Hardware
 Arduino
 RaspberryPi_Python
PrS:表示器
MAR3953 320X480 3.95"
 概要と線や点を描く
 フォントを描く
SSD1306 I2C 0.96"OLED
 Hardware
 Arduino
 RaspberryPi_Python
Pr:Old Processor他
Ot:Others その他

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フリーパッケージ。

 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

ピン名内容
A2,A1,A0スレーブアドレス
SDAシリアルデータ入力 / オープンドレイン出力
SCLシリアルクロック入力
WP書込保護





 1.3 スレーブアドレス

スレーブアドレスは 7bit で表すことになっている。
D6~D3までは固定(1010)になっており、D2がA2端子、D1がA1端子、D0がA0端子の印加電圧に対応している。
このため、スレーブアドレスは0x50~0x57になり、8個の同じメモリーを搭載出来ることが判る。
NoControl CodeA2A1A0Slave
Address
D6D5D4D3D2D1D0
110100010x50
210100000x51
310100110x52
410100100x53
510101010x54
610101000x55
710101110x56
810101100x57

 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) ストップ

1.4.3 ACK

書バイトの後ろに『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の場合の処理例としては表示器があるなら、赤ランプを点灯して「メモリーが検出されない」など表示させ、次の処理に移る(表示リセットスイッチ押し下げ処理含む)様にする。
など考えられます。

 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

ページ書込

128K EEPROMは、64バイトのページ書込に対応しています。
ページ書込の開始と手順
ページ書込はバイト書込と同じ方法で開始されます。
ただし、マイコンは最初のデータワードが取り込まれた後に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信号が返されます。

 1.4.6 読込

readコマンドは、アドレスワード内の8番目のread/writeビットが「1」に設定される点を除き、writeコマンドと同様です。
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)信号を送信し、さらに別のバイトデータを要求していることを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の現行アドレス読込)の実行を継続します。





2 データの書込・読込

24C128にデータを書込場合、1回につき、5(ms)待つ事が必要なため、データはバイト書込より、ページ書込(1回で64バイト書込)の方が早く書込できます。
MCU側として単独の変数より配列に入れた方が良い事が判ります。
しかし値と配列名に関連性が無いため、プログラム上ではわかりにくくなります。
この問題をきれいに解決する最もおすすめの方法は、C言語の「構造体(struct)」と「共用体(union)」を組み合わせる方法です。
この方法を使えば、プログラム内では分かりやすい変数名でアクセスでき、EEPROMに書き込むときは一発でバイト配列として扱えます。
具体的な実装パターンと、EEPROM特有の注意点を解説します。

 2.1 構造体と共用体

C言語の構造体(struct)と共用体(union)は、複数の変数を1つにまとめるためのデータ型です。もっとも大きな違いは、メモリの共有方法にあります。

 2.1.1  構造体(struct)とは

構造体は、異なる型のデータを並べて1つにまとめる機能です。
メモリ管理: メンバーごとに独立したメモリ領域が割り当てられます。
同時利用: すべてのメンバーの値を同時に保持・使用できます。
主な用途: 住所録(名前、電話番号、郵便番号)や、ゲームのキャラクター情報(座標、HP、名前)など、関連する複数のデータをひとかたまりで扱いたいとき。

構造体のイメージ

【構造体のメモリ空間】全体サイズ = 各メンバーの合計(+パディング)
[ メンバーA ] [ メンバーB ] [ メンバーC ]

 2.1.2  共用体(union)とは

共用体は、複数のメンバーで同じメモリ領域を共有(使い回し)する機能です。
メモリ管理: 最もサイズが大きいメンバーに合わせてメモリが確保されます。
同時利用: 値を保存できるのは、常にどれか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バイトずつだと遅い問題)の両方をきれいにクリアできます。

 2.2.5  構造体の重要な注意点

CH32V203は32bit(RISC-V)マイコンです。
C言語の構造体は、マイコンがアクセスしやすいように自動的にデータの間に隙間(パディング)を入れてしまいます(4バイト境界アライメント)。
これにより、sizeof(SettingData_t) のサイズが想定より大きくなり、EEPROM内に無駄な空きスペース(ゴミデータ)が書き込まれたり、データ位置がズレたりします。
これを防ぐために、構造体を定義する際は必ず __attribute__((packed)) を付与して、隙間を詰め(パック化)してください。

 2.2.6  24C128を扱う際の2つの罠

構造体を使って配列問題を解決しても、24C128のハードウェア特性による以下の制限に注意する必要があります。

(1)ページバウンダリ(64バイトの壁)

24C128は一度に最大64バイトまで連続書き込み(ページ書き込み)ができますが、アドレスの64バイトの境界(0x003Fから0x0040など)をまたいで連続書き込みすると、データが先頭にラップアラウンド(上書き)して壊れます。
構造体の合計サイズが64バイトを超える場合や、書き込み開始アドレスが64の倍数でない場合は、ページをまたがないように小分けにして書き込む関数(ページング処理ルーチン)を実装してください。

(2)書き込み完了待ち(約5ms)

EEPROMにデータを書き込んだ後、内部で物理的な書き込みが完了するまで約5ミリ秒かかります。
書き込み直後に連続して次のデータを書き込んだり読み出したりする場合は、必ず Delay_Ms(5); を入れるか、I2Cのアックポーリング(応答確認)を行ってください。





































更新日 2026/07/26 13:36  管理者 平林 剛Hirabayashi Takeshi