かふぇルネのIICサンプルプログラムを改造したが,EEPROM (24FC6) の連続書き込みが不安定

皆様,

G13(CCRL)にてチョコさんのIICサンプルプログラムのMD_STATUS put_data_IIC00( uint8_t s_addr, uint8_t buffer1, uint8_t buffer2)を修正し,以下のプログラムを作成しました.

これはEEPROMのByte Writeを行うためのものです.これを5msのインターバルをおいて連続的に書き込むと,非常に不安定で正常に書き込めないことが多発しています.buffer1, buffer2 がEEPROMのアドレス,buffer3がデータです.ストップコンデイション云々の問題でしょうか?

ご指導お願いします.

=======

MD_STATUS put_3byte_IIC00( uint8_t s_addr, uint8_t buffer1, uint8_t buffer2, uint8_t buffer3)
{

    MD_STATUS status;
    //uint8_t work1, work2;
    
    //work1 = (uint8_t) ((buffer2 >>8) & 0x00FF);
    //work2 = (uint8_t) (buffer2 & 0x00FF);
    
    g_write_data[0] = buffer1;       /* set data1       */
    g_write_data[1] = buffer2;         /* set data2       */
    g_write_data[2] = buffer3;         /* set data3       */
    
    /*--------------------------------------
     start transmission
     --------------------------------------*/
    
     
    status = R_IIC00_Master_Send(s_addr, (uint8_t *__near)g_write_data, 3);
    
    if( IIC_SUCCESS == status )         /* check start successfully     */
    {
        
        /*--------------------------------------
         transmit start and
         wait for transmission end
         --------------------------------------*/
        
        do
        {                               /* wait for transmission end    */
            
            status = R_IIC00_check_comstate(); /* get IIC status          */
            
        }while( IIC_USING == ( status & IIC_STS_MASK ) );
        
        /*
         release IIC  bus
         */
        R_IIC00_StopCondition();          /* issue stop condition         */
        
    }
    else
    {
        /* do nothing */
    }
    
    return (status);
    
}

Parents
  • (追加)

    順番は関係ないようです.EEPROMのアドレスの値に関係するようです.見てみます.

  • (追加) アドレスも関係ないようです.

  • チョコ様

    書き込みは正常のようです.読み込みが問題です.

    同じアドレスの読み込みを添付画面の「run the program after the cpu reset」ボタンをクリックすと指定していないアドレスのデータが読み込まれますが,もう一度このボタンを押すと正しく読み込みます.

    読み込みには,

     put_data_IIC00(i2c_adr, adr_high, adr_low);
     read_byte_IIC00(i2c_adr, &data);

    の関数を使用していますが,アドレスを指定するput_data_IIC00が動作不安定です.あらためて,EEPROMのrandom readを見ると,STOPが最後に出ていますが,put_data_IIC00はStop conditionを出しています.read_byte_IIC00もStop conditionを出しています.

  • 画面添付が不足していました.「run the program after the cpu reset」ボタンです.

  • read_byte_IIC00を次のように変更しましたが,状況は同じです.

    MD_STATUS read_byte_IIC00( uint8_t s_addr, uint16_t buffer1, uint8_t *const buffer2 )
    {

        MD_STATUS status;
        uint8_t work1, work2;
        work1 = (uint8_t) (buffer1 << 8);
        work2 = (uint8_t) (buffer1 & 0xFF);
       
        g_write_data[0] = work1;
        g_write_data[1] = work2;           /* set register address         */

    /*--------------------------------------
        transmit register address
    --------------------------------------*/

        status = R_IIC00_Master_Send(s_addr, (uint8_t *__near)g_write_data, 2);

        if( IIC_SUCCESS == status )         /* check start successfully     */
        {

    /*--------------------------------------
        wait for transmission end
    --------------------------------------*/

            do
            {

                status = R_IIC00_check_comstate(); /* get IIC status  */

            }while( IIC_USING == ( status & IIC_STS_MASK ) );

    /*--------------------------------------
       transmission end
    --------------------------------------*/

            if ( IIC_SUCCESS == status )    /* check result         */
            {

    /*--------------------------------------
       start IIC receiving
    --------------------------------------*/

                status = R_IIC00_Master_Receive(s_addr, (uint8_t * __near)buffer2, 1);

                if( status == 0)            /* check start successfully     */
                {

    /*--------------------------------------
        wait for receive end
    --------------------------------------*/

                    do
                    {
                        status = R_IIC00_check_comstate();

                    }while( IIC_USING == ( status & IIC_STS_MASK ) );
                }
                else
                {
                    /* do nothing */
                }

            }
            else
            {
                /* do nothing */
            }

        }

        R_IIC00_StopCondition();              /* issue stop condition     */

        return (status);

    }
  • チョコです。

    「かふぇルネのIICサンプルプログラム」とはどれのことでしょうか。いくつもプログラムが存在し、簡易IICのライブラリはステータス関係を何回か変更しているので、そこらを確定しないと先に進められません。

    「IIC通信のマスタ側(RL78/G13の簡易IIC版)改 2C」のことであれば、制御対象はスレーブのRL78に準備されたRAMを対象にしているので、シリアルEEPROMとは異なります。また、構造と関数名がかなり変わっていたり、関数の引数がポインタだったり、実体渡しだったりして混乱しまっているので、プロジェクト全体の情報がないとコメントできません。す。

    RL78/G13の簡易IICを使用したアプリケーションノートがあるので、そちらを参照される方がいいような気がします。

    renesasのトップページで"r01an2828"で険悪すると見つかります。このアプリケーションノートのサンプルコードは何種類のEEPROMに対応しているようです。

    以上

  • チョコ様

    ご指導ありがとうございます.

    調べたら私が使用しているものは,version 1.10です.別なスレッドでCCRL2CがUpされていますが,EEPROM対応ではないとのこと了解いたしました.なお,速度は400KbpsでPullupは,SDA,SCLとも4.2Kohmです(5V).

    r01an2828を調べてみます.

  • チョコ様

    r01an2828は初心者のレベルを超えていると思います.IICのような一般的なプロトコルを使うにはあまりにもH/Wレベルにより過ぎていると思います.EEPROMが動作するようなIICのAPIのようなものはないでしょうか?

  • チョコ様

    CCRL2CのAPIはEEPROMに使用できないでしょうか?

  • チョコです。

    I2Cは汎用的な通信方式ですが、それを使ってアクセスするEEPROMの方に制限があります。

    I2C対応のEEPROMは容量によって、内部のEEPROMのアドレスをスレーブアドレスの下位ビットに埋め込むことで、通信データ数を少なくするようになっているものがあります。それでも、容量によって、送信する内部のEEPROMのアドレスが1バイトで済むか、2バイト必要かが変わります。また、EEPROMの容量によって、容量が異なるいくつかのブロックに分割されていて、一度にはブロックをまたがった書き込みができません(読み出しはブロックを超えても可能です)。ライブラリ・レベルで、そこらにきちんと対応しようとするとあのような構成になってしまうと思います。このためのパラメータがIIC_EEPROM.cで、以下のように定義されています。

    ここらが、複雑になっている原因です。ここらは、EEPROMで異なるので、全てにまじめに対応しようとすると避けられません。

    RL78/G10のアプリケーションノート(r01an3081jj)ではブロックサイズを制限することでシンプルにしようとしています。ただし、使用しているのがR5F10Y16とコード領域が2kバイトと小さいのでアセンブラで記述されています。

    ここらを避けるためには、使用するEEPROM(の容量)を限定して、RL78/G10のように書き込むEEPROMのアドレスを制限して、一番小さなブロックサイズである16バイト単位に合わせ込み、ブロックを超えるような書き込みをしないという制限を行うとかなり簡単になるかと思います。

    とにかく、問題の原因がEEPROMの側にあることを理解してください。

    以上

  • チョコです。

    先ほどリプライしたように、原因はEEPROM側にあるので、EEPROMへのアクセスに制限を付けるのが一番です。

    256kビットのEEPROMに限定して、書き込みアドレスを16バイトごとの先頭にして、書き込むデータ数を16バイト以下に制限すれば、比較的簡単にできると思います。

    部品箱にに24FC256と24LC256があったので、少し時間をもらえれば、確認はできるかと思います。

    以上

  • チョコ様

    情報ありがとうございます.

    page毎のwriteを考えるとデバイスにより対応が違ってくると思いますが,一般的な64kbitあるいが256kbitに対するrandom write,random readではアドレスを2byte指定で1byte書き出し/読み取りで,かなり一般的な処理になると思います.

    ご紹介いただいたr01an2828では減算処理によるwaitがありました.RL78ではclockによりその時間は変動すると思います.

    10年位前ですが,78k0のKF2ではcode generateのAPIを使用してEEPROM(64Kbit)は動作しました.新しいRL78/G13で,このような問題で手間取っているのは,Renesasさんの問題だとはおもいますが,日の丸プロセッサの可用性を高めるにはこのような問題でトラブルのはよくないと思っております.

Reply
  • チョコ様

    情報ありがとうございます.

    page毎のwriteを考えるとデバイスにより対応が違ってくると思いますが,一般的な64kbitあるいが256kbitに対するrandom write,random readではアドレスを2byte指定で1byte書き出し/読み取りで,かなり一般的な処理になると思います.

    ご紹介いただいたr01an2828では減算処理によるwaitがありました.RL78ではclockによりその時間は変動すると思います.

    10年位前ですが,78k0のKF2ではcode generateのAPIを使用してEEPROM(64Kbit)は動作しました.新しいRL78/G13で,このような問題で手間取っているのは,Renesasさんの問題だとはおもいますが,日の丸プロセッサの可用性を高めるにはこのような問題でトラブルのはよくないと思っております.

Children
  • チョコです。

    >ご紹介いただいたr01an2828では減算処理によるwaitがありました.

    細かく見てないので、断定できませんが、R_IICr_SCL_TimeやR_IICr_SCL_highTimeでの処理でしょうか。

    それならば、簡易IICでスタートコンディション等をソフトで発生させるための時間測定で、32MHz動作でもクロックの規格(MIN)を満足させるようになっているようです。MINの規格なので、動作クロックが32MHzより低くなってもMIN規格より長くなるだけなので気にしていないのではないでしょうか。ダミークロック出力でも同じものを使っているようですね。

    >random write,random readではアドレスを2byte指定で1byte書き出し/読み取りで,かなり一般的な処理になると思います.

    これが一般的かどうかは疑問ですが、1バイトの読み書きであれば、EEPROMへのアクセスでのブロックの制限はなくなります。ただし、送信したデータをEEPROMの指定されたアドレスに書き込むためにはEEPROM内でチャージポンプを起動してから書き込むのにそれなりの時間(MAXで5ms)がかかります。その時間が、1バイトごとに許されるかどうかは使い方によっても変わってくるのではないかと思います。

    以上