STM32F103で遊ぶ【クロック設定~GPIO篇】

今回はプロジェクトの作成から、クロック設定、Lチカまでです。

プロジェクトの作成


まず最初にSW4STM32でプロジェクトを作成していきます。ファイル->新規->C++プロジェクトを選択すると、初期設定画面が出てきます。

プロジェクト名を入力して、次へ。

構成は変更なしで次へ。

ボードの選択をします。「系列」でSTM32F1を選び、「Create a new custom board」から新規にボードを設定します。

今回ファームウェアは使わず動かそうと思うので、「No firmware」を選択したまま完了を押します。これでプロジェクトの作成は完了です。

次に、STの公式ページからF1シリーズ用のパッケージを取ってきます。最低限必要な定義ファイルなどは,DriversディレクトリのCMSIS内にあるので、CMSISをプロジェクトツリーのルートに置きます。ついでにCMSIS内のIncludeディレクトリをプロジェクトのパスに追加しておきましょう。プロジェクトを右クリックしてメニューのプロパティからC/C++ 一般、パスおよびシンボルを選択します。インクルードタブの言語からC++ GNUを選択し、パスを追加します。

クロック設定


今回使用しているボード上には周波数8MHzのクリスタルがのっているため、それをマイコンのクロックソースとして使用します。細かいクロックの設定は以下の画像を参照してください。(画像はCubeMXの設定画面より拝借。簡単に設定できるし範囲外は警告が出るのでコード生成に使わなくても周波数決めるのに便利。)

左にあるプロジェクトツリーのsrcディレクトリを右クリックし、新規->ソース・ファイルからファイルを追加します。名前は適当に決めてください。ここにメイン文を書いて、マイコンを動かしていきます。今回のクロック設定で必要になる処理は

・HSEオシレータ・クロックの動作

・PLLクロックの設定

・PLLクロックの動作

の3つとなります。順に見ていきましょう。

HSEオシレータ・クロック

HSEオシレータ・クロックとはクロックの1つであり、端的に言うとマイコン内蔵でないクリスタルから供給するクロックのことです。今回は外付けのクリスタルを使用するのでこのHSEを使用することになります。クロックに関するレジスタであるRCCの説明を見るとクロック制御レジスタ(CR)のBit16でHSEオシレータのオンオフが切り替えられることがわかります。

 

すなわち、レジスタのBit16に1をセットすればよいので

RCC->CR |= 0x00010000;

こうなります。これをF103のヘッダファイルで定義されているマクロを使用して設定すると、次のようになります。

RCC->CR |= RCC_CR_HSEON;

PLLの設定

PLLは、クロックを逓倍して、マイコンを高い周波数で動作させるためのものです。設定はRCCのクロック構成レジスタ(CFGR)で行います。PLLの選択、クロックソースの選択(HSE)、逓倍、ペリフェラルのクロックの設定を行います。クロックソースはHSE/1、逓倍数は最大周波数の72MHzで動作させるので9倍にします。

RCC->CFGR = 0x00000000;
RCC->CFGR |= RCC_CFGR_SW_1;     //システムクロックとしてPLLを選択
RCC->CFGR |= RCC_CFGR_PPRE1_2;  //PPRE1=SYSCLK/2
RCC->CFGR |= RCC_CFGR_PLLSRC;   //PLLSRC=HSE/1
RCC->CFGR |= (RCC_CFGR_PLLMUL_0 & RCC_CFGR_PLLMUL_1 & RCC_CFGR_PLLMUL_2);   //PLL出力=PLL入力x9

もしくは

RCC->CFGR = 0x001D0402;

PLLの動作

PLLの設定を行った後、PLLを動作させます。HSEを動作させたのと同じクロック制御レジスタ(CR)のBit24にPLLのオンオフを制御するレジスタがあるので、それをオンにします。

RCC->CR |= 01000000;

もしくは

RCC->CR |= RCC_CR_PLLON;

これでクロックの設定は終了です。

Flashへのアクセス


STMマイコンはクロックの設定をしただけでは動かなくて、Flashのアクセススピードを動作させる周波数ごとに変更しないといけません。Flashへの確実なアクセスをするため、Flashへのアクセス時間を一定にする必要があり、マイコンのメインクロックのスピードごとに遅延の設定が必要なようです。プログラミングマニュアルによると、フラッシュアクセスコントロールレジスタ(FLASH_ACR)の下位3ビットでこの遅延時間を設定できるようです。SYSCLKが72MHzなので2ウェイトステートとなります。

FLASH->ACR |= 0x00000002;

もしくは

FLASH->ACR |= FLASH_ACR_LATENCY_2;

ここに気付くまでにかなり時間がかかりました。デバッガ使っても突然止まるからわけわからんし…。

Lチカ


とりあえずクロックの設定がうまくできているかの確認も含め、1ビットの万能デバッガで動作確認をします。使用しているボード上にLEDがついているのでそれを光らせます。GPIO含め、STMのペリフェラルにはクロックがあり、基本的にはデフォルトで全てオフになっているのでこれを有効化しないといけません。各種GPIOポートのクロックは、APB2プリスケーラを通して供給されるため、APB2ペリフェラル・クロック・イネーブル・レジスタ(RCC_APB2ENR)でクロック供給を許可します。

使用するポートがPC13なので、IOPCENビットを1にします。

RCC_APB2ENR |= RCC_APB2ENR_IOPCEN;

また、ピン自体を出力として使用するための設定はGPIOレジスタのポート構成レジスタ(GPIOx_CRL、GPIOx_CRH)で行います。

今回使用するピン番号は13であり、上位ビットなので、CRHの方ですね。出力モード、最大速度50MHz、プッシュプル・汎用出力に設定するので、プログラムは以下のようになります。

GPIOC->CRH &= ~0x00F00000;
GPIOC->CRH |= 0x00300000;

もしくは

GPIOC->CRH &= ~(GPIO_CRH_MODE13 & GPIO_CRH_CNF13);
GPIOC->CRH |= GPIO_CRH_MODE13_0 & GPIO_CRH_MODE13_1;

また、実際にピンのHigh、Lowを変化させるのは、GPIOレジスタのポート出力データ・レジスタ(GPIOx_ODR)になります。

GPIOC->ODR |= 0x00002000;    //High(点灯)
GPIOC->ODR &= ~0x00002000;    //Low(消灯)

もしくは

GPIOC->ODR |= GPIO_ODR_ODR13;    //High(点灯)
GPIOC->ODR &= ~GPIO_ODR_ODR13;    //Low(消灯)

ポート出力データ・レジスタの13番目をセットすると点灯、リセットすると消灯となります。ビット数がポートの番号と対応しているのでわかりやすいですね。

プログラム


以上を踏まえて作成したプログラムが以下になります。上で説明した各種設定に加えて、クロック安定化待ちの処理などを追加しています。

#include "../CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h"

int main(void){
    //Clock Configuration
    RCC->CR &= ~RCC_CR_PLLON;
    while(RCC->CR & RCC_CR_PLLRDY);    //PLL停止待ち

    RCC->CR |= RCC_CR_HSEON;   //HSEON
    while(!(RCC->CR & RCC_CR_HSERDY));    //HSE動作待ち

    RCC->CFGR = 0x001D0402;     //PLL選択, PLLx9=72MHz, PLL = HSE/1
    FLASH->ACR |= FLASH_ACR_LATENCY_2;  //FLASH読み込みの遅延時間設定

    RCC->CR |= RCC_CR_PLLON;    //PLLON
    while(!(RCC->CR & RCC_CR_PLLRDY));    //PLL安定化待ち

    //GPIO Configuration
    //LED:PC13
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; //GPIOCクロック有効
    GPIOC->CRH = 0x00300000;    //PC13プッシュプル出力

    while(1){
        GPIOC->ODR = 0x00002000;    //HIGH
        for(int i = 0; i < 1000000; i++);
        GPIOC->ODR = 0x00000000;    //LOW
        for(int i = 0; i < 1000000; i++);
    }
}

結果


光った

参考


データシート

リファレンスマニュアル

フラッシュプログラミングマニュアル

こちらの記事をかなり参考にさせていただきました。ありがとうございます。

STM32いじってみた(4) PLLクロック編

Leave a Reply

Your email address will not be published. Required fields are marked *