AVRマイコンIC・ATtiny26Lのクロック周波数を変更する手順について書きます。マイコンICにAVRライターをつないで電源が入った状態にしておきます。ライターは別項「USB接続AVRライター」を使用しました。本当は「BASCOM-AVR IDE」上でやりたかったのですが、うまくいかないのでWindows XPの「コマンドプロンプト」を使ってやってみました。AVRライターの種類を選ぶのかもしれません。
ATtiny26Lのクロック周波数は、購入時(工場出荷時)には「内蔵RC発振器・1MHz」にセットされています。本当にそうなのか確かめるためのプログラムを考えました。LED点滅プログラムから「Wait」命令を取り除いたような形です。これを実行するとPA0出力にクロック周波数の10分の1の周波数の信号が出てきます。PA0〜GND間に周波数カウンタをつないで出力周波数を測定し、それを10倍すればクロック周波数を求めることができます。出力周波数は1MHz以下なので、デジタルテスタの周波数測定レンジなどでも間に合います。
プログラムは下記の通りです。BASCOM-AVRがインストールされたパソコンで下記リンクをクリックしてファイルをダウンロードすると、BASCOM-AVR IDEが自動的に立ち上がって画面内にプログラムが表示されます。
プログラムファイル clocktest.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | Config Porta = Output | ポートAを出力に設定する。 | |
4 | |||
5 | Do | Doループの範囲ここから。 | |
6 | Porta.0 = 1 | PA0の出力を「1」にする。 | |
7 | Porta.1 = 1 | PA1の出力を「1」にする。 | |
8 | Porta.0 = 0 | PA0の出力を「0」にする。 | |
9 | Porta.1 = 0 | PA1の出力を「0」にする。 | |
10 | Loop | Doループの範囲ここまで。5行目へ戻る。 | |
11 | |||
12 | End | 終わり。 |
Doループの中でPA0とPA1がそれぞれ1回オン・オフします。「Wait」命令がないので非常に高速でオン・オフします。なお、出力端子(PA0, PA1)は開放のままでOKです。LEDをつないでもかまいませんが、肉眼ではつきっ放しにしか見えません。
このプログラムで、Doループを一巡するのにどれくらいの時間がかかるか調べてみます。それにはBASCOM-AVRの「プログラムシミュレータ」を使います。プログラムをコンパイルしたあとシミュレータの画面を開きます。
ツールバーの (Step into code, 上図1番)を1回クリックすると、プログラムの1行目の左に青い矢印が出ます(上図2番)。この矢印は現在実行中のプログラムを示しています。ここで、画面の一番下を見ると「Cycl.=0 : 0mS」と出ています(上図3番)。これは、プログラムのサイクル数の進行と時間の経過を表わしています。
サイクルというのは、プログラムの実行に要したクロックパルスの数です。1サイクルあたりの時間はクロック周波数によって違います。クロック周波数が1MHzの場合は、クロックパルスの周期が1μSですから、1サイクル=1μS=0.001mSになります。 を1回クリックするたびプログラムは少しずつ進んでいきますが、それにつれてサイクル数と経過時間の数字も増えていきます。同じ1行でもプログラムの内容によって所要時間が違います。
6行目「Porta.0 = 1」まで進んだとき、サイクル数は「772」、時間は「0.772mS」になります。さらにプログラムを進めると10行目「Loop」に至り、次はまた6行目「Porta.0 = 1」に戻ります(「Do」では矢印が止まらない)。2回目に「Porta.0 = 1」まで進んだ時点でのサイクル数は「782」、時間は「0.782mS」でした。下の図の左が1回目の「Porta.0 = 1」、右が2回目の「Porta.0 = 1」です。ここで、2回目のときのサイクル数から1回目のときのサイクル数を差し引くと「10」になります。つまりDoループを1巡するのに10サイクル(10クロック)を要したということがわかります。時間に直すと10μSです。
PA0は(PA1も)Doループがひと回りする間に1回「1」になり、また「0」に戻ります。つまり10サイクル(10μS)周期で同じ動作を繰り返します。周期が10μSということは、周波数に直すと100kHzです。したがって、もしクロック周波数が1MHzぴったりなら、PA0〜GND間(あるいはPA1〜GND間)に周波数カウンタをつなげば、100kHzを表示するはずです。逆に言えば、周波数カウンタの表示値の10倍がクロック周波数ということになります。
実際に上記のプログラムを実行し、PA0に周波数カウンタをつないでみたところ、測定値は「101.7kHz」になりました。つまりクロック周波数はその10倍の「1.017MHz」と判明しました。やっぱり少しずれていますね。IC内蔵発振器の周波数はICの温度や電源電圧によっても変わります (温度が低いほど周波数が高くなる。電源電圧が高いほど周波数が高くなる。)
プログラム各行のサイクル数とポート出力の関係をタイミングチャートで表わすと下の図のようになります。
クロック周波数を知るにはもっと簡単な方法があるかもしれませんが、あとで行なう実験の都合もあって、サイクル数と時間のことを少し詳しく書きました。
クロック周波数を変更するには、「ヒューズビットの書き換え」ということをしなければなりません。まず、ATtiny26Lの現在のヒューズビットがどうなっているか調べます。実は、この操作は別項「AVRマイコン回路の製作」でやった動作テストと同じです。繰り返しになりますが、ここでもう一度手順を説明します。
まずWindows XPのコマンドプロンプトを起動します。パソコンの画面で「スタート」→「すべてのプログラム」→「アクセサリ」とたどって、「コマンドプロンプト」というところをクリックします。すると黒いウィンドウが出ます。これがコマンドプロンプトです。コマンドプロンプト内には英文で数行の表示が出ていますが、最後の行の末尾にカーソルが点滅しています。ここに、
avrezusb -rf
と入力します。「avrezusb」と「-rf」の間には半角のスペースが入ります。入力したらキーボードの「Enter」を押します。ATtiny26Lのヒューズビットが購入時のままの状態なら下記のように表示されるはずです。
この「Low: 〜」、「High: 〜」の部分がATtiny26Lの現在のヒューズビットです。「Cal: 〜」も何かの設定を表わしているのでしょうが、今はわかりません (その後判明しました。後述)。クロック周波数に関係するのは「Low: 〜」の部分です。「:」(コロン)の後の8桁の数字を書き換えます。ここまでのコマンドプロンプトの画面のようすを下に示します。
ヒューズビットを書き換えるには、コマンドプロンプトのカーソルが点滅している部分に
avrezusb -fl00000000
と入力します。「f」の次は小文字の「l」(エル)です。「Low: 〜」の部分を書き換えるので「-fl」になります。今は関係ありませんが、「High: 〜」の部分を書き換えたいときは「-fh」と書きます。「-fl」に続く8桁の数字はクロック周波数を何MHzにするかによって違ってきます。ATtiny26Lの内蔵RC発振器の周波数は1, 2, 4, 8MHzの4種類を選択できます。それぞれ次のようなコードになります。見やすくするために上4桁と下4桁の間を空けて書きますが、実際に入力するときは詰めて書いてください。間を空けるとエラーになります。
現在はクロック周波数が1MHzなので「Low:11100001」と表示されていたわけです。クロック周波数を2MHzに変更したいときは、
と入力してから「Enter」キーを押します。すると画面には
という表示が出ます。これでクロック周波数の変更は完了しました。念のため、もう一度ヒューズビットの読み出しを行なって確認します。「Low:11100010」に変わっていればOKです。コマンドプロンプトの画面のようすを下に示します。
上記の手順でクロック周波数を変更し、最初に挙げたプログラムで実際のクロック周波数を測定してみた結果は次の通りです。4MHzと8MHzの誤差が大きいのが気になります。測定方法に問題があるのでしょうか。8MHzだけ桁数が少ないのは、測定に使った周波数カウンタ(デジタルテスタ)の仕様です。
本来なら、クロック周波数を変更したときはプログラム中の「$crystal = 1000000」の記述も変更しなければなりませんが、今回のテストプログラムは「Wait」などの時間に関する命令を含んでいないので、そのままでも大丈夫です。
(以下、2007年3月5日に追記)
上記の周波数誤差について「AVR試用記」のkumanさんからメールでご教示をいただき、プログラム上で校正できることを知りました。kumanさん、ありがとうございます。
ヒューズビットを読み出したときに表示される「Cal 169 173 160 163」は内蔵RC発振器を使うときの補正値だそうです。左から順に1MHz, 2MHz, 4MHz, 8MHzの値で、数値は個々のICによって違います。内蔵RC発振器の周波数の精度を上げるには、発振校正レジスタOSCCALにこの補正値を書き込む必要があります。具体的には、プログラムの冒頭部分に「Osccal=169」のように記述すればよいとのことです。さっそく試してみました。
まず、ATtiny26Lにライターをつないでヒューズビットを読み出します。私の場合は下記のように表示されました。「Cal」値が上記と違うのは、別のICを使用したためです。
クロック周波数が8MHzの場合を例に取ると、8MHz用のCal値は「171」です。よって、テストプログラムの3行目に「Osccal = 171」と書きました。下記のようなプログラムになります。2行目は「$crystal = 8000000」と書いてありますが、もちろんヒューズビットを8MHz用に書き換えなければ8MHzになりません。
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 8000000 | クロック周波数を8MHzに設定。 | |
3 | Osccal = 171 | 内部発振器の補正値を「171」とする。 | |
4 | Config Porta = Output | ポートAを出力に設定する。 | |
5 | |||
6 | Do | Doループの範囲ここから。 | |
7 | Porta.0 = 1 | PA0の出力を「1」にする。 | |
8 | Porta.1 = 1 | PA1の出力を「1」にする。 | |
9 | Porta.0 = 0 | PA0の出力を「0」にする。 | |
10 | Porta.1 = 0 | PA1の出力を「0」にする。 | |
11 | Loop | Doループの範囲ここまで。6行目へ戻る。 | |
12 | |||
13 | End | 終わり。 |
このプログラムを実行してクロック周波数を実測してみたところ、8.15MHzでした。未校正のときは8.55MHzでしたので、大幅に改善されました。他のクロック周波数でも試してみたので、結果を下に記します。2MHzだけはなぜか誤差が増えてしまいましたが、それ以外は好結果が得られました。なお、実験時の室温は15℃、ICの電源電圧は5.03Vです。
1MHz | 2MHz | 4MHz | 8MHz | ||||
校正前 | 校正後 | 校正前 | 校正後 | 校正前 | 校正後 | 校正前 | 校正後 |
1.015 | 1.015 | 2.012 | 2.034 | 4.250 | 4.052 | 8.55 | 8.15 |
Cal値を少しずつ変えると、クロック周波数を微調整することができます。下の表はその実験の結果です。
1MHz | 2MHz | 4MHz | 8MHz | ||||
Cal値 | 周波数 | Cal値 | 周波数 | Cal値 | 周波数 | Cal値 | 周波数 |
未校正 | 1.015 | 未校正 | 2.012 | 未校正 | 4.250 | 未校正 | 8.55 |
179 | 1.015 | 181 | 2.034 | 171 | 4.052 | 171 | 8.15 |
178 | 1.011 | 180 | 2.026 | 170 | 4.036 | 170 | 8.12 |
177 | 1.006 | 179 | 2.012 | 169 | 4.013 | 169 | 8.07 |
176 | 1.002 | 178 | 2.004 | 168 | 3.999 | 168 | 8.05 |
175 | 0.991 | 177 | 1.993 | 167 | 3.967 | 167 | 7.98 |
(追記ここまで)
ATtiny26Lは内蔵RC発振器のほか、外付けの発振回路(水晶発振器など)をクロック源にすることもできます。それについては「クロック周波数変更(その2)」以降をご覧ください。