Software CPU Clock Speed Control (p.194)非公式訳

CPUのクロック速度をソフトウェアで制御する

AVRマイコンのデータシートを見ると、9.12.2 CLKPR - Clock Prescale Register というセクションがあります(訳註: 2018年DS40002061A版)。このレジスタの下位4ビットCLKPS<3:0>を使うと、1~256の範囲(ただし2の整数乗に限る)でCPUのクロック速度が分周できます。したがって、たといデフォルトの状態でメインシステムクロックが8 MHzで動作していても、消費電力を本当に抑えたい場合や余計な速度が不要の場合はCPUのクロック速度を8 MHz÷256 = 31.25 kHzまで落とすことができます。

何かの拍子にCPUのクロック速度が変わってしまっては困りますので、その対策としてClock Prescaler Change Enableビットが用意してあります。プリスケーラービットへの書き込みは、Clock Prescaler Change Enableビットをセットしてから4 CPUクロックサイクル以内に行わなければなりません。このタイミングは非常にシビアであるため、クロック速度が簡単に変更できる函数がavr-libcライブラリーに用意してあります。このCPUプリスケーラーマクロ函数avr/power.hライブラリーに入っています。あらかじめ組み込んであるこうしたライブラリーで分周比を設定する利点は、ひとつは細かなタイミングに気を遣う必要がないことであり、もうひとつはわかりやすい名前の付いたマクロが分周比ごとに定義してあることです。

フルスピードである8 MHzに設定するときは、下の2行をコードに追加するだけで済みます。

#include <avr/power.h>           // <avr/power.h>をインクルードして、
clock_prescale_set(clock_div_1); // この行をmain()ブロックに記述する。

また、CPUのクロック速度を0.5 MHzにして消費電力を抑えたい場合は下の行をmain()ブロックに記述してください。

clock_prescale_set(clock_div_16);

ここで注目してほしいのは、ソフトウェアでCPUのクロック速度を設定した場合はヒューズビットの設定は基本的に無視されるということです。つまり、デフォルトである1 MHzで動作するようヒューズビットを設定した場合であっても、CPUのクロック速度はソフトウェアで上げることも下げることもできるということです。ヒューズビットの設定は、ソフトウェアの設定で書き換えの可能なデフォルト速度であると見なすことができます。

CPUのクロック速度を極端に遅く設定した場合は、相対的にフラッシュプログラマーの通信速度が極端に速くなってしまいかねないことに気をつけなければなりません。このようにCPUのクロック速度を落とした結果、フラッシュプログラマーが機能しなくなった場合は、CPUのクロック速度に合わせてフラッシュプログラマーの速度も落とす必要があります。AVRDUDEの場合は、-Bフラグを使ってビットクロックを大きな値(遅い値)に設定し直してください。clock_div_256を指定して極端に遅い速度でCPUを動作させている場合は、-B 200程度まで上げないとマイコンにプログラミングできないことがあります。

また、コードの内部でCPUのクロック速度を動的に変化させる場合はすべての速度が変化してしまうことにも気をつけてください。_delay_ms(100)函数のような函数は指定の遅延時間が得られないことがありますし、シリアル通信ルーチンはまったく機能しなくなります。この種の函数は、動作すべき速度を#define F_CPUマクロで計算しています。CPUのクロック速度をコードの内部で動的に変える場合は、現在設定してある速度がmakeファイル内のF_CPU定義(F_CPUをコード内で定義することにした場合はコード内のF_CPU定義)に一致しない限り、遅延函数もシリアル通信ルーチンも機能しません。

ただし本書はinitセクションで一度だけCPUのクロック速度を設定し、あとはそのままにしています。makeファイルごとに専用のF_CPU定義も用意してあるはずですので、CPUのクロック速度について心配する必要はありません。CPUのクロック速度について考えなければいけないのは、CPUのクロック速度を複数組み合わせる場合だけです。たとえばF_CPUに定義してあるのとは別のクロック速度でシリアルポートを使う必要のある場合は、マイコンを初期化し直して新たなクロック速度に一致させなければなりません(それよりも、CPUのクロック速度は動的には変化させないのが無難です)。