システムクロック【STM32のSYSCLK設定詳細 】
システムクロックはマイコン固有のものですので一度設定すると変更するものではありませんが、しっかり理解することで他のマイコンへの応用ができるようになります。
マイコンのクロック
この章では水晶振動子などの発振器で発生したクロック信号をもとにしてマイコンの動作周波数となるシステムクロックの作成の仕方、各ペリフェラルに供給するクロックの設定について解説します。
クロックとは組み込み技術の基本の章で説明しましたがマイコンのCPUを始めとし、すべての回路のタイミングとなるパルス信号のことです。組み込み機器でのクロック設定はマイコンの性能を発揮する動作速度を確保したうえで、できるだけ消費電力を押さえるために重要なものです。
各ペリフェラルの設定をするときにどの速度のクロックが供給されているかを認識することは大切です。マイコン入門者にとって初めは少し難しいかもしれませんが、すべて理解する必要はなく使うところだけを重点的に一度仕組みを理解してクロック設定の機能をまとめたブロック関数を作成してしまえば、あとはアプリケーションに応じてパラメータを変えるだけです。
設定用のペリフェラルライブラリの使い方を解説していますが、マイコンのクロック構成はどれも同じようなものなのでここで本質的な働きを理解すればどこにでも通用すると思います。
STM32マイコンではクロック信号を供給するのに水晶振動子やセラミック振動子による外部の振動子による発振回路の他に、抵抗器RとコンデンサCで構成されるRC発振回路を内蔵しています。
内蔵発振回路を利用すれば外部に振動子を外付けしなくてもよいのでマイコンの周辺回路がシンプルになる利点がある一方、抵抗値やコンデンサ容量により周波数が決まるため製品ごとのばらつきや温度などの周辺環境により周波数が変動することも考えられます。
その点、水晶振動子など外部発振源は周波数が一定で正確です。UART通信など非同期で外部機器と接続する場合にはクロックが不安定であると通信速度が不安定となり通信障害が発生する可能性もあるため、クロックは正確であることが求められます。「マイコンの外部クロック」に詳細を記載しています。
クロック源を内部にするか外部から与えるかはアプリケーション用途にもよりますので最終的には設計者の判断で行います。
クロック源の種類
STMマイコンで利用できるクロック源は4種類あります。
ここでは外部発振源を使用したHSEクロックからシステムクロックを生成し、各ペリフェラルに供給するクロックを設定する方法を解説します。
STM32マイコンでも他のマイコンでも水晶振動子など外部発振源を使う場合に振動子の発振周波数そのままをシステムクロック(動作周波数)にするのではなく、数倍に高速化して使うことが多いです。
高速の動作周波数を実現するのに例えば200MHzのシステムクロックで動作させたいために200MHzの外部発振源を使用すれば簡単のようですが、周波数が高くなるほど消費電力が増え発熱したり、発振が不安定になったりします。
組み込み機器ではPCとは違って放熱性の悪い環境での使用に耐えなければならない場合も多いので発熱は致命的です。
そこで低い周波数で安定した外部発振源を用いてこれを基にPLL回路(位相同期回路)でクロック周波数を整数倍に大きくしたり(逓倍)、整数で割って小さくしたり(分周)します。
マイコンのクロック設定には上述のPLL回路が必ず登場しますがマイコンを使う上では原理を理解することはあまり重要ではなくクロック周波数を変更するものの認識だけでいいとおもいます。
STM32マイコンではクロックは上図のような構成になっていて設定したパラメータでシステムクロックやペリフェラルへのクロックが作成されます。
クロックの設定は一見複雑なのですが、この中で使用する箇所を限って使うことになるので一度仕組みを理解すると、ここで使用するペリフェラルライブラリ以外での設定や他のマイコンシステムでの設定でも容易に行えるようになります。
余談になりますが、コード自動生成ツールを使用するとツール内ではクロックを作成するのに視覚的にわかりやすいブロック図の中に必要なパラメータを入力するだけで自動にシステムクロックやペリフェラル用クロックを作成してくれます。
大変便利なのですが、このようなツールを使う際にもブロック図の機能をまず理解しておくべきです。このクロックの構成はSTM32マイコンに限られたものではなくどのマイコンでも使われているものですのでここでしっかり理解してしまえばつぶしがききます。
クロックの設定
それでは外部発振HSEに8MHzの水晶振動子を使用した場合の例で解説していきます。システムクロックSYSCLKを72MHz,APB1ペリフェラルクロックPCLK1を18MHz, APB2ペリフェラルクロックPCLK2を72MHzのクロック設定手順は以下の通りです。
① RCCシステムリセット
まずRCC_DeInit関数を実行してマイコンのクロックシステムをリセットします。
電源投入直後ではクロックシステムは初期状態(内部HSI:8MHz)ですので、この関数は実行しなくてもよいのですが、フェールセーフのため実行しておきます。
② 外部クロックHSEを有効化
外部クロックHSEを有効化します。HSE有効化関数RCC_HSEConfigの引数はRCC_HSE_ONでHSE有効、RCC_HSE_OFFでHSE無効となります。
なお、参考までにRCC_HSE_Bypassという引数もありますが、これは水晶振動子やセラミック振動子を使わずにOSC_IN端子に外部クロックソースを入力し、HSEをバイパスするときに使用します。
内部クロックHSI(8MHz)を使用する場合はRCC_HSEConfig()の実行は必要ありません。
③ HSE準備完了まで待機
外部振動子はコンデンサと組み合わせた発振回路ですので起動してからクロックが安定するまでわずかながら時間がかかります。安定するまで待機させるのにRCC_WaitForHSEStartUp関数を実行させて戻り値のHSEStartUpStatusを取得します。
戻り値のHSEStartUpStatus がSUCCESS(1)になったら次の過程に進みます。
④ PLL回路によるPLLCLKの設定
PLL回路によるPLLCLKの設定をします。
PLLCLKはRCC_PLLConfig関数を実行させて作成します。
設定例:分周比1, 逓倍率9
RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9);
第1引数には分周比を指定します。
■ RCC_PLLSource_HSI_Div2 : HSIを2分の1に分周し、PLLに供給
■ RCC_PLLSource_HSE_Div1 : HSEをそのままPLLに供給
■ RCC_PLLSource_HSE_Div2 : HSEを2分の1に分周し、PLLに供給
第2引数にはPLL回路に指定する逓倍を指定します。
■ RCC_PLLMul_x: 2 - 16の整数(マイコンの上限以下で設定)
上のプログラム例ではHSEクロック8MHzで分周比1、逓倍率9なのでPLLCLKは72MHzとなります。
⑤ HCLK、PCLK1、PCLK2の分周設定
次に、HCLK、PCLK1、PCLK2の分周設定をします。
HCLKはSYSCLKをRCC_HCLKConfig関数で引数に分周比を指定実行して生成します
引数の分周比:
■ RCC_SYSCLK_Div1 : 分周しない
■ RCC_SYSCLK_Div2 : 2分の1
■ RCC_SYSCLK_Div4 : 4分の1
■ RCC_SYSCLK_Div8 : 8分の1
■ RCC_SYSCLK_Div16 : 16分の1
■ RCC_SYSCLK_Div64 : 64分の1
■ RCC_SYSCLK_Div128 : 128分の1
■ RCC_SYSCLK_Div256 : 256分の1
■ RCC_SYSCLK_Div512 : 512分の1
PCLK1、PCLK2はHCLKをそれぞれRCC_PLCK1Config関数,RCC_PLCK2Config関数で引数に分周比を指定実行して生成します。
引数の分周比:
■ RCC_HCLK_Div1 : 分周しない
■ RCC_HCLK_Div2 : 2分の1
■ RCC_HCLK_Div4 : 4分の1
■ RCC_HCLK_Div8 : 8分の1
■ RCC_HCLK_Div16 : 16分の1
⑥ PLL回路を有効化する
PLL_PLLConfig()関数でPLL回路の逓倍率を設定しましたがこのままではまだ、PLL回路は作動していません。PLL回路の作動開始にRCC_PLLCmd関数を使用します。引数がENABLEでPLL回路を作動させ、DISABLEで回路を停止させます。
設定例:
RCC_PLLCmd(ENABLE);
⑦ SYSCLKソースを選択
PLL回路を作動設定しても正常に開始するには多少の時間かかるのでPLL回路の準備が完了したかを確認するRCC_GetFlagStatus関数を使用して、この関数の戻り値フラグがRESETからSETになれば準備完了を意味します。
プログラム内では戻り値フラグがRESETの間待機させています。RCC_GetFlagStatus関数はPLL回路以外のさまざまな状態の確認に用いることができます。
設定例:
RCC_GetFlagStatus(RCC_FLAG_PLLRDY);
引数に指定するRCC_FLAGマクロでクロック設定に関するものを記します。設定例ではPLLの準備完了を確認しています。
引数(フラグステータス):
■ RCC_FLAG_HSIRDY: HSI準備完了
■ RCC_FLAG_HSERDY: HSE準備完了
■ RCC_FLAG_PLLRDY: PLL準備完了
■ RCC_FLAG_LSIRDY: LSI準備完了
■ RCC_FLAG_LSERDY: LSE準備完了
その他、RCC_FLAG_PINRST、RCC_FLAG_PRTRST、RCC_FLAG_SFTRST、RCC_FLAG_IWDGRST、RCC_FLAG_WWDGRST、RCC_FLAG_LPWRSTなどがありますので必要に応じて使用します。
クロック設定の最後にPLLCLKをシステムクロックの動作周波数SYSCLKに指定します。これはRCC_SYSCLKConfig関数を実行して設定します。
引数:
■ RCC_SYSCLKSource_HSI : PLL回路を経由していないHSIを使用
■ RCC_SYSCLKSource_HSE : PLL回路を経由していないHSEを使用
■ RCC_SYSCLKSource_PLLCLK : PLL回路を使用
設定例:
RCC_SYSLKConfig(RCC_SYSCLKSource_PLLCLK);
最後にSYSCLKにPLLCLKが設定されているかどうかを確認するためにRCC_GetSYSCLKCource関数の戻り値を確認して設定したとおりものであったら完了としています。このプログラムではPLLCLKを設定したので戻り値が0x08になれば設定完了です。
戻り値:
■ 0x00 : HSIが使用されている
■ 0x04 : HSEが使用されている
■ 0x08 : PLLCLKが使用されている
これまでプログラムを例に設定を解説してきましたが、実際にはこの設定プログラムをそのまま使用し、パラメータ部分だけを変更すればよいとおもいます。設定の流れを理解してもらえばよいと思います。