AVRで遊んでみる。 2016.6.22
なぜAVRで遊んでみることにしたかは、後ほどゆっくり書くとして、
おもちゃを秋月電子で購入したので、早速遊んでみることにしました。
書き込み器はISP(In System Priograming)のものを使いました。
AVRはATMEGA328Pです。
早速動くように、ユニバーサル基板に5Vレギュレータを搭載した組み立てです。
こんな感じでまずは動作環境を整えます。
ソフトは
フリーで得られるAVR ATUDIO7を導入しました。これって800MBのサイズがあるので、最初のDLだけで数分かかってしまいます。
ソフトのインストールが終わったら、早速C言語で組んでみました。
いわゆるLEDチカチカではありませんが、I/OをON/OFFさせてみて、どの程度の速度で動くか試してみました。
CPUのクロックは水晶で10MHzを用いたので、1サイクルは100nSになります。
まずは、もっともシンプルなプログラムです。
このプログラムならなんと400nS(2.5MHz)で動くようです。
すなわち4サイクルです。1命令1サイクルと高速です。
もっともシンプルなプログラム。 1サイクル2.5MHzで動くようです。
一応、確認のためにNOP(No Operation)命令を4つ挿入して、確認です。
この4つの命令でサイクルは800nS(1.25MHz)になるはずですが、たしかに実測でも1.25MHzになっていますね。
4サイクル分のNOPを挿入。 1サイクル1.25MHzなので予想通りです。
PICで試してみましょう! 2016.6.25
遅いといわれるPICですが、ほんとうに遅いのか確認してみましょう。
いつもつかうSTANDARD版であるPIC16F886でプログラムを組んで、CCS-Cでコンパイルです。
PIC16F886では
まずは最短で動くプログラム作成です。 1サイクルは625kHzです。
プログラムの動作サイクルは625kHzです。AVRでは2.5MHzでしたので、ほんとうに1/4の速度で動くようです。
PIC16F1938では?
もうすこし最近のPICだったらどうか試してみましょう。
使う石をPIC16F1938に変更して、再コンパイルして実行してみましょう。
を!PIC16F1938では2.5MHzサイクルで動きます。
なんと、PIC16F1938に置き換えるだけで4倍高速になりました。
これはコンパイルの効率が上がっているのかな?
それともPIC内部の処理が高速になっているのかな?
いづれにしても、PICも新しいものに変えると高速に動くことが確認できました。
こりゃ、AVRは使わなくてもいいかな?
んん。。。。
こんな投稿をいただきました。
確認も含めて詳しく調べてみましょう。
ちなみに、動作は10MHzの外部発振は共通です。
基本的なプログラムのヘッダーは次のようになっています。
#include "16F1938.H" ここで使用するPICを定義 #fuses HS,NOWDT,PROTECT,NOMCLR,NOBROWNOUT,NOLVP,PUT #use delay(clock=10MHz) クロックは10MHzを宣言 #use fast_io(B) main() { set_tris_b(0x00); while(1){ output_high(PIN_B0); output_low(PIN_B0); } } |
ソース | PIC16F1938 | PIC16F883 |
ソースコードはPIC16F1938もPIC16F883も同じです。 |
2.5MHz/4クロックサイクル コンパイルコード 001B: BCF 03.5 001C: BSF 06.0 001D: BCF 06.0 001E: GOTO 01C |
625.6kHz/16クロックサイクル コンパイルコード 0018: MOVLB 02 0019: BSF 0D.0 001A: BCF 0D.0 001B: GOTO 019 |
2.0MHz/5クロックサイクル |
1サイクル 500kHz/20クロックサイクル |
|
1サイクル 1.666MHz/6クロックサイクル |
1サイクル 416kHz/24クロックサイクル |
単純な命令ばっかりです、PIC16F1シリーズはPIC16Fシリーズに比べてやっぱり早いようです。
PLLで内部クロックが4倍になっている?
マニュアルをみていると外部クロックもPLLで4倍で動くようにもみえます。
ということは最大で32MHzで動くPIC16F1シリーズなら、従来品の128MHz相当ってことかな?
もうすこし、詳しくみてみましょう。
PLLを動作させるかどうかはCONFIGURATIONのなかにPLLENビットがあります。
CONFIGURATION WORD2が1733ということはPLLENはONですね。これをOFFにすれば、1/4になるのかな?
ということで、早速CONFIGURATIONビットを変更してテストです。
これでなぞは解けたような気がします。内部処理がPLLで4倍になっていたのですね。
PLLEN=ON (2.5MHz) PLLEN=OFF (625kHz)
ちょっと気になる点が・・・・
動作がはやい分には問題ないのだけど、正確な時定数が必要な場合はdelay関数がつかえない(つかえるけど注意しないと)
ことになるので、この点は注意が必要です。
#use delay(clock=10MHz)
main() {
set_tris_b(0x00);
while(1){
output_high(PIN_B0);
delay_us(500);
output_low(PIN_B0);
delay_us(500);
}
}
ということで上記のように、500uSの遅延を2箇所いれて、1kHzの波形になるか確認してみましょう。
裏切られた・・・
発振周波数は4kHzです。ということはPLLの倍率がコンパイラが考慮を忘れている?
内部処理が4倍になっていますが、コンパイラがそれを考慮していない感じです。
周波数の定義値を変更してみましょう。
#use delay(clock=40MHz)
main() {
set_tris_b(0x00);
while(1){
output_high(PIN_B0);
delay_us(500);
output_low(PIN_B0);
delay_us(500);
}
}
出力が1kHzの周期になりました。
とすれば、無事1kHzになりましたが、こりゃ絶対に間違いそうです。
水晶を27MHzに変えてみる。
PLLで内部で4倍になっているとして、どこまで早い水晶がつかえるのかな?
と思って27MHzの水晶に変更してみました。
#use delay(clock=27MHz)
main() {
set_tris_b(0x00);
while(1){
output_high(PIN_B0);
output_low(PIN_B0);
}
}
1サイクル6.075MHz?
10MHzの水晶だと1サイクル2.5MHzだったので、27MHzになれば2.7倍の6.75MHzになるはずですが、
6.075MHzどまりです。ということで、PLLの動作限界を超えているのかな?
他の水晶でも試してみましょう。
結果だけですが、下記の結果です。
おそらく20MHzくらいが限界なのかな?という感じです。
水晶(MHz) | 実行サイクル (計算値) |
実測値 | 誤差 |
10MHz | 2.5MHz | 2.5001MHz | 0.004% |
12MHz | 3.0MHz | 3.0001MHz | 0.03% |
24.576MHz | 6.144MHz | 6.1492MHz | 0.08% |
27MHz | 6.75MHz | 6.0753MHz | 10.0% |
どうやら、その後のBSSの書き込みから内部がMAX32MHzなので、4倍PLLをつかう場合は
外部クロックは8MHzが最大値になるようです。素子のオーバスペックに期待すれば20MHzでもいけそうですが、
これは危険ですね。
され、結論的には内部PLLのおかげでPIC16F1シリーズは高速にはなるけれど、性能的には従来のPIC16Fと同じ
ということでしょうね。プログラム領域が増えたことが結構助かるところかもしれません。
そういえば、DAC9018Dなんかは、プログラム領域が97%くらいまでいっていて、それ以上のコマンドを入れられなかった
ということがありますが、PIC16F1シリーズに帰れば、追加のコマンドがいれられそうです。
(つづく?)