EEPROMとの通信でアドレスもデータとして書き込んでしまう

マイコン:RL78/G14
開発環境:CS+forCC

コード生成機能を使ってI2CのEEPROMを使おうとしているのですがうまくいきません。

具体的には下記のコードを実行するとアドレスがデータとして保存されてしまっています。

読み込むことはできるのですがどうもメモリの先頭から順々に保存されているらしくアドレスもデータとして読み込んでしまいます。

コード生成を用いたEEPROMの読み書き方法を教えていただけないでしょうか?

初歩的な部分での間違いかもしれませんがよろしくお願いします。

uint8_t buf[16];
R_MAIN_UserInit();
buf[0] = 0x00;                                   /*アドレス上位8bit*/
buf[1] = 0x10;                                   /*アドレス下位8bit*/
buf[2] = 0xee;                                   /*データ1byte*/
i2c_flag = 0;
R_IICA0_Master_Send(Slave_Address, buf, 3, 1);

while (i2c_flag == 0);

R_IICA0_StopCondition();
while (SPD0 == 0) ;

  • わわいです
    EEPROMによって、アドレスが1バイト、2バイト、3バイト、4バイトのもの、といろいろありますんで、まずはお使いのEEPROMのデータシートを読んで、アドレス部が何バイトのものなのかを確認しましょう。
    そして、そのバイト数に合わせるようにコードを組む必要がありますね
  • わわいさん

    お返事ありがとうございます。
    使用しているEEPROMはAT24C1024Bでアドレスが2バイトのものです。
    なので上位と下位にわけて送信したのですがうまくいきませんでした。
  • nobuyuki様
    コード生成サポート担当の鈴木です。
    下記のスレッドが参考になると思われます。よろしくお願いします。
    japan.renesasrulz.com/.../6699
  • チョコです。

    そのままでは、コード生成のIICA関係のAPIはリスタートに対応していないので、使い物になりません。

    クレームを付けたら、1回の送信処理完了後にSTOPコンディションを出さないようにはなったのですが、通信の開始処理の頭でI2Cバスのチェックをしているのですが、自分自身でI2Cバスを占有しているのにビジーチェック(IICBSY0が1かどうか)を行い、そこでエラーにしてしまっています。ここのif文をなくせばうまくいくはずです。(具体的には、if文が条件を満足しないようにしてしまう。)

    AT24C1024B(1Mビット)を使っているということは、128Kバイトなので、2バイトでは、アドレスが不足するので、スレーブアドレスに最上位ビットを組み入れるはずですが、そこらはきちんとケアされていますか。

    また、提示されたAPIの使い方では少なくとも、「R_IICA0_Master_Send」関数の第4引数の1は小さすぎます。

    個人的にはコード生成のAPIのこの引数は気に入りません。というか、APIそのものが気に入らないので、

    I2C関係は自分でライブラリを作っています。

    「サンプルプログラム等」にいくつかI2C関係のプロジェクトを登録しています。そこにI2C関係のライブラリがあります。

    IICマスタ(RL78/G13版)改

    https://japan.renesasrulz.com/cafe_rene/m/sample_program/293

     

    「サンプルプログラム等」は下の図のようにトップページの上の方から行くことができます。

    https://japan.renesasrulz.com/cafe_rene/m/sample_program

    ここにはエクセルで一覧があるので、RL78で絞り込めば、RL78関係のサンプルプログラムが探せます。

    以上

  • 鈴木さん
    返信ありがとうございます。

    今回のコードを作成するにあたって鈴木さんが転載してくれたスレッドも参考にしてEEPROMから読み込みを行ったのですがbuf[0]、buf[1]にアドレスがbuf[2]に書き込んだデータ(今回はee)が格納されていたため、アドレスもデータとして保存されてしまっているのでは?と思い書き込みの時点で何か間違いがあると思い質問させていただきました。
    下記のコードは読み込みに使用したコードで R_IICA0_Master_Restart はスレッドを参考に作製した関数です。

    uint8_t buf[16];

    R_MAIN_UserInit();

    buf[0] = 0x00;
    buf[1] = 0x10;

    R_IICA0_Master_Send(Slave_Address, buf, 2, 1);

    R_IICA0_Master_Restart(Slave_Address, buf, 1, 1);

    R_IICA0_StopCondition();
    while(SPD0 == 0);
  • チョコさん
    返信ありがとうございます。
    記載していただいたサンプルコードも試してみたいと思います。
  • nobuyuki様
    EEPROMへ正しくデータが送れているかI2Cの波形を取得してACKが返っているか調べることは可能でしょうか
  • チョコです。
    >R_IICA0_Master_Send(Slave_Address, buf, 2, 1);
    >R_IICA0_Master_Restart(Slave_Address, buf, 1, 1);

    これらのAPIの呼び出しの第4引数の1はだめです。少なくとも100程度にしておくべきです。
    1では、スタート・コンディションを検出する前に、待ち処理を抜けてしまい、エラーに
    なっている可能性があります。
    R_IICA0_Master_SendやR_IICA0_Master_Restartの戻り値を確認してください。おそらく
    MD_ERROR2(0x83)やMD_ERROR1(0x82)になっていると思われます。

    送信と受信で同じバッファを使っているようなので、送信時に設定したデータがそのまま
    残っていてそれを見ていると考えられます(I2Cの通信は行われていない)。
    これは、送信と受信でバッファを分ければすぐに確認できます。
  • 皆さんの意見を参考に試行錯誤した結果、読み書きができるようになりました。
    ありがとうございます。
    アドレスがデータとして入っていたと思っていたのはチョコさんがおっしゃっていたように送信時のデータが残っていただけでした。
    また質問することがあるかもしれませんがその時はよろしくお願いします。
  • チョコです。
    読み書きができるようになってよかったですね。
    シリアルEEPROMでは、書き込みデータを受信して、ストップ・コンディションを検出してから受信したデータを実際のEEPROMに書き込みますが、ページ(24C1024Bで256バイト単位)をまたがることはできないので、書き込むアドレスには注意してください。書き込みは5ms以下で終わります。それまでは、単にバッファに入っているだけです。
    こういった点も注意して進めてください。