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シリーズに帰れば、追加のコマンドがいれられそうです。

(つづく?)