- ベストアンサー
pic12f675の待ち時間関数について
初めて質問します。 現在pic12f675で遊んでいるのですが、 http://homepage3.nifty.com/mitt/pic/picc/picc675_04_1.html にある、 // =================== 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の待ち時間関数になるのでしょうか? どなたか答えてくれませんか?
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
PIC12シリーズでは4クロックで機械語の1命令を実行します。 (ジャンプする命令では8クロック) この事は例示されたソースリストに // clock 4MHz // 命令 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を使用しているのであればストップウォッチ機能で実行時間を測ってみてください。 なお、このようなコードはコンパイラのバージョンや最適化のレベル指定で実行時間が変わるのでアセンブラで記述するほうがいいです。 実行中に割り込みがかかると時間が延びるのでそれが不都合な場合には割り込みを禁止するかタイマーを利用するのがいいです。
その他の回答 (3)
- tadys
- ベストアンサー率40% (856/2135)
下記のようにセッティングしてください Debugger -> Select Tool -> MPLAB SIM Debugger -> Settings を指定して Osc/Trace タブを選んで Processor Frequencyに4MHzを設定 Debugger -> Stopwatch を選択 ブレークポイントのところでStopwatchウインドーの「ZERO」をクリック ステップ実行、または次のブレークポイントまでの時間を計る。 なお、View -> Disassembly List を選択すればコンパイラがどのように機械語に変換したかが分かります。
お礼
御返答ありがとうございます。 18μsとなりました。 いろいろ勉強させてもらい、感謝至極です。 アセンブリ言語も勉強したいと思います(;^_^A アセアセ・・・ お二人とも、ほんとにありがとうございました!
- f-tomohiko
- ベストアンサー率50% (11/22)
まず、CPUの1クロックで1行実行出来るわけではありません。 Cプログラムの1行はコンパイラで数命令から下手すると20命令以上に 変換されます。 さらに、SH2のようにパイプライン処理で1クロック1命令を実行出来る マイコンの場合でも、外部 DRAMのように4 waitが入ってしまうと1クロ ック1命令も怪しくなります。 PIC16 がパイプライン処理をしているか知りませんが、こうゆうループは 実機で確認して合わせるしかないのが実情でしょう。 とゆうわけで、4MHzなら4M行/s ではなく数倍処理速度が落ちると 考えた方が実用的です。 こんな説明でいかがでしょう。
お礼
御返答ありがとうございます。 上のtadvsさんのストップウォッチ機能で確認してみます。 お付き合いいただき、ありがとうございましたm(_ _)m
- f-tomohiko
- ベストアンサー率50% (11/22)
この例題で使われているCPU CLOCK周波数の場合 for ループを2回 実行すると、約50マイクロ秒になるとゆう事です。 ループの実行回数はCPUの種類、クロック周波数で調整する必要が 有ります。
補足
御返答ありがとうございます。 このマイコンのクロックは4MHzですよね? ということは 1/4000000=0.00000025=0.25μsの処理能力をもつので、必要なループの回数は200回なのではないでしょうか? 調整しているとしたら、プログラムのどこでしているのでしょうか? 回答していただければありがたいです。
補足
御返答いただきありがとうございます。 御察しの通りMPLABのv8.4を使っています。 break pointをはりつけるところまでは、調べてできたのですが、 デバッガーをクリックしても、select toolとclear memoryしか出てきません(・_・?) もし、ご存知でしたらストップウォッチ機能の使い方を教えていただけないでしょうか?