ループ処理の実行時間について

こんにちは。マイコン初心者です。

R8C/15を使ってLEDの点灯を繰り返そうと思っています。
Timerを使わずに、ソフトウェアタイマ(for文のカウントアップで、
wait時間を作ろうと考えていました。
例えば1msecの時間をfor文で作ろうと思い、20Msecのクロック選択なので、
20MHzのクロックなので、1/20M=50nsecとなり、
20000倍にすれば1msec近くになると思っていました。
しかし、サイクル数のシュミレーションをみると、32768サイクル(約20msec)という結果になっていました。。。
単純に20msec/32768=610nなので1.6MHzがサイクル周波数となっています。
またシミュレータ同様にオシロでポートのON/OFFをオシロで確認すると、20msecぐらいかかっています。
クロックは初期化で20MHzに設定していると思うのですが、
何が原因は考えらますでしょうか?お手数ですがアドバイスいただけると幸いです。


参考までにプログラム(開発環境はHEW4.0)と実行時間結果の様子をのせておきます。
デバッガーが原因かと思い切り分けを行うためにRUNモードでも確認しましたが動作は同じになりました。

R8CデータシートURL:http://documentation.renesas.com/doc/products/mpumcu/rjj09b0176_r8c14hm.pdf

作成プログラム↓

======================================================
#include "sfr_r815.h"


// メインクロック切替関数 20MHz
void set_MainCLK(void)
{
 prc0 = 1;      // プロテクト制御(書き換え許可)
 cm13 = 1;      // Xin-Xout端子切り替え
 cm05 = 0;      // Xin-Xoutメインクロック発振
 cm06 = 0;      // 8分周以外(分周なし)
 asm("nop");     // 発振の安定待ち
 asm("nop");     //    (同上)
 asm("nop");     //    (同上)
 asm("nop");     //    (同上)
 ocd2 = 0;      // メインクロック選択
 prc0 = 0;      // プロテクト制御(書き換え禁止)
}

//メイン関数 Wait時間の確認 20000回のカウントアップで1msec
void main(void)
{
 int cnt;
 set_MainCLK();
 pd1_3=1;
 while(1)
 {
 p1_3=0;
 for(cnt=0; cnt<2000; cnt++); //wait 0.1msec
 p1_3=1;
 for(cnt=0; cnt<20000; cnt++); //wait 1msec
 }

}
======================================================

wait時間.pdf

 

 

Parents
  • チョコです。

    forループは1命令で実行できるわけではなく、複数の命令で実行されます。

    そのため、20MHzで動作時に20000回のループで1msecとなることはなく、

    遙かに長い時間が必要です。

    ループの実行時間を見積もるには、1ステートメントがどのような命令で構成

    されるかを確認して、そのうえで、概略の時間を見積もってください。

  • オンチップオシレータ32MHzの場合、こんな感じで大体1mSになるようです(CS+とE1で実験しました)。

    void DelayMsec(uint16_t cnt)

    {

    uint16_t i, j;

    for (i = 0; i < cnt; i++) {

    for (j = 0; j < 3541; j++);

    }

    }

    正確に調べたいのなら逆アセンブルしたソースを追いかける(それでも割込みが入れば変わるはず)・・・自分は面倒くさいからCS+の実行時間監視機能を使ったり、実際にプログラムを走らせてストップウオッチで30秒ほど計って「j<3541」の部分を調整してます。

    「LEDの点滅周期」と言う事なら実動作させて大体でOKって事でどうでしょう?

Reply
  • オンチップオシレータ32MHzの場合、こんな感じで大体1mSになるようです(CS+とE1で実験しました)。

    void DelayMsec(uint16_t cnt)

    {

    uint16_t i, j;

    for (i = 0; i < cnt; i++) {

    for (j = 0; j < 3541; j++);

    }

    }

    正確に調べたいのなら逆アセンブルしたソースを追いかける(それでも割込みが入れば変わるはず)・・・自分は面倒くさいからCS+の実行時間監視機能を使ったり、実際にプログラムを走らせてストップウオッチで30秒ほど計って「j<3541」の部分を調整してます。

    「LEDの点滅周期」と言う事なら実動作させて大体でOKって事でどうでしょう?

Children
No Data