MSP430G2553 - EEPROM
概要
EEPROM (Electrically Erasable Programmable Read-Only Memory) は、電気的に消去、書き込み可能な不揮発性メモリの1種である。
EEPROMの主な特徴を以下に示す。
- 不揮発性
- 電源を切ってもデータを保持できる。
- 書き換え可能
- データの消去と書き込みを電気的に行うことができる。
- バイト単位のアクセス
- バイト単位でデータの読み書きが可能である。
- 書き換え回数の制限
- 一般的に、100万回程度の書き換えが可能である。
- 低速
- フラッシュメモリ等と比較して、読み書きの速度が遅い。
- シリアル通信
- I2CやSPI等のシリアル通信インターフェースを使用して、マイクロコントローラと通信する。
- 容量
- 数[Kbit]〜数[Mbit]までの容量のデバイスが存在する。
- 用途
- 設定情報や較正データの保存、データロガー、小容量のデータ保存等に使用される。
EEPROMは、マイコンのシステムで、不揮発性のデータ保存が必要な場合に広く使用されている。
フラッシュメモリと比較して書き換え回数が多く、バイト単位のアクセスが可能な点が特徴である。
ただし、書き換え速度が遅く、大容量のデータ保存には向かない。
また、書き換え回数にも制限があるため、頻繁に更新されるデータの保存には適していない。
したがって、用途に応じて、EEPROM、フラッシュメモリ、SRAM等の他のメモリデバイスを使い分ける必要がある。
マイコンの内蔵メモリでデータ保存が可能な場合は、外付けのEEPROMを使用しないこともある。
EEPROMは、マイコンのシステムにおいて、小容量の不揮発性データ保存が必要な場合に重要な役割を果たすデバイスである。
EEPROMの種類
一般的に、外付けのEEPROMとして使用されているデバイスには、以下のようなものがある。
以下に示すEEPROMは、MSP430マイコンのI2CまたはSPIインターフェースに直接接続して使用することができる。
容量や速度、インターフェースの種類などの要件に応じて選択する。
特に、24LC256は、比較的大容量でI2Cインターフェースを備えているため、MSP430マイコンの組み合わせで広く使用されている人気の高いEEPROMの1つである。
24LC256 (256Kbit I2C EEPROM)
- Microchip社製の不揮発性メモリ
- I2Cインターフェースを使用
- 32[KB] (256[Kbit]) の容量
- 低消費電力で動作
25LC640A (64Kbit SPI EEPROM)
- Microchip社製の不揮発性メモリ
- SPIインターフェースを使用
- 8[KB] (64[Kbit]) の容量
- 高速動作が可能
AT24C32 (32Kbit I2C EEPROM)
- Atmel (現Microchip) 社製の不揮発性メモリ
- I2Cインターフェースを使用
- 4[KB] (32[Kbit]) の容量
- industryグレードの信頼性
サンプルコード
24LC256 (256Kbit I2C EEPROM)
以下の例では、I2C通信を使用してEEPROMとの通信を行っている。
I2C通信を初期化した後、i2c_write_byte関数を使用してEEPROMにデータを書き込み、i2c_read_byte関数を使用して書き込んだデータを読み出している。
- i2c_init関数でI2Cの初期化を行う。
ピンの設定、I2Cの設定、クロック周波数の設定等を行う。
MSP430G2553マイコンのP1.6をSCL、P1.7をSDAに指定している。 - i2c_write_byte関数を使用して、指定したアドレスにデータを書き込む。
スタートコンディション、アドレスの送信、データの送信、ストップコンディションの順に処理を行う。 - i2c_read_byte関数を使用して、指定したアドレスからデータを読み出す。
スタートコンディション、アドレスの送信、再スタートコンディション、データの受信、ストップコンディションの順に処理を行う。
実際に動作させる場合は、回路の接続や電源の供給等にも注意が必要である。
#include <msp430.h>
// 24LC256のI2Cアドレス
// 24LC256のA0, A1, A2ピンがGNDに接続されている場合
#define EEPROM_ADDRESS 0x50
void i2c_init();
void i2c_write_byte(unsigned char address, unsigned char data);
unsigned char i2c_read_byte(unsigned char address);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // ウォッチドッグタイマを停止
i2c_init(); // I2Cの初期化
unsigned char data = 0xAA; // 書き込むデータ
unsigned char address = 0x10; // EEPROMのメモリアドレス
i2c_write_byte(address, data); // EEPROMにデータを書き込み
unsigned char read_data = i2c_read_byte(address); // EEPROMからデータを読み出し
while(1);
}
void i2c_init()
{
P1SEL |= BIT6 + BIT7; // I2Cピン(SCL, SDA)の設定
P1SEL2|= BIT6 + BIT7;
UCB0CTL1 |= UCSWRST; // I2Cの無効化(設定変更のため)
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2Cマスターモード, I2Cモード, 同期モード
UCB0CTL1 = UCSSEL_2 + UCSWRST; // SMCLK (1MHz) を選択, I2Cの無効化
UCB0BR0 = 10; // SCLクロック周波数を100kHzに設定
UCB0BR1 = 0;
UCB0I2CSA = EEPROM_ADDRESS; // スレーブアドレスの設定
UCB0CTL1 &= ~UCSWRST; // I2Cの有効化
}
void i2c_write_byte(unsigned char address, unsigned char data)
{
while (UCB0CTL1 & UCTXSTP); // 停止コンディションが送信されるまで待機
UCB0CTL1 |= UCTR + UCTXSTT; // 送信モード, スタートコンディション
while (!(IFG2 & UCB0TXIFG)); // TXバッファが空になるまで待機
UCB0TXBUF = (address >> 8) & 0xFF; // 上位アドレスの送信
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = address & 0xFF; // 下位アドレスの送信
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = data; // データの送信
while (!(IFG2 & UCB0TXIFG));
UCB0CTL1 |= UCTXSTP; // ストップコンディションの送信
}
unsigned char i2c_read_byte(unsigned char address)
{
while (UCB0CTL1 & UCTXSTP);
UCB0CTL1 |= UCTR + UCTXSTT; // 送信モード, スタートコンディション
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = (address >> 8) & 0xFF; // 上位アドレスの送信
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = address & 0xFF; // 下位アドレスの送信
while (UCB0CTL1 & UCTXSTT);
UCB0CTL1 &= ~UCTR; // 受信モード
UCB0CTL1 |= UCTXSTT; // 再スタートコンディション
while (UCB0CTL1 & UCTXSTT);
UCB0CTL1 |= UCTXSTP; // ストップコンディションの送信
while (!(IFG2 & UCB0RXIFG)); // 受信完了まで待機
return UCB0RXBUF; // 受信データの読み出し
}
25LC640A (64Kbit SPI EEPROM)
以下の例では、SPI通信を使用してEEPROMとの通信を行っている。
SPIの初期化後、eeprom_write_byte関数を使用してEEPROMにデータを書き込み、eeprom_read_byte関数を使用して書き込んだデータを読み出している。
- spi_init関数でSPIの初期化を行う。
ピンの設定、SPIの設定、クロック周波数の設定等を行う。 - eeprom_write_byte関数を使用して、指定したアドレスにデータを書き込む。
WREN
コマンドで書き込み有効化して、WRITE
コマンドでアドレスとデータを送信する。 - eeprom_read_byte関数を使用して、指定したアドレスからデータを読み出す。
READ
コマンドでアドレスを送信して、データを受信する。
実際に動作させる場合は、回路の接続や電源の供給等にも注意が必要である。
特に、25LC640AのCS (チップセレクト) ピンは、適切なポートピンに接続して、ソースコード内で設定する必要がある。
#include <msp430.h>
// CSピンの設定 (例: P1.4)
#define EEPROM_CS_PIN BIT4
void spi_init();
void spi_send(unsigned char data);
unsigned char spi_receive();
void eeprom_write_byte(unsigned int address, unsigned char data);
unsigned char eeprom_read_byte(unsigned int address);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // ウォッチドッグタイマーを停止
P1DIR |= EEPROM_CS_PIN; // CSピンを出力に設定
P1OUT |= EEPROM_CS_PIN; // CSピンをハイに設定
spi_init(); // SPIの初期化
unsigned char data = 0xAA; // 書き込むデータ
unsigned int address = 0x1000; // EEPROMのメモリアドレス
eeprom_write_byte(address, data); // EEPROMにデータを書き込み
unsigned char read_data = eeprom_read_byte(address); // EEPROMからデータを読み出し
while(1); // 無限ループ
}
void spi_init()
{
P1SEL |= BIT5 | BIT6 | BIT7; // SPI用のピン設定(SCLK, MOSI, MISO)
P1SEL2 |= BIT5 | BIT6 | BIT7;
UCB0CTL1 |= UCSWRST; // SPIの無効化(設定変更のため)
UCB0CTL0 |= UCCKPL | UCMSB | UCMST | UCMODE_0 | UCSYNC; // SPIマスターモード, 8ビット, MSBファースト, アイドル時クロック高, 同期モード
UCB0CTL1 |= UCSSEL_2; // SMCLK (1MHz) を選択
UCB0BR0 |= 0x02; // SPIクロック周波数を1[MHz] / 2 = 500[kHz]に設定
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // SPIの有効化
}
void spi_send(unsigned char data)
{
while (!(IFG2 & UCB0TXIFG)); // 送信バッファが空になるまで待機
UCB0TXBUF = data; // データを送信バッファに書き込み
}
unsigned char spi_receive()
{
while (!(IFG2 & UCB0RXIFG)); // 受信バッファにデータが入るまで待機
return UCB0RXBUF; // 受信データを返す
}
void eeprom_write_byte(unsigned int address, unsigned char data)
{
P1OUT &= ~EEPROM_CS_PIN; // CSピンをLowに設定
spi_send(0x06); // WREN (書き込み有効化) コマンド
P1OUT |= EEPROM_CS_PIN; // CSピンをハイに設定
__delay_cycles(100); // 100[uS]
P1OUT &= ~EEPROM_CS_PIN; // CSピンをロウに設定
spi_send(0x02); // WRITE (書き込み) コマンド
spi_send((address >> 8) & 0xFF); // アドレス上位バイト
spi_send(address & 0xFF); // アドレス下位バイト
spi_send(data); // データ
P1OUT |= EEPROM_CS_PIN; // CSピンをHighに設定
__delay_cycles(5000); // 書き込み時間分待機
}
unsigned char eeprom_read_byte(unsigned int address)
{
unsigned char data;
P1OUT &= ~EEPROM_CS_PIN; // CSピンをLowに設定
spi_send(0x03); // READ (読み出し) コマンド
spi_send((address >> 8) & 0xFF); // アドレス上位バイト
spi_send(address & 0xFF); // アドレス下位バイト
data = spi_receive(); // データ受信
P1OUT |= EEPROM_CS_PIN; // CSピンをHighに設定
return data;
}
AT24C32 (32Kbit I2C EEPROM)
AT24C32 EEPROMを使用してI2C通信する場合は、上記の24LC256のサンプルプログラムとほぼ同じとなる。
これは、AT24C32と24LC256がどちらもI2Cインターフェースを使用しており、通信プロトコルが同一だからである。
主な違いは、EEPROMの容量とアドレッシングである。
- 24LC256は、256[Kbit] (32[KB]) の容量を持ち、16ビットのアドレス (0x0000~0x7FFF) を使用する。
- AT24C32は、32[Kbit] (4[KB]) の容量を持ち、8ビットのアドレス (0x00~0xFF) を使用する。
したがって、24LC256向けのサンプルコードをAT24C32で使用する場合、以下の点を変更する必要がある。
- EEPROMのI2Cアドレスを確認して、必要に応じて、EEPROM_ADDRESSの定義を変更する。
- i2c_write_byte関数内およびi2c_read_byte関数内で、アドレスの送信部分を修正する。
AT24C32は8ビットアドレスを使用するため、アドレスの上位バイトの送信は不要である。
これらの変更を加えることで、24LC256向けのサンプルコードをAT24C32で使用することができる。
ただし、EEPROMの容量が異なるため、アドレスの範囲に注意が必要である。
AT24C32の有効なアドレス範囲は、0x00~0xFFであり、それ以外のアドレスを指定した場合の動作は未定義となることに注意する。
void i2c_write_byte(unsigned char address, unsigned char data)
{
// ...略
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = address; // アドレスの送信(8ビットのみ)
// ...略
}
unsigned char i2c_read_byte(unsigned char address)
{
// ...略
while (!(IFG2 & UCB0TXIFG));
UCB0TXBUF = address; // アドレスの送信(8ビットのみ)
// ...略
}