AVRマイコンIC・ATtiny26Lに外付けの水晶発振器をつないでクロック源にする実験をしました。IC内蔵RC発振器と違って、いつでも正確なクロック周波数が得られます。
最初にDOC-49S3という3端子の水晶発振器をつないで見ました。周波数は1.308MHzです。以前「水晶発振器を使ったAMトランスミッタ」でも使用したものです。通販で入手できる水晶発振器の中ではこれが一番安価だと思います。秋月電子通商で5個100円でした。
回路図を下に示します。ATtiny26LはPB4(7番ピン)が「XTAL1」、PB5(8番ピン)が「XTAL2」という機能を持っています。外部発振によってクロックを生成する場合はこれらの端子を利用します。水晶発振器を接続するときは出力端子を「XTAL1」につなぎます。
水晶発振器を接続したら、「クロック周波数変更(その1)」の手順にしたがってヒューズビットを書き換えます。コマンドプロンプトを起動して、
と入力してから「Enter」キーを押せばOKです。水晶発振器など外部クロック信号をクロック源にする場合は周波数に関係なく上記のコード(1110 0000)になります。「ckset.bas」を実行してクロック周波数を測定したところ、ぴったり1.308MHzでした。
「LCDの表示(その5)」で時計表示のプログラム「lcd5c.bas」を実験しました。このときは時間が不正確でしたが、水晶発振器によって正確なクロックが得られたのでもう一度試してみました。元のプログラムは下記の通りです。
プログラムファイル lcd5c.bas
1 | $regfile = "at26def.dat" | ATtiny26Lを使用する。 | |
2 | $crystal = 1000000 | クロック周波数を1MHzに設定。 | |
3 | |||
4 | Config Lcdpin=Pin, Db4=Porta.4, Db5=Porta.5 | LCDのピン接続の設定。DB4=PA4, DB5=PA5。 | |
5 | Config Lcdpin=Pin, Db6=Porta.6, Db7=Porta.7 | LCDのピン接続の設定。DB6=PA6, DB7=PA7。 | |
6 | Config Lcdpin=Pin, E=Porta.3, Rs=Porta.2 | LCDのピン接続の設定。E=PA3, RST=PA2。 | |
7 | Config Lcd = 16 * 2 | 16文字×2行表示のLCDを使用する。。 | |
8 | |||
9 | Dim S1 As Byte | 秒カウント用変数「S1」を使用する。 | |
10 | Dim M1 As Byte | 分カウント用変数「M1」を使用する。 | |
11 | Dim S2 As String * 2 | 秒表示用変数「S2」を使用する。 | |
12 | Dim M2 As String * 2 | 分表示用変数「M2」を使用する。 | |
13 | |||
14 | Cursor Off | カーソルを表示しない。 | |
15 | |||
16 | Do | Doループの範囲ここから。 | |
17 | Cls | LCDの表示を消去する。 | |
18 | |||
19 | If S1 = 60 Then | 条件分岐のプログラムここから。 | |
「S1」が「60」になったら20, 21行目へ。 | |||
20 | S1 = 0 | 「S1」を「0」にする。 | |
21 | Incr M1 | 「M1」に1を加える。 | |
22 | End If | 条件分岐のプログラムここまで。 | |
23 | |||
24 | S2 = Str(s1) | 「S1」の値を文字に変換して「S2」に代入する。 | |
25 | S2 = Format(s2, "00") | 「S2」の表示形式を「00」にする。 | |
26 | M2 = Str(m1) | 「M1」の値を文字に変換して「M2」に代入する。 | |
27 | M2 = Format(m2, "00") | 「M2」の表示形式を「00」にする。 | |
28 | |||
29 | Lcd "Time " ; M2 ; "m" | LCDに「Time 」と表示、 | |
続いて変数「M2」と文字「m」を表示する。 | |||
30 | Lcd S2 ; "s" | LCDに変数「S2」と文字「s」を表示する。 | |
31 | |||
32 | Wait 1 | 1秒間待つ。 | |
33 | Incr S1 | 変数「S1」に1を加える。 | |
34 | Loop | Doループの範囲ここまで。16行目へ戻る。 | |
35 | |||
36 | End | 終わり。 |
このプログラムではDoループを一巡する間に秒のカウントが「1」増えます。ですからDoループ内のプログラムの実行時間がぴったり1秒になっていないと正確な計時はできません。そこで、「クロック周波数変更(その1)」でやったように、プログラムシミュレータを使ってDoループを一巡するのにかかる時間を調べてみます。その前にプログラム2行目「$crystal = 1000000」を「$crystal = 1308000」と書き換えます。時間が関係するプログラムではここの記述をクロック周波数にあわせる必要があります。それと32行目「Wait 1」を「Waitms 1000」にします。細かい時間を設定するためです。
プログラムをコンパイル(機械語に変換)してからシミュレータを起動し、最下段の経過時間を見ながらプログラムを少しずつ進めていきます。「Waitms 1000」のところは (Step into code)を何回もクリックしないと次に進まないと思います。Doループ内のどれかの行で、ループ1回目と2回目の経過時間を比較します。私は17行目「Cls」のところで比較しました。
上記の通り、ループ1回目の経過時間は「266.2439mS」、2回目は「1294.901mS」となりました。差し引き「1028.6571mS」、約1.029秒です。つまりこのプログラムをクロック周波数1.308MHzで動かすとDoループを一周するのに1.029秒かかります。これは「Waitms 1000」以外の部分で29mSかかっていることを意味します。この29mSが1秒あたりの誤差(遅れ)になります。そこでプログラム32行目「Waitms 1000」を「Waitms 971」に書き換えてみました(29mSだけ短くした)。
再度シミュレーションして時間を測りました。
1回目は前と同じ「266.2439mS」、2回目は「1265.781mS」で、差し引き「999.5371mS」になりました。つまり1秒あたり0.4629mSだけ進む計算になります。ぴったりとはいきませんが、前に比べるとだいぶマシになりました。
実際にプログラムを書き込んで動作させ、ストップウオッチを使って測定してみたところ、数分単位ならかなり正確な計時をしてくれました。もっとも、これでも24時間たつと40秒も進んでしまいますから、時計としては実用になりません。AVRマイコンで時計を作るには、特別な周波数の水晶発振子と時計専用のプログラムを用いるようです。
修正したプログラムへのリンクを下に掲げます。2行目が「$crystal = 1308000」、32行目が「Waitms 971」に変わっている以外は元のプログラムと同じです。
プログラムファイル lcd5c_2.bas
「EXO-3」という、分周器を内蔵した水晶発振器があります。今回使用した12.8MHzのタイプは、12.8MHz(原発振周波数)のほか、6.4MHz(1⁄2)、3.2MHz(1⁄4)、1.6MHz(1⁄8)などを出力できます。概要を下に示します。
これを使って、12.8MHzと1.6MHzをそれぞれクロックとして入力してみました。回路図は下記の通りです。ヒューズビットは前の3端子の水晶発振器と同じなので、配線だけを変えればすぐ動作します。
ATtiny26Lの最高周波数はデータシートでは8MHzとなっていますが、12.8MHzでも問題なく動作しました。また、EXO-3は分周比が大きくなるにつれて出力電圧が下がってきますが、8分周の1.6MHzでも大丈夫でした。いずれも時計表示のプログラムを動かしてちゃんと正確に計時することを確かめました。クロック周波数を頻繁に変更して実験したいときは、このようなタイプの水晶発振器が便利だと思います。