MAX2990のI²Cインタフェースを使用して業界標準のEEPROM (24C04)に書込みを行う方法

要約

電力線通信モデムMAX2990のI²Cインタフェースを使用して外部EEPROM 24C04とのインタフェースを行う方法を、アーティクルおよびサンプルファームウェアコードによって説明します。

はじめに

このアプリケーションノートおよびサンプルファームウェアコードは、電力線通信モデムMAX2990のI²Cインタフェースを使用して外部のEEPROM 24C04とのインタフェースを行う方法を示すものです。I²CバスはMAX2990 (マスター)によって制御され、24C04 EEPROMがスレーブになります。この例で使用するハードウェア構成を下図に示します。

図 1. この例で使用するMAX2990のハードウェア構成

ファームウェアの説明

I²Cインタフェースの初期化

I²Cモジュールをイネーブルする場合、必ずSCLおよびSDAをオープンドレイン構成にする必要があります。この構成は、I²C通信が正しく動作するために必要です。I²CはGPIOポートの代替機能であるため、初期化の間はファームウェアでSCLおよびSDA入力のプルアップを(そのポートコントローラの出力ビットにゼロを書き込むことによって)確実にディセーブルする必要があります。

この例では、250kHzのクロック周波数を使用しています。最初に、MAX2990のI²Cインタフェースを次に示すように設定する必要があります。

PO1_bit.Bit2 = 0; 		// Disables the GPIO function of the
PO1_bit.Bit3 = 0; 		// I2C pins

I2CCN_bit.I2CEN = 0; 	// Makes sure that I2C is disabled
			// to allow the changing of the I2C settings

I2CCN_bit.I2CMST = 1; 		// Sets the I2C engine to master mode
I2CCN_bit.I2CEA = 0; 		// 7-bit address mode
I2CCK_bit.I2CCKL = 0x40; 	// 2µs CLK-low, to define I2C frequency
I2CCK_bit.I2CCKH = 0x40; 	// 2µs CLK-high, to define I2C frequency

I2CTO = 200; 		// I2C_TIMEOUT
I2CST = 0x400; 		// Resets I2C status register

I2CCN_bit.I2CEN = 1; 		// Enables the I2C engine

書込みモード

24C04 EEPROMへの書込みを行うためには、I²Cインタフェースを介して以下のバイトを書き込む必要があります。

  1. I²C EEPROMのアドレス(この例では0xA0)
  2. EEPROM内のメモリ位置のアドレス
  3. データバイト(アドレスは自動的に増加します)
この例では、EEPROMの0x00以降の位置に、0x12、0x34、0x56、0x78、および0x90の各バイトを書き込みます。
i2c_init_write(); 	// Sets the MAX2990 I2C Engine into write mode
i2c_write(0x50); 	// 24C04 write (adr = 0b1010 000 0) = 0xA0
			// The MAX2990 I2C engine shifts the I2C address by
			// 1 bit, because it will generate the R/W bit
			// automatically

i2c_write(0x00); 	// word address location
i2c_write(0x12); 	// data1
i2c_write(0x34); 	// data2
i2c_write(0x56); 	// data3
i2c_write(0x78); 	// data4
i2c_write(0x90); 	// data5
I2C_STOP; 		// Sends I2C stop-condition
Figure 2. Write mode.

読取りモード

書き込んだデータをEEPROMから読み戻す場合、書込みのための十分な時間を24C04に与えることが重要です。通常これには「STOP状態」から数ミリ秒かかります。使用するICのデータシートを調べて、必ず適切なタイミングを使用してください。

i2c_init_write(); 	// Sets the MAX2990 I2C engine into write mode
i2c_write(0x50); 	// 24C04 write (adr = 0b1010 000 0) = 0xA0
			// The MAX2990 I2C engine shifts the I2C address by
			// 1 bit, because it will generate the R/W bit
			// automatically

i2c_write(0x00); 	// word address location

i2c_init_read(); 	// Sets the MAX2990 I2C engine into read mode

i2c_write(0x50); 	// 24C04 read (adr = 0b1010 000 1) = 0xA1
			// The MAX2990 I2C engine shifts the I2C address by
			// 1 bit, because it will generate the R/W bit
			// automatically

unsigned char data[5]; 		// Array to store the received data
i2c_read(data[0]); 		// Reads 1 byte from I2C and writes it to the array
i2c_read(data[1]); 		// Reads 1 byte from I2C and writes it to the array
i2c_read(data[2]); 		// Reads 1 byte from I2C and writes it to the array
i2c_read(data[3]); 		// Reads 1 byte from I2C and writes it to the array
i2c_read(data[4]); 		// Reads 1 byte from I2C and writes it to the array
I2C_STOP; 			// Sends I2C stop-condition
次に、EEPROMの読取りおよび書込みに使用される以下の関数について解説します。
i2c_init_write(void)
i2c_init_read(void)
i2c_write(UINT8 data)
i2c_read(UINT8 *data)
Figure 3. Read mode.
void i2c_init_write(void)
{
I2CCN_bit.I2CMODE = 0; 	// I2C transmit mode
I2CCN_bit.I2CACK = 1; 	// Creates I2C NACK so that slave can create ACK
I2C_START; 		// Generates I2C START condition
while( I2CCN_bit.I2CSTART == 1 ); 	// Waits until the START condition
					// was put to the I2C bus
I2CST_bit.I2CSRI = 0; 			// Resets the I2C interrupt flag
}

int i2c_init_read(void)
{
I2CCN_bit.I2CMODE = 1; 	// I2C read-mode
I2CCN_bit.I2CACK = 0; 	// Creates I2C ACK after receive
I2C_START; 		// Generates I2C START condition

while( I2CCN_bit.I2CSTART == 1 ); 	// Waits until the START condition
I2CST_bit.I2CSRI = 0; 			// Resets the I2C interrupt flag
}

void i2c_write(UINT8 data)
{
I2CBUF = data; 				// Puts the data on the I2C bus
while( I2CST_bit.I2CTXI == 0 ); 	// Waits for transfer complete
I2CST_bit.I2CTXI = 0; 			// Resets the I2C transmit complete
					// interrupt flag
}

void i2c_read(UINT8 *data)
{
I2CBUF = 0xff; 		// Puts "all ones" on the I2C bus so that slave can pull
			// the bus down to generate zeros

while( !I2CST_bit.I2CRXI ); 		// Waits for receive complete
I2CST_bit.I2CRXI=0; 			// Resets the I2C receive complete
					// interrupt flag

*data = I2CBUF; 			// Writes the data to the pointer
}