RL78/G1D 簡易I2C I2C no ACK エラー

お世話になります。以前にもこちらで質問させていただいたのですが、再び別の内容について投稿させて頂きます。

https://japan.renesasrulz.com/cafe_rene/f/forum18/5233/rl78-g1d-i2c/29519#29519 以前の投稿はこちらです。

BT-RL-01 RL78/G1Dと6軸センサLSM6DS3の通信を簡易I2Cで実現させたいのですが、I2c no ACK のエラーが返ってきて上手くできません。

使用している環境はCS+ for CCです。

試しにセンサーを外した状態で、マイコンの出力信号をオシロでとってみたところ図の様になりました。

CH1がSDA,CH2がSCLです。電源は3.3Vの安定化電源を使用しています。

どうもSDAの波形が可笑しいようでhighは3.3Vに達しておらず、パルスとのこぎり波が合わさっているように見えます。

原因としてなにが考えられるでしょうか?よろしくお願いいたします。

また、I2C通信で使用しているスレーブのレジスタの値を読み取る関数を以下に載せます。そのほかはコード生成機能を使用しています。

uint8_t readRegister(uint8_t slave_addr,uint8_t r_addr, uint8_t * const buf_data,uint8_t buf_size){
/*flag RESET*/
error_status = MD_OK;

iic_flag_send = FALSE;

iic_flag_receive= FALSE;


/*address field send and waiting for completing*/
R_IIC00_Master_Send(slave_addr,r_addr,1);
do{

if(error_status!=MD_OK){
R_IIC00_Stop();
break;
}
}while(iic_flag_send==FALSE);


/*receive data from slave and waiting for completing*/
R_IIC00_Master_Receive(slave_addr,(uint8_t *__near)buf_data,buf_size);
do{
if(error_status!=MD_OK){
R_IIC00_Stop();
break;
}
}while(iic_flag_receive==FALSE);
if(iic_flag_send==TRUE&&iic_flag_receive==TRUE&&error_status==MD_OK){
return 0; //success
}else{
return 1;   //error
}
}

  • チョコです。
    プログラム以前に,波形が問題です。
    SDA信号のプルアップ抵抗はどのような値を使っていますか。
    抵抗値が大きすぎるようです。SCLが400kHz程度なら,1kΩ以下にしてください。

    以上
  • チョコです。

    波形を見ていて気付いたのですが,スレーブ・アドレスを間違えていませんか。

    LSM6DS3のアドレス(110101xb)は7bitなので,RL78のIIC00では110101xybになります。

    (ここで,xはLSM6DS3のSAD端子で設定した値,yはR/Wを指定する。)

    波形を見ていると,7bitの値をそのまま送信しているように見えます。

    スレーブ・アドレスとしては,LSM6DS3のデータシートのTable 11. SAD+Read/Write patternsの

    右端の欄に書かれている値にしてください。

     

    以上

  • こんなSDAの波形は見たことがありませんね、どこかの出力ポートと意図しない短絡や、SDAの配線がむき出しで1メートルぐらい伸びているとか、基本的なところがおかしいのでは?
  • チョコです。
    波形でストップ・コンディションが出ていないので,プログラムをよく見たら,
    ストップ・コンディションを発行する処理がありません。
    R_IIC00_StopはIIC00を停止させる処理で,これは使い方としておかしい処理です。
    R_IIC00_Stopを呼び出す前にR_IIC00_StopConditionを呼んで,ストップ・コンディションを発行
    してください。これは,I2Cバスを使用する上での手順(作法)です。

    以上
  • チョコ様、ご返信ありがとうございます。返信が遅くなり申し訳ありません。
    上記のソースのR_IIC00_Stopはエラー時に停止をさせる意図で入れております。
    IIC通信完了時の割り込み関数r_iic00_interrupt(void)のソースを下記に載せます。
    これの/* Control for master send */の部分にてストップコンディションの発生があったので、自分で記述する必要はないと思い書かなかったのですが、これとは別にユーザー関数内に記述する必要があるのでしょうか?
    御返信よろしくお願いいたします。
    static void __near r_iic00_interrupt(void)
    {
    if (((SSR00 & _0002_SAU_PARITY_ERROR) == 0x0002U) && (g_iic00_tx_count != 0U))
    {
    r_iic00_callback_master_error(MD_NACK);
    }
    else if(((SSR00 & _0001_SAU_OVERRUN_ERROR) == 0x0001U) && (g_iic00_tx_count != 0U))
    {
    r_iic00_callback_master_error(MD_OVERRUN);
    }
    else
    {
    /* Control for master send */
    if ((g_iic00_master_status_flag & _01_SAU_IIC_SEND_FLAG) == 1U)
    {
    if (g_iic00_tx_count > 0U)
    {
    SIO00 = *gp_iic00_tx_address;
    gp_iic00_tx_address++;
    g_iic00_tx_count--;
    }
    else
    {
    R_IIC00_StopCondition();
    r_iic00_callback_master_sendend();
    }
    }
    /* Control for master receive */
    else
    {
    if ((g_iic00_master_status_flag & _04_SAU_IIC_SENDED_ADDRESS_FLAG) == 0U)
    {
    ST0 |= _0001_SAU_CH0_STOP_TRG_ON;
    SCR00 &= ~_C000_SAU_RECEPTION_TRANSMISSION;
    SCR00 |= _4000_SAU_RECEPTION;
    SS0 |= _0001_SAU_CH0_START_TRG_ON;
    g_iic00_master_status_flag |= _04_SAU_IIC_SENDED_ADDRESS_FLAG;

    if (g_iic00_rx_length == 1U)
    {
    SOE0 &= ~_0001_SAU_CH0_OUTPUT_ENABLE; /* disable IIC00 out */
    }

    SIO00 = 0xFFU;
    }
    else
    {
    if (g_iic00_rx_count < g_iic00_rx_length)
    {
    *gp_iic00_rx_address = SIO00;
    gp_iic00_rx_address++;
    g_iic00_rx_count++;

    if (g_iic00_rx_count == (g_iic00_rx_length - 1U))
    {
    SOE0 &= ~_0001_SAU_CH0_OUTPUT_ENABLE; /* disable IIC00 out */
    SIO00 = 0xFFU;
    }
    else if (g_iic00_rx_count == g_iic00_rx_length)
    {
    R_IIC00_StopCondition();
    r_iic00_callback_master_receiveend();
    }
    else
    {
    SIO00 = 0xFFU;
    }
    }
    }
    }
    }
    }
  • IKUZO様、ご返信ありがとうございます。
    やはりI2Cの波形としては可笑しいですよね。アナログ的な部分を見直してみます。
    ありがとうございました。
  • チョコです。
    >これの/* Control for master send */の部分にてストップコンディションの発生があったので、
    この処理は,正常に通信できたときに実行されるものです。
    今回の場合には,その前の段階でスレーブからのNACK応答を検出して,「r_iic00_callback_master_error(MD_NACK);」でエラー処理に移行しています。
    そちらで何もケアされていないものと考えられます。(そのために,波形上にストップ・コンディションが確認できません。)
    同じファイルにある「r_iic00_callback_master_error」関数での処理を確認してください。

    その前に,異常な波形の対策を行ってください。SDA信号で1が続くべきところが立下っているのは,SCL信号のロウと一致しているようなので,プルアップしている元の電源に問題があるのかもしれません。これが,SDA信号の立ち上がりにも影響している可能性もあります。どちらにしてもハードに問題があります。