AVRには外部クロックがなくても動作するように、ICの内部にRC発振回路によるクロックを内蔵しています。
工場出荷時に規定の周波数(基本的に8MHz)になるように校正されていますが、データシートによると10%までの誤差がある可能性があり、シリアル通信では致命傷になります。
そこで、個別に調整できるようにOSCCAL(発振校正レジスタ)が存在します。このレジスタをプログラム実行時に書き換えることで発振周波数を変更できます。OSCCALが大きいほど高い周波数で、小さいほど低い周波数で動作します。
AVRはヒューズビットのCKOUTをプログラム(0)することにより、CLK0端子からシステムクロックが出力されます。これを測定機器で観測しながらOSCCALレジスタを操作することによりクロックを調整します。
校正
手元にあったATmega88を8Mhzに校正してみました。今回は周波数の測定には周波数カウンタを利用しました。もちろんオシロスコープで周波数を算出しても構いません。
工場出荷時の校正値はAVR ISP mkⅡを利用して読み出せます。この個体は0xbbになっていました。この状態での発振周波数はこのようになりました。
8.09MHzと少し高い周波数になっていました。誤差は+1.3%とデータシートの許容範囲10%に比べるとかなりよい精度です。が、少し高いので0xbaにしてみました。
0xbaにしたところ8.03MHz。これでもまだ高いので、0xb9にしてみます。
0xb9にすると7.99MHzと誤差は-0.13%とかなり高精度にできました。しかし、残念ながらCR発振は気温等に影響されるので常にこの精度を維持することはできません。あくまでも「今の環境」での周波数です。
実験
試しにどこまでいけるのか、CLK0端子を周波数カウンタに接続しながらいろいろとOSCCALを操作して動作周波数を見てみます。
OSCCALを0x00にしてみると、3.92MHz。
半分の0x7fでは、8.08MHz。あれ?0xb9の時より高い?
そこで、0x8fにしてみると、6.53MHz。データシートを読んでみると、最上位ビットは高周波範囲(1)か低周波範囲(0)かの選択になっているようで、この2つの範囲は重なっており、0x7fの時の方が0x80のときより高い周波数になっているようです。
最後にもっとも大きい0xffにしてみると、12.97MHzとなりました。
これほど範囲が広いのであれば無理矢理でよければ内蔵CRである程度の速度まで動かすことができそうです。
おまけ
周波数カウンタに接続したブローブをどこにもつながないと、商用電源のノイズを広うようで、60Hz近辺の周波数が表示されました。
4 コメント