公開日:2025/11/29
title.png

37th Season


#37-3 可変周波数クロック発振器(さん)

 前回、可変周波数クロック発振器を完成させたのですが、MHzオーダの高速なクロック出力を確認する手段が無くて、ひとまず1kHzという遅いクロックの出力波形を確認して終了していました。今回はMHzオーダの高速クロックを出力して、評価してみたいと思います。

MCUを駆動する

 可変周波数クロック発振器の評価方法ですが、何しろMHzオーダのクロックを評価しなくてはなりません。手元にはオシロスコープ〰等の測定機器が無いので、直接観測する事ができないのです……。そこで、出力クロックCLKOでマイコン(MCU)を駆動し、その挙動でCLKOの周波数を間接的に評価しようと考えました。

 例えば、周波数fCLKO[MHz]のクロックCLKOを出力しておき、これをMCU(ATmega328等)の外部クロックとして入力、駆動します。その上で、MCUから適切なPWMを出力して、そのPWMの周波数fPWMを測定します。
 PWMの周期はMCUのクロック周波数fCLKOをN分周したものですから、PWMの周波数が判れば、元となったCPUのクロック周波数fCLKO=fPWM×Nと判ります。

328duinoを駆動する

 出力クロックCLKOで駆動するMCUには328duinoを採用します(下図およびリンクを参照)。

ar95_schem1.pngar95_328duino_1.jpg

 328duinoの第一形態(上左図)は、外部に接続した水晶発振子で発振したクロックによって動作する様になっています(水晶発振モード)。328duinoは、ほぼATmega328ですから、ヒューズLのCKSELフィールドを書き換えると、外部クロック入力モードに設定する事は可能なのですが、ヒューズを書き換えるのは結構面倒なのです。

 ちょっと乱暴ですが、水晶発振モードのままで外部からクロックを入力してしまいます。下図は一般的な水晶発振回路です。

ar95_osc.png

 上図の水晶発振子XTALと負荷容量CL1,2がATmega328の外部に接続されていて、水晶発振しています。それ以外の素子はATmega328のチップ内に集積されています。水晶発振子と負荷容量を取り外してしまって、X1(XTAL1)端子からクロックを入力すると、そのクロックで動作させることができます。

 内部の帰還抵抗Rfが、発振ドライバOSCからの出力をぶつけてくるので、外部から入力してくるドライバと喧嘩になります。しかし、一般にRfは高抵抗(100k〜10MΩ)なので負ける事は無く、外部クロックを入力することができます。

※ダンピング抵抗Rdは低抵抗なので(0Ωの場合も多い)、X2(XTAL2)端子からクロックを入力しようとすると、発振ドライバOSCの出力と完全に喧嘩になります。ドライバのトランジスタ(ON抵抗)を通して、互いの電源−GND間が短絡するので、LSIが破壊に至る恐れがあります。必ず、X1(XTAL1)端子側から入力してください。

 と、言う事で、実験用に328duino(第一形態)を用意しましょう。

実験装置

 全体の実験装置としては、概ね以下の様になると考えています。

 図にしてみると、以下図の様な感じです。

a373_evalsys.png

 手持ちの測定機器では、MHzオーダのCLKO周波数を直接計測する事はできませんが、それを1/1,000分周したPWMを出力しておくと、そのPWMの周波数は充分低い為、計測可能です。計測したPWM周波数を×1,000倍すると、元のCLKO周波数を知ることができます。

 贅沢にも3個のマイコンが登場しますが、評価したいDUT(Design Under Test)は、可変周波数クロック発振器としてのATtiny85です。お忘れなき様。

評価用プログラム

 ATtiny85に書き込む可変周波数クロック発振器としてのソフトウェアは、前回完成させたプログラム(ti85_vclkgen.ino)を使います。

 今回、UNOと328duinoへ書き込む評価用のプログラムは、1本にまとめてしまいました。以下にリンクしておきます。

  評価用プログラム:pwm_freq.ino

 328duino用のPWM出力機能と、UNO用の入力PWM周波数計測機能が、上のプログラムに詰まっています。コンパイルして、UNOと328duinoへ書き込んでください。
 各々、シリアルモニタを開くと、以下のコマンドを受け付ける様になっています。

  シリアルモニタコマンド仕様:

 「各々」と言っても、上のコマンドはPWM周波数を計測するホスト側であるUNO用なので、ターゲット側328duinoでは使いません。従って、ターゲット側328duinoにシリアルモニタ(USB⇔UART変換モジュール)を接続する必要はありません。

MHz級の実験

 こちらの実験装置を組み立ててて、準備しましょう。各々必要なプログラムを書き込んだATtiny85、Arduino UNO、328duinoを、以下表に従って接続してください。

Arduino UNO 接続 ATtiny85 接続 328duino※
5V VCC VCC
GND GND GND
A5(SCL) D2(SCL)  
A4(SDA) D0(SDA)
  D4(CLKO) XTAL1※
D8(ICP1) D3(OC2B)

※328duinoは、第一形態から水晶発振子と負荷容量を取り外してください。

 以下図に実験中の様子を示します。

a373_expr.jpg

高速クロックの評価

 実験サンプルに従って評価を進めます。

  実験サンプル:【 】内はUNOシリアルモニタからの送信データ
  【show,1】
  OK: show 1 (1000[ms])
  SHOW: freq[Hz],8044,8048

 可変周波数クロック発振器(ATtiny85)のデフォルト8MHzクロック出力から生成した、1/1,000分周PWMの周波数8,044Hz(瞬間値)、8,048Hz(平均値)が計測できました。従って、元のCLKO出力周波数は×1,000倍の8.048MHz(平均値)です。
 周波数−OSCCAL変換表の解像度などを考慮すると、狙い通りの周波数と言って良いでしょう(誤差約0.6%)。

 出力クロック周波数を変更して見ましょう。

  【swr1,2,30,00,01,00】
  OK+ swr1.0c[0x02]=0x30 ……OSCFRQ=7MHz(0x30=(7MHz−4MHz)×16)
  OK+ swr1.0c[0x03]=0x00 ……PLLCSR=×8逓倍
  OK+ swr1.0c[0x04]=0x01 ……TCCR1=PCK/1
  OK+ swr1.0c[0x05]=0x00 ……OCR1C=0x00(PWM周期=(0x00+1)×2)
  OK: swr1 4

 出力クロックCLKO周波数を7MHz×8逓倍÷1分周÷(1×2)周期=28MHzに設定しました。328duinoのfCPUが28MHzになりました。確認して見ましょう。

  【show,1】
  OK: show 1 (1000[ms])
  SHOW: freq[Hz],28119,28159

 こちらも設定通りの周波数が計測できました(誤差約0.6%)。ATmega328の最高動作周波数20MHz @5Vを遥かに超えていますので、皆様お手元の個体で動作する保証は有りません。もし動作しなかったら、少し周波数を下げてみてください。
 328duinoにLED_BUILTINを接続しておくと、一定時間毎に点滅します。クロック周波数が速すぎて328duinoが正常動作しなくなると、点滅が停止するので判ります。
 この調子で周波数を上げて行ったところ、CLKOが29MHzになったあたりから、328duinoの動作が停止する場合がありました。30MHzでは、確実に動作を停止してしまいます。手元の個体は、実力で28MHz辺りまでは動作可能な模様です。

PLLの実力評価

 続いてPLLの実力を確認してみます。

  【swr1,5,04】……OCR1C=0x04(PWM周期=(0x04+1)×2)
  OK: swr1.0c[0x05]=0x04

 I/Oレジスタに書き込んだ瞬間に新しい値が有効なので、書き込む順番に注意です。前の実験(CLKO @28MHz)の直後、OSCFRQレジスタを書き込んでしまうと非常に高速なクロックが出力されてしまうので、先にOCR1Cレジスタへの書き込みを実施しました。

  【swr1,2,d0,00,01】
  OK+ swr1.0c[0x02]=0xd0 ……OSCFRQ=17MHz(0xd0=(17MHz−4MHz)×16)
  OK+ swr1.0c[0x03]=0x00 ……PLLCSR=×8逓倍
  OK+ swr1.0c[0x04]=0x01 ……TCCR1=PCK/1
  OK: swr1 3

 上の書き込みによって、クロックCLKO周波数を17MHz×8逓倍÷1分周÷(5×2)周期=13.6MHzに設定しました。確認しましょう。

  【show,1】
  OK: show 1 (1000[ms])
  SHOW: freq[Hz],13698,13704

 これも設定通りの周波数が観測できました(誤差約0.8%)。
 ですが、この設定ですと、PLLの出力周波数が17MHz×8逓倍=136MHzとなっています。それを1/10に分周して出力した13.6MHzです。思い出してみてください、ATtiny85データシートによると、PLLの周波数は85MHz(MIN)で飽和すると記載されています。
 データシートの規定通りだとするなら、13.6MHzではなく、8.5MHzが観測されるべき条件です。
 実はこの規定はMIN規定なので、「個体によっては、もっと高い周波数まで発振する場合がありますよ」って事なのです。実際、手元のATtiny85では、PLLが85MHzを遥かに超えた136MHzで、しっかり発振したことが確認できました。


 めでたく、ATtiny85で作った可変周波数クロック発振器のMHzオーダでの動作確認が済みました。お陰で328duinoの最高動作周波数fMAXも計測できたし、任意のクロック周波数を出力できる事は、それなりに「需要がある」のではないでしょうか?


btn_arduino.png

btn_prev.png btn_next.png

home