RL78/G13におけるCS+コード生成の簡易I2Cについて

失礼いたします。

MPU6050の慣性計測ICを用いるために簡易I2Cをコード生成にて使用できないかを実験中です。

データシートや他チップ用サンプルを覗いた限り下記に示すMain文で読めるものと考えたのですが上手くいきません。

データの行き来はE1エミュレータにて確認していますがR_IIC11_Master_Sendの各種割り込みは起動しています。

しかし、R_IIC11_Master_Receiveの完了割り込みは起動したりしなかったりするうえ、帰ってくるアドレスには何も入力されていません。


//起動
txd[0] = 0x6B*2;
txd[1] = 0x00;
R_IIC11_Master_Send(DeviceID,txd,2);
完了割り込み待ち
while (1U)
{
//IC読み出しメモリ番地指定
txd[0] = 0x3B*2;
R_IIC11_Master_Send(DeviceID,txd,1);
完了割り込み待ち
//IC読み出し要求
R_IIC11_Master_Receive(DeviceID,rxd,14);
完了割り込み待ち
50ms待機
}

大変恐縮ですが、ご回答よろしくお願いいたします。

  • チョコです。

    「通信完了待ち」を「完了割り込み待ち」で行われているようですが、INTIIC11は1バイト転送完了で発生します。

    R_IIC11_Master_SendやR_IIC11_Master_Receiveではスレーブアドレスの送信完了で発生するのですが、ここらは理解していますか。

    これまでも何度も言っていますが、コード生成の通信関係の処理には大いに問題があります。

    そこで、個人的にはコード生成は初期設定だけしか使いません。APIは全て自前でやっています。サンプルプログラム等の以下のプログラムが参考になるかと思います。

    IIC通信のマスタ側(RL78/G13の簡易IIC版)改 2C

    プロジェクトをzipにして添付してもらえれば、具体的なコメントができるのですが。

    以上

  • チョコ様

    お返事ありがとうございます。
    URL先を拝見いたしました。量が多いので理解するのに少々かかりそうです。

    プロジェクトですが、多くは記述していないためこの場に記述いたします。
    投稿時から割り込み部分をディレイに変えております。

    void main(void)
    {
    R_MAIN_UserInit();
    /* Start user code. Do not edit comment generated here */


    txd[0] = 0x6B*2;
    txd[1] = 0x00;
    IMU_IIC11_Send(DevicdID,txd,2);


    while (1U)
    {

    IMU_IIC11_Receive(DevicdID,MPU6050_AX*2,rxd,14);

    tag += 1;
    }
    /* End user code. Do not edit comment generated here */
    }

    void IMU_IIC11_Send(uint8_t adr, uint8_t * const tx_buf, uint16_t tx_num)
    {
    int i;
    SCR03 = 0xC000;
    R_IIC11_StartCondition();
    SIO11 = adr & 0xFE;
    wait_5us();
    for(i = 0; i < tx_num; i++)
    {
    SIO11 = tx_buf[i] & 0xFE;
    wait_5us();
    }
    R_IIC11_StopCondition();
    }

    void IMU_IIC11_Receive(uint8_t adr, uint8_t mem, uint8_t * const rx_buf, uint16_t rx_num)
    {
    int i;
    SCR03 = 0xC000;
    R_IIC11_StartCondition();
    SIO11 = adr | 0x01;
    wait_5us();
    R_IIC11_StopCondition();
    R_IIC11_StartCondition();
    for(i = 0; i < rx_num; i++)
    {
    SIO11 = (mem + 0x02 * i) | 0x01;
    wait_5us();
    rx_buf[i] = SIO11 & 0xFF;
    }
    R_IIC11_StopCondition();
    }

  • チョコです。

    MPU6050のデータシートを眺めると、I2Cバスでの書き込みは以下のようにスレーブアドレスの次にRA(レジスタアドレス)を送信し、その後にレジスタに書き込むデータを送信するという一般的なシーケンスです。

    読み出しは以下のようになっており、これも、最初にRA(レジスタアドレス)を設定するために書き込みを行い、リスタートして読み出しモードでスレーブアドレスを送信し、引き続いてレジスタの内容を読み出す動きです。これも一般的なアクセス方法です。

    MPU6050は使ったことがないので、netでArduinoでの使用例を探してみました。
    比較的簡単そうだったのは「メカトロDIYチャレンジ」でしたので、そこの内容を参考にしてみます。

    MPU6050をArduinoで使う①入門編 | メカトロDIYチャレンジ(Mechatro DIY Challenge) (mechadiy.com)

    setup()関数は以下のようになっていました。

    最初にMPU6050のレジスタ0x6bに0x00書き込むことで、MPU6050を起動するようです。Ouraさんのプログラムでは、なぜかRAが「0x6b」ではなく、「0x6B*2」と異なっています。Arduinoではスレーブアドレスは7ビットで、RL78では8ビットなので、0x68を2倍するはいいのですが、RAはそのまま0x6bとすべきは。データシートでMPU6050の内部レジスタのアドレスを確認できていないので、理由が分かりません。(もしかしたら、データが16ビット長なので、2倍したのですか。)

    txd[0] = 0x6B*2;
    txd[1] = 0x00;
    IMU_IIC11_Send(DevicdID,txd,2);

    また、ここで呼び出している IMU_IIC11_Send関数ですが、以下のようになっています。最初にSCR03のbit15とbit14を同時に1にしていますが、簡易IICモードではこれはやってはいけなかったはずです。なにを参考にしてこのような処理を行ったのでしょうか。

    void IMU_IIC11_Send(uint8_t adr, uint8_t * const tx_buf, uint16_t tx_num)
    {
    int i;
    SCR03 = 0xC000;
    R_IIC11_StartCondition();
    SIO11 = adr & 0xFE;
    wait_5us();
    for(i = 0; i < tx_num; i++)
    {
    SIO11 = tx_buf[i] & 0xFE;
    wait_5us();
    }
    R_IIC11_StopCondition();
    }

    さらに、データ受信でもSCR03を0xC000にしているのは間違いです。

    void IMU_IIC11_Receive(uint8_t adr, uint8_t mem, uint8_t * const rx_buf, uint16_t rx_num)
    {
    int i;
    SCR03 = 0xC000;
    R_IIC11_StartCondition();
    SIO11 = adr | 0x01;
    wait_5us();
    R_IIC11_StopCondition();
    R_IIC11_StartCondition();
    for(i = 0; i < rx_num; i++)
    {
    SIO11 = (mem + 0x02 * i) | 0x01;
    wait_5us();
    rx_buf[i] = SIO11 & 0xFF;
    }
    R_IIC11_StopCondition();
    }

    細かいところがきちんとできていないので、正常には動作しません。

    通常は、割り込み処理で細かな制御を行うのですが、それをやっていないように見えます。

    一度、動作しているサンプルプログラムをきちんと読まれることを推奨します。

    以上

  • 取り急ぎ回答を致します。

    なぜかRAが「0x6b」ではなく、「0x6B*2」と異なっています。

    の部分につきましてデータシート内のシリアルデータレジスタを15-9までが分周、

    7-1が受送信用データ、0がR/W判別と考えておりました。

    データ受信でもSCR03を0xC000にしているのは間違いです

    上記についても同様でシリアルデータレジスタのみでI2C制御可能と考えておりました。

    そのため受送信をオンにしておけばよいものと…

    現在は示して頂いたサンプルをIIC11に変えて試行中です。

    割り込み(INTIIC11、INTTM0)がうまく起動しないためデータシートとにらめっこをしております。

  • チョコです。

    >割り込み(INTIIC11、INTTM0)がうまく起動しないためデータシートとにらめっこをしております。

    Ouraさん、その後どうなりましたでしょうか。わりこみは許可されているのでしょうか。また割り込みのマスクは解除されているでしょうか。もう少し詳しい情報があれば、コメント可能なのですが。

    (INTTM0は存在しないので、INTTM00か何かでしょうか。)

    MPU6050のレジスタ・マップで確認したら、0x6Bは、以下に示すように、"PWR_MGMT_1"で初期値は0x40になっていて、SLEEPになっているようです。最初に行うのは、これをクリアしてスリープをする処理のようです。

    RL78/G13のSDRレジスタとは無関係です。

    以上

  • チョコです。

    もしかしたら、MPU6050は下の写真のボードではないですか。

    回路図は見つけられませんでしたが、右端の5PINはレギュレータだと思います。VCCには5V電源を接続し、レギュレータで3.3VをMPU6050のVDD(およびVLOGIC)に供給しているようです。MPU6050は以下のような動作条件になっています。

    気になったのが、簡易IIC11のSCL11はオープンドレインではなく、通常のCMOS出力です。RL78/G13の簡易IIC11と接続するなら、RL78/G13は3.3Vで動作させて、MPU6050のボードは5Vを供給する必要がありそうです。RL78/G13のSCL端子を調べてみると、簡易IICでのSCL01、SCL11、SCL21にはオープンドレインに設定するレジスタがなく、SCL00、SCL10、SCL20はオープンドレインに設定するレジスタがありました。

    ここらは、大丈夫でしょうか。

    以上

  • チョコ様

    返信が遅れてしまいました。

    時間関係の割り込み周りは起動するようになりましたが、ACKが返ってこないためその後の処理に進まないといった状況です。

    7bitと8bitの違いによるものかと睨んで試行錯誤していますが頂いたプログラムから作成しても状況に変わりは殆どないです。

    ボードは以下のものを使用しております。3.3V系で問題ないと考えております。

    www.digikey.jp/.../6588492

  • チョコです。

    3.3Vのレギュレータが内蔵されているようなので、信号レベルは3.3V系ですが、ボードのVINは5Vを供給する必要があるはずですが、どうなっていますか。VINに3.3Vを供給した場合にはMPU6050が何Vになるのか不明です。ここらがACKが戻らない理由かもしれませんね。

    CSI11では、SCLはCMOS出力なので、RL78/G13の電源電圧で出力されます。これは、ハードウェアの問題で、ソフトの設定では何も対応できません。

    時間を見て、部品の調達をして、ちょっと動作確認をチェックしてみます。

  • チョコです。

    QB-R55F100LEのIIC11にMPU6050を接続して動作確認を行ってみました。3.3Vできちんと動作しているようです。

    プロジェクトはできるだけ、コード生成された内容を使いました。IIC11関係では、IIC11の割り込み処理(r_cg_serial_user.c)に通信完了フラグ(g_iic11_status)を追加し、r_iic11_interruptのcallback処理でg_iic11_statusに通信結果を設定しています。

    このフラグに関して、クリアする関数(R_IIC11_Clear_status)、読み出す関数(R_IIC11_Get_status)、通信完了を待つ関数(R_IIC11_Wait_finish)も追加しています。

    このフラグを使った通信完了まで待つような簡易IICの読み書き関数をr_cg_serial.cの後ろのuser codeに準備しました。

    これを用いて、MPU6050を制御する関数を(MPU6050_LIB.c)に初期化関数と測定結果の読み出し関数を準備しています。

    main処理としては、初期化でMPU6050のスリープを解除し、1秒ごとに読み出すだけでの簡単な処理です。読み出した結果を以下に示します。

    データの妥当性等は検証していません。とにかく、IIC11を使って、MPU6050から計測結果を読み出せることを示しています。

    通信でエラーが検出されたら、エラーLEDを点灯するようにしていますが、いまのところエラーは検出されていません。

    コード生成されたAPIのR_IIC11_StartConditionに問題があったためにリスタートできなかったので、読み出し処理でレジスタアドレスを指定した後でいったんストップコンディションを発行するようにして対応はしました。

    動作確認したプロジェクトのzipファイルを添付しておきます。参考にしてください。


    MPU6050_IIC11.zip

    以上

  • チョコ様

    ファイルありがとうございます。

    動作を確認できました。

    コメントが丁寧に差し込まれていて何をすべきかの助けになりました。

    工作の対象にするには難易度が高くて諦めてしまうところでしたので本当に感謝いたします。