「私は本当にそれをまったく理解していません。オンラインで何らかの方法でコメントに表示されるすべてのコードには、なぜそんなに多くのサイクルを実行しているのかというランダムな数字がありますが、文字通り、何が何をどこで何を誰が行うのかについての説明はありません.本当にわからない。」
「それは理解できますが、正確なタイミングがどこから得られるのかわかりません。どのように計算しますか? これらの数値はどこから来るのですか? VAR1 を 15 に設定すると、何が起こり、何が変化しますか? 3 つの遅延変数を 4、16、12 に設定すると、タイミングはどこから来るのでしょうか?これらの数値はどうなるので、ループは特定の時間になりますか?ありがとう – ジミー ペイジ"
私があなたの質問を理解したら:
16F690 データシートには次のように記載されています。
1 命令サイクルは、4 MHz のオシレータ周波数の場合、4 つのオシレータ周期で構成されます。これにより、通常の命令実行時間は 1 μs になります。すべての命令は、条件テストが真である場合、または命令の結果としてプログラム カウンターが変更されない限り、1 つの命令サイクル内で実行されます。これが発生すると、実行には 2 命令サイクルかかり、2 番目のサイクルは NOP として実行されます。
たとえば、Delay1 の値が 3 で、次のループがあるとします。
上
decfsz 遅延 1,f
トップへ戻る
decfsz を実行するたびに、在庫を 1 サイクル取得します。IF f がゼロで、スキップする必要がある場合は、2 サイクルの命令になります。goto を実行するたびに pc が変化するため、2 サイクルの命令になります。ループをたどると、次の形式を使用してこれを示します。
命令前の Delay1 値、命令、実行に使用されるサイクル、総サイクル数
3,decfsz,1,1
2,goto,2,3
2,decfsz,1,4
1,goto,2,6
1,decfsz,2,8
そのため、Delay1 が 3 から始まるループ自体は、4MHz で実行している場合、8 サイクルまたは 8us かかりました。最初にサイクルを計算してから、パーツのクロック レートを調整することが重要です。同じコードが 2mhz で実行されている場合は 16us、1mhz で実行されている場合は 32us になる可能性があります。
したがって、調べてみると、f 値が 1 でない場合、decfsz+goto ペアは 2+1=3 サイクルであることがわかります。値が 1 の decfsz を 1 回ヒットすると、2 サイクルになります。したがって、3 の Delay1 から開始すると、2 つの非 1 エントリ値 (3,2) が存在します。最後に decfsz をヒットしてスキップしたときの 2 サイクルを追加すると、合計サイクル ((3-1)*3)+2=8 になります。
Delay1 を 11 に設定してこのループに入った場合、((11-1)*3)+2=32 サイクル、7 は 20 サイクルになります。
さらに進んで、1 つの decfsz ループを別のループにラップすると、実行されるサイクル数が増え続けます。Delay1 が 3 で、Delay2 が 2 の場合
上
decfsz 遅延 1,f
トップへ戻る
decfsz 遅延 2,f
トップへ戻る
次に、Delay1 decfsz,goto ループの初回は 8 サイクルであることがわかっています。最初の decfsz Delay2,f は Delay2 が 1 ではないので 1 サイクル、合計 9 まであります。後藤はあと2本、合計11本。f メモリが 8 ビットであると仮定すると、2 回目の Delay1 ループに 0 で入ると、0x100 または 256 と考えて計算すると ((256-1) 3)+2=767 サイクル多くなります。 、これまでに合計 778 件。Delay2 は現在 1 であるため、これが最終的な decfsz Delay2,f であり、コストは 2 で、合計 780 サイクルです。そして、((Delay2-1) (((256-1)*3)+2))+(((Delay1)-1)*3)+に近い何かのサイクルを計算するアルゴリズムを考え出すことができます。 2)+((Delay2-1)*3)+2 サイクル。
そして、私のループはあなたのループよりも 1 decfsz ループ小さいですが、他の命令で始まるという点で私のループをあなたのループに似せると:
エントリ
動き.3
movwf Delay1
movl2.2
movwf Delay2
上
decfsz 遅延 1,f
トップへ戻る
decfsz 遅延 2,f
トップへ戻る
2 つの movlw と 2 つの movwf の 4 つのサイクルを、実行するサイクル数の全体的な式に追加する必要があります。
したがって、文字通り、なぜこれほど多くのサイクルを実行しているのか説明があります。そして、その説明はデバイスのデータシートにありました。
これをさらに進めましょう。patrickmdnet がリンクされているコード ジェネレーターを取得して、780 サイクルを生成します。
; 遅延 = 780 命令サイクル
; クロック周波数 = 4 MHz
; 実際の遅延 = 0.00078 秒 = 780 サイクル
; エラー = 0%
cblock
d1
d2
エンドク
;778サイクル
movlw 0x9B
movwf d1
movlw 0x01
movwf d2
遅延_0
decfsz d1, f
$+2 に移動
decfsz d2, f
Delay_0 に移動
;2サイクル
$+1 に移動
このループは、少し異なる設計になっています。
Delay_0 に到達する前に、f レジスタをロードする 4 サイクルから始めます。
あなたの質問のコードと上記の私の説明のように、内側の decfsz ループ goto は Delay_0 に直接分岐しません。これは decfsz d2,f をスキップします。したがって、そのループを通過するパスが 1 でない場合は、decfsz に 1 サイクル、goto $+2 に 2 サイクル、goto Delay_0 に 2 サイクル、1 でない d1 ごとに合計 5 サイクルがあります。そして、d1 が 1 である時間にさらに 2 つ追加します。これにより、((0x9B-1)*5)+2 = 772 サイクルが得られ、この前の 4 サイクルを追加すると、最大 776 サイクルになります。
興味深いことに、最後の decfsz d1,f は、d2 が 0x01 に設定された decfsz d2,f にヒットします。これは、スキップが保証されることを意味します。これは 2 サイクルです。d2 をロードするための movlw/movwf の代わりに、別の goto $+1 を使用した goto $+2 が同じことを行っていたでしょう。とにかく、この 2 サイクルの 1 つの命令で合計 778 サイクルになります。
780 に到達するには、さらに 2 サイクルが必要です。これは、goto $+1 で行われます。goto は pc を変更するため、常に 2 サイクルになります。プログラムに生成を依頼した 780 サイクルがあります。