ATtiny10 用プログラム (8)

内蔵 8 MHz オシレータの周波数を測定するには、正確で安定な基準周波数が必要で、これは外部から与える必要があります。
ATtiny10 では、Timer0 および CPU コアのクロックとして外部クロックを選択すると、内部クロックの行き先はフラッシュ・メモリの書き換え回路 (NVM: Non Volatile Memory controller) だけとなり、Timer0 部分には供給されなくなります。
そのため、CPU コアおよび Timer0 のクロックとしては内部 8 MHz オシレータを選択し、Timer0 に外部から信号入力可能な端子に外部基準周波数を供給することになります。
Timer0 に外部から入力可能なのは、

  • 外部クロック端子 (T0 : 4 番ピン)
  • インプット・キャプチャ端子 (ICP0 : 3 番ピン)

のふたつだけです。
(正確にはアナログ・コンパレータ経由のインプット・キャプチャのルートもありますが、入力端子を 2 つ (AIN0 と AIN1) 消費するため実用的ではありません)
このうち、T0 から外部基準クロックを入力する方式は、構成としては「普通」の周波数カウンタと同様です。
しかし、測定対象の (不明な) 周波数のクロックから「ゲート・タイム」を作成し、周波数が既知な外部基準クロックをカウンタの入力とする点が、「普通」の周波数カウンタとは逆になっています。
前述のように、ここでは、この構成は取らず既存のライブラリを利用した「周期」カウンタの構成を取りました。
既存ライブラリ利用といっても、リソースに乏しい ATtiny10 では、動作させるためには、あちこちを削らなければなりませんでした。
現状、ギリギリで動作しており、変数を 1 バイトでも増やすと動作しなくなります。
また、ループを繰り返している途中でハングアップすることがあります。
これについては、OSCCAL を一通り変化させて測定できれば実用上十分なので、原因は追求せずにおきます。
基準クロックは連続的に与えておき、周期測定が終了したら、基準クロックをボーレート・クロックとして利用して、非同期 (調歩同期式) ソフトウェア・シリアルによって測定結果を外部に吐き出します。
ピン変化割り込みを利用して実現しているので、基準クロックの両エッジで割り込みがかかり、外部クロック周波数の 2 倍がボーレートとなります。
「周期測定」では、基準入力周波数は低いほど精度が高くなりますが、ボーレートが低くなることとの兼ね合いもあり、周波数は 600 Hz (ボーレートは 1200 bps) としました。
現状では、ATtiny10 は Arduino と接続したまま実験を行っているので、この 600 Hz クロックも「Arduino918」スケッチでは遊んでいるタイマ出力を利用して作り出しています。
回路図を下に示します。

ATtiny10 の 5 V CMOS レベルの出力を RS232C のレベルに変換するのにチャージポンプ内蔵のインターフェース IC、MAX232A (およびその互換品) を使った回路として示してあります。
Arduino のディジタル 9 番ピンから 600 Hz クロックを出力しています。
スケッチに下のリストで示すプログラムを追加し、setup() 関数内で Baud_clock_setup() 関数を呼び出しています。

#define BPS (600)

void Baud_clock_setup( void )
{
  pinMode(9, OUTPUT);
  TCCR1A = (_BV(COM1A0)); // toggle OC1A (Digital 9 pin)
  TCCR1B = (_BV(WGM12) | _BV(CS10)); // CTC mode, clk_io/1
  OCR1A  = (uint16_t)(-0.5 + (0.5 * F_CPU / BPS));
} // void Baud_clock_setup()

シンボル「BPS」を 600 と定義していますが、これは Arduino のディジタル 9 番ピンから出力される周波数を示しており、ATtiny10 の実際のシリアル出力のボーレートはこの倍の 1200 bps になります。
ATtiny10 に書き込む HEX ファイルを下に示します。
「osc_tn10_fixed.hex」

:100000000AC019C097C15CC1E0C015C014C013C0BC
:1000100012C011C010C011271FBFCFE5D0E0DEBF56
:10002000CDBF10E0A0E4B0E001C01D93AE34B10735
:10003000E1F748D0D4C1E4CF88ED8CBF16BF089556
:100040008F708A3010F4805D01C0895CA6D108955C
:10005000CF93DF93C82FD92F24E0969587952A95C3
:10006000E1F78F70EDDF2C2F3D2F2F70822FE8DF0F
:10007000DF91CF910895CF93DF93C82FD92F282FE9
:10008000392F832F82958F70DBDF2C2F3D2F832F0D
:100090008F70D6DF8C2F9D2F34E0969587953A95FB
:1000A000E1F78F70CDDF2C2F3D2F2F70822FC8DF0F
:1000B000DF91CF91089580E270D180E36ED188E71F
:1000C0006CD10895B9DF7BD1789414BD80E246C02D
:1000D00088ED8CBF84B589BFEEDF84B590E0B8DFD2
:1000E00088EE93E063D007C08AB781608ABF8895A5
:1000F0008AB78E7F8ABF8BA100008823A9F388EC82
:1001000090E054D007C08AB781608ABF88958AB7CB
:100110008E7F8ABF8BA100008823A9F3CCDF85A145
:10012000000096A1000094DFC6DF67A1000078A15F
:10013000000089A100009AA1000090E089DF87A15A
:10014000000098A10000A9A10000BAA1000093DF5F
:100150008DE023D18AE021D184B58F5F84BD84B541
:10016000853E08F4B5CFB2CFF8948BB58E7D8BBDAC
:1001700078941BA900000895F7DF8FEF9FEF97BDDC
:1001800086BD8EB583608EBD8DB5807E89618DBD47
:1001900011A9000010A90000FA98F8948AB58162AC
:1001A0008ABD8BB581628BBD78940895AA2797FD8F
:1001B000A095BA2F23E0B695A795979587952A9590
:1001C000D1F784A90000D8DF08951F930F930FB7CC
:1001D0000F9310E02F933F938F939F9394A1000070
:1001E00080A100008F5F80A9000080A10000891716
:1001F00008F45DC08BB58E7D8BBD83A1000080FFB0
:100200000BC085A1000096A1000097FD05C082A14A
:1002100000008F5F82A900008AA1000080FF0BC050
:1002200087A1000098A1000097FD05C089A10000EA
:100230008F5F89A9000089A1000022A1000090E041
:10024000821B910B9AA9000089A9000087A10000D8
:1002500098A1000025A1000036A10000821B930B8D
:1002600098A9000087A9000027A1000038A100007C
:1002700085A1000096A100002817390750F489A134
:1002800000009AA10000815090409AA9000089A91D
:10029000000081A1000090E08150904096A90000EC
:1002A00085A9000010A9000081E08BA900009F91A2
:1002B0008F913F912F910F910FBF0F911F91189523
:1002C0001F930F930FB70F9310E08F939F938AB5EF
:1002D0008AA9000082B593B598A9000087A90000FB
:1002E00080A1000089A9000081A10000982F9F5FD4
:1002F00091A90000882381F487A1000098A1000043
:1003000096A9000085A9000089A1000082A900002B
:100310008AA1000083A9000081A100008E3F19F48A
:100320008BB58F7D8BBD9F918F910F910FBF0F91DB
:100330001F9118951F930F930FB70F9310E08F9392
:100340008DA10000882311F410980DC08CA100002D
:1003500080FF02C0109A01C010988CA10000869501
:1003600080688CA900008DA100008F5F8DA900001E
:100370008DA100008A3021F48FEF8DA900009098A4
:100380008F910F910FBF0F911F911895F894889A34
:10039000909A789408959098089507C09AB79160BC
:1003A0009ABF88959AB79E7F9ABF9DA1000097FF3C
:1003B000F5CF8CA900001DA90000E8DF089581E0B9
:1003C00081B9109A119A8FEF8DA900008CA90000B5
:1003D000E2DF82E080BB8AB7817F8ABF0895F8940C
:0203E000FFCF4D
:00000001FF

ソースリストは次回の記事で示します。
ATtiny10 の PB1/ICP0 (3 番ピン) に 600 Hz を加え、上記プログラムを実行させると、PB0 (1 番ピン) から 1200 bps の「8N1」フォーマットの調歩同期式シリアル出力として次のような出力が出てきます。

 0x21 0xFD 0x1868F7
 0x22 0xFD 0x18862D
 0x23 0xFD 0x18BEDA
  . . . < 中略 > . . .
 0xE2 0x57 0x18BE0C
 0xE3 0x57 0x18E181
 0xE4 0x55 0x187B16

各行は、それぞれ、

    OSCCAL   p_den   p_num

の値です。
ATtiny10 では、10 進変換して出力する余裕はないので、16 進数として出力しており、C プログラムで読み込んでデータ処理する場合に便利なように、C 言語方式の「0x」プリフィクスを付けて出力しています。
これを Hyper Terminal や TeraTerm などのターミナル・ソフトでキャプチャしてテキスト・ファイル化します。
内蔵オシレータの周波数 foscを求める式は、外部から 3 番ピンに加えた周波数を fext として、

fosc = fext * p_num / p_den

で計算します。 もちろん、計算は整数ではなく実数で行います。
上の出力例の最初の行 (OSCCAL = 0x21) を例にとると、

fext = 599.97 [Hz]
p_den = 0xFD = 253.0
p_num = 0x1868F7 = 1599735.0

fosc = 599.97 * 1599735.0 / 253.0 = 3.7936 [MHz]

となります。