LPC1343 I2C EEPROM通信 read

出来た事

1.I2Cを使ったEEPROMのRead(1byte Read)

(エラー処理なしの単純処理)
開発Listへ戻る

さて1byte Readの場合です。(前回1 byte write)
任意のアドレスの1 byteのデータを読み出します。
まず動作としてWriteとReadで何が違うのかを確認します。

Writeの場合(Microchip : DS21930A_JP - Page 16引用)

Readの場合(Microchip : DS21930A_JP - Page 19引用)

最初のほうはReadもWriteも同じです。
任意のアドレスを指定するところまでは同じなんですね。

その次にまたStartを入れてデバイスの指定と今度はReadを送信します。
ここのACKは(Readなので"H"と記載した矢印の右横のACK)
Readしますよ良いですか?というマスタから訊かれているのに対して
EEPROMがOK!と返事をするという意図なのでEEPROMからACKが出ます。

次はいよいよEEPROMからデータを受けることになります。
EEPROMがデータを出していてマスタ(LPC1343)がデータを受けるので
ここのACKの管理(図中のマスタ管理 No ACK部分)は、マスタ側にあります。
1.マスタがACKを返す: もっとデータ頂戴!という意味
EEPROMは次のアドレスのデータを出力する。
2.マスタがACKを返さない: もうデータは要らないよという意味。
EEPROMはもうデータを送信しない。
今回は1byte Readなので2番の動作を選択します。



code (PJTはSemihostingで作る

#ifdef __USE_CMSIS
#include "LPC13xx.h"
#endif

#include
#include

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#include

int main(void) {

LPC_IOCON->PIO0_4 = 0x01; // PIO0_4 as SCL
LPC_IOCON->PIO0_5 = 0x01; // PIO0_5 as SDA
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);// Enable for I2C clock
LPC_SYSCON->PRESETCTRL |= 0x02; // De-asset I2C reset

LPC_I2C->SCLL = 350; // SCL Low
LPC_I2C->SCLH = 350; // SCL High
// Duty=50% about 100kHz@70MHz clock

NVIC_EnableIRQ(I2C_IRQn); // Enable I2C interrupt

LPC_I2C->CONCLR = 0x6c; // I2C flagClear
LPC_I2C->CONSET = 0x40; // I2C enable

LPC_I2C->CONSET = 0x20; // assert Start

// Enter an infinite loop, just incrementing a counter
volatile static int i = 0 ;
while(1) {
i++ ;
}
return 0 ;
}

void I2C_IRQHandler(void)
{
uint8_t StatValue;
int adrs=0x13;

StatValue= LPC_I2C->STAT;
switch ( StatValue )
{
case 0x08: //Now Status is Start
LPC_I2C->DAT =0xa0; //Device address 1010 000 + Write
LPC_I2C->CONCLR = 0x28; //clear interrupt flag + set next action
break;
case 0x18: //Now Status is SLA+W and Receive ACK
LPC_I2C->DAT =adrs; //Address
LPC_I2C->CONCLR = 0x08; //clear interrupt flag
break;

// ここまではWriteと同じなので説明割愛

case 0x28: //Now Status Data byte and Receive ACK
LPC_I2C->CONSET = 0x20; //Set Start again
LPC_I2C->CONCLR = 0x08;
break;
case 0x10: //Receive Repeated Start
LPC_I2C->DAT = 0xa1; //Set Device address & Read
LPC_I2C->CONCLR = 0x28;
break;
case 0x40: //Now Status is SLA+R and Receive ACK
// LPC_I2C->CONSET = 0x04; //send ACK (LPC1343 output ACK)
LPC_I2C->CONCLR = 0x08;
break;
case 0x58:
LPC_I2C->CONSET = 0x10; //send stop command
LPC_I2C->CONCLR = 0x08; //Clear interrupt & Disable I2c
while(LPC_I2C->CONSET & 0x00000010); //waiting STOP flag
LPC_I2C->CONCLR = 0x48; //Clear interrupt & Disable I2c

default:
break;
}
}

解説です。

Writeのときと変わる部分から説明します。(codeの青文字以下の説明です)

データのアドレスを指定した後
ステータスが0x28になり
割り込みが発生します。
次は再度スタートコマンドを入れなければならないのでコードは以下です。

case 0x28: //Now Status Data byte and Receive ACK
LPC_I2C->CONSET = 0x20; //Set Start again
LPC_I2C->CONCLR = 0x08;
break;

再度入力したスタートコマンドのステータスはRepeated Statとして0x10になります。
ステータス9x10で割り込みが入ると

バイスコードを指定してReadコマンドを入れます。
EEPROMのデバイスコード=1010, アドレス=000(回路でA0-A2をGNDに接続) Read=1ですから
0xa1です。


case 0x10: //Receive Repeated Start
LPC_I2C->DAT = 0xa1; //Set Device address & Read
LPC_I2C->CONCLR = 0x28;
break;

バイスアドレス+Readを送信してEEPROMからACKを受けるとステータスが0x40になって
割り込みが入ります。
次はデータを受ける番です。
連続してデータを受ける場合 (+1 アドレスに格納されたデータを受ける場合)
LPC1343からEEPROMにACKを返せばいいのです。その場合は
LPC_I2C->CONSET = 0x04; でAckを返す設定をすればよいのですが
今回は1byte Readなので不要です(だからコメントアウトしてます)
割り込みクリアをすれば、No-Ackでデータを受けてくれます。

case 0x40: //Now Status is SLA+R and Receive ACK
// LPC_I2C->CONSET = 0x04; //send ACK (LPC1343 output ACK)
LPC_I2C->CONCLR = 0x08;
break;

データを受けてACKを返さなかった場合のステータスは0x58です。
割り込みが入ると
すでにDATAレジスタにはEEPROMから受けたデータが入っていますので
Printfで表示します。
そして、Stop commandを入れて、割り込みクリア です。
Stopコマンドが入るのをステータスレジスタで確認できるまでまって
I2C オフです。

LPC_I2C->CONSET = 0x10; //send stop command
LPC_I2C->CONCLR = 0x08; //Clear interrupt & Disable I2c
while(LPC_I2C->CONSET & 0x00000010); //waiting STOP flag
LPC_I2C->CONCLR = 0x48; //Clear interrupt & Disable I2c


結果としてコンソールにWriteのときに書いた2cが表示されています。