電子書籍の厳選無料作品が豊富!

初めて質問します。
現在pic12f675で遊んでいるのですが、
http://homepage3.nifty.com/mitt/pic/picc/picc675 …
にある、
// =================== 50uSウェイトルーチン ===============
static void wait_50uS() {
unsigned int cnt;
unsigned int i;
cnt = 2;
for(i=0 ; i<cnt ; i++) {
NOP();
}
}
の意味がわかりません。
特にfor(i=0 ; i<cnt ; i++) {
NOP();
}
の箇所です。
これでなぜ、50μsの待ち時間関数になるのでしょうか?
どなたか答えてくれませんか?

A 回答 (4件)

PIC12シリーズでは4クロックで機械語の1命令を実行します。


(ジャンプする命令では8クロック)
この事は例示されたソースリストに
//clock4MHz
//命令1μS
と書いてあることからも分かります。

C言語のソースをコンパイラが機械語に変換した時に何命令になるかは
最適化のレベルによって変わってきます。
例示されたソースリストについて最高の最適化がなされた場合は
  nop
  nop
  return
の3命令に変換されます。この場合は3usの時間待ちになります。
まったく最適化をなされない場合にどうなるかを考えて見ると以下のようになります。
static void wait_50uS() {
// 関数の入り口での処理
// WREGをセーブする 1CYC
// statusをWREGに入れて、RAMにセーブする 2CYC
unsigned int cnt;    // 0CYC
unsigned int i;     // 0CYC
cnt = 2;        // WREGに2を入れ、cntにセーブ 2CYC
for (i=0 ; i<cnt ; i++) {
        // 1回目のループ
        // i=0 ; WREGに0を入れ、iにセーブ 2CYC
        // i<cnt ; iをWREGにいれ、cntと比較、i<cntなのでNOP();を実行 4CYC
NOP();     // nop; 1CYC
        // i++ 1cyc
        // ループ開始へジャンプ 1CYC
}
        // 2回目のループ
        // i<cnt ; iをWREGにいれ、cntと比較、i<cntなのでNOP();を実行 4CYC
NOP();     // nop; 1CYC
        // i++ 1cyc
        // ループ開始へジャンプ 1CYC
        // 3回目のループ
        // i<cnt ; iをWREGにいれ、cntと比較、i<cntでないのでループを抜ける 4CYC
}
// 関数の出口での処理
// RAMにセーブした statusを元に戻す 2CYC
// セーブしたWREGを戻す 1CYC
// リターンする 1CYC
トータル29CYCなので実行時間は29usになります。
コンパイラがこのように変換しているとは限りませんが50usにはならないでしょう。
MPLABを使用しているのであればストップウォッチ機能で実行時間を測ってみてください。

なお、このようなコードはコンパイラのバージョンや最適化のレベル指定で実行時間が変わるのでアセンブラで記述するほうがいいです。
実行中に割り込みがかかると時間が延びるのでそれが不都合な場合には割り込みを禁止するかタイマーを利用するのがいいです。

この回答への補足

御返答いただきありがとうございます。
御察しの通りMPLABのv8.4を使っています。
break pointをはりつけるところまでは、調べてできたのですが、
デバッガーをクリックしても、select toolとclear memoryしか出てきません(・_・?)
もし、ご存知でしたらストップウォッチ機能の使い方を教えていただけないでしょうか?

補足日時:2009/11/01 17:58
    • good
    • 0

下記のようにセッティングしてください


Debugger -> Select Tool -> MPLAB SIM
Debugger -> Settings を指定して
     Osc/Trace タブを選んで Processor Frequencyに4MHzを設定
Debugger -> Stopwatch  を選択
ブレークポイントのところでStopwatchウインドーの「ZERO」をクリック
ステップ実行、または次のブレークポイントまでの時間を計る。

なお、View -> Disassembly List を選択すればコンパイラがどのように機械語に変換したかが分かります。
    • good
    • 0
この回答へのお礼

御返答ありがとうございます。
18μsとなりました。
いろいろ勉強させてもらい、感謝至極です。
アセンブリ言語も勉強したいと思います(;^_^A アセアセ・・・
お二人とも、ほんとにありがとうございました!

お礼日時:2009/11/02 15:58

 まず、CPUの1クロックで1行実行出来るわけではありません。


 Cプログラムの1行はコンパイラで数命令から下手すると20命令以上に
変換されます。
 さらに、SH2のようにパイプライン処理で1クロック1命令を実行出来る
マイコンの場合でも、外部 DRAMのように4 waitが入ってしまうと1クロ
ック1命令も怪しくなります。
 PIC16 がパイプライン処理をしているか知りませんが、こうゆうループは
実機で確認して合わせるしかないのが実情でしょう。
 とゆうわけで、4MHzなら4M行/s ではなく数倍処理速度が落ちると
考えた方が実用的です。
 こんな説明でいかがでしょう。
    • good
    • 0
この回答へのお礼

御返答ありがとうございます。

上のtadvsさんのストップウォッチ機能で確認してみます。

お付き合いいただき、ありがとうございましたm(_ _)m

お礼日時:2009/11/01 17:46

 この例題で使われているCPU CLOCK周波数の場合 for ループを2回


実行すると、約50マイクロ秒になるとゆう事です。
 ループの実行回数はCPUの種類、クロック周波数で調整する必要が
有ります。

この回答への補足

御返答ありがとうございます。
このマイコンのクロックは4MHzですよね?
ということは
1/4000000=0.00000025=0.25μsの処理能力をもつので、必要なループの回数は200回なのではないでしょうか?
調整しているとしたら、プログラムのどこでしているのでしょうか?
回答していただければありがたいです。

補足日時:2009/11/01 11:57
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!