”かふぇルネ“はルネサス製品に関してユーザ同士が自由に会話をするツールであり、回答者はルネサス社内外の方たちとなります。ルネサス製品やソリューションに関して正式な回答をご希望の場合は、ルネサス技術サポート問合せをご使用ください。

かふぇルネの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);
    
}

  • (追加)

    2回連続して別なアドレスに書き込むを行う,最初の書き込みは正常ですが,2番目の書き込みが不安定です.int 16200, 900, 17200 が各々16383,771,17407のようになります.うまく書きこめる時もあります.

  • (追加)

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

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

  • チョコです。

    どこをどのように改造したのでしょうか。全体像 が分かるような情報(プロジェクト)を開示してもらえませんか。

    変な改造を行っていると動作は不定です。

    また、通信速度はいくつで、プルアップ抵抗値は何Ωでしょうか。

    ところで24FC6は24FC64の間違いですよね。

    以上

  • チョコさま

    毎回お世話になります.

    replyが当方にメールされていなかったようで返答が遅れました.

    EEPROMは,24FC64でしたが,deviceが悪いと思い,これを現在は24C256に交換しました.

    コードは以下のとおりです.

    1アドレスに1バイト書き込み,1バイト読むというコードに変更しました.

    以前intを書き込むプログラムは,アドレス指定に配列を使っていました.これが悪かったようで,下のコードでは,uint8_tを使用しいます.

    このプログラムでは,書き込み及び読み込みは一応動作します.一応というのは,次のような現象があります.

    E1エミュレータを使用していますが,例えばアドレスは同じにして,書き込むデータを変更して[F6] build and downloadし実行してもデータは変更されません.Disconnect from Debugger [Shift F6]を行い,再度[F6]を行うと正しく書き込みができます.

    EEPROMの問題か,あるいはプログラムの問題なのか分かりません.ご指導お願いします.

    void write_data_byte(uint8_t i2c_adr, uint16_t rom_adr, uint8_t data)
    {
        
        uint8_t adr_high, adr_low;

        adr_high = (uint8_t) (rom_adr >> 8 );
        adr_low = (uint8_t) (rom_adr & 0xFF);
        
        put_3byte_IIC00(i2c_adr, adr_high, adr_low, data);
        wait_10ms();

    }

    uint8_t read_data_byte(uint8_t i2c_adr, uint16_t rom_adr)
    {
        uint8_t adr_high, adr_low, data;

        adr_high = (uint8_t) (rom_adr >> 8 );
        adr_low = (uint8_t) (rom_adr & 0xFF);

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

    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);
        
    }

    MD_STATUS put_data_IIC00( uint8_t s_addr, uint8_t buffer1, uint8_t buffer2)
    {

        MD_STATUS status;
        
        g_write_data[0] = buffer1;         /* set data1        */
        g_write_data[1] = buffer2;         /* set data2        */
        
        /*--------------------------------------
         start transmission
         --------------------------------------*/
        
        status = R_IIC00_Master_Send(s_addr, (uint8_t *__near)g_write_data, 2);
        
        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);
        
    }

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

        MD_STATUS status;

        //g_write_data[0] = buffer2;           /* set register address         */

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

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

        //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)buffer1, 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);

    }

  • (追加) 読み込みも[Shift F6],そして[F6]をしないと正しく読み込みできません.

  • 画像を添付します.lcd_sii_goto1, lcd_sii_puts1はデバッグのための液晶ディスプレイ表示です.

  • チョコ様

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

    同じアドレスの読み込みを添付画面の「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の側にあることを理解してください。

    以上