今回はIDEの話題から離れてしまいますが、前回追加したコードについて説明します。
追加したコードはGPIOの初期化に関するものになります。
投稿時の開発環境:
PC:Windows10 OS
IDE: STM32CubeIDE Version1.1.0
Configurator: STM32CubeMX Version5.4.0
Board: STM32Nucleo-F401RE
/* USER CODE BEGIN 1 */
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
/* USER CODE END 1 */
このIDEを使うにあたり、基本的にユーザーは USER CODE BEGIN と USER CODE END の間にコードを書く決まりがあるのでした。
stm32のペリフェラル(周辺機能)を動作させるには初期設定が必要になります。
そして各周辺機能に対する初期化専用の構造体が用意されています。
ここではLチカするためのGPIOに対する GPIO_InitTypeDef型の構造体を使っています。
構造体に値をセットしてGPIOの初期化関数であるHAL_GPIO_Init()を呼びます。
(GPIO以外の周辺機能についても同じパターンで初期化を行うことになります)
初期化関数の先頭に HAL という言葉がついています。
ここで少々HALについて触れておきます。
HALとは Hardware Abstraction Layer の略で日本語にすると「ハードウエァ抽象化層」です。
HALはハードウェアごとの仕様の違いを吸収し、ユーザーが同じ方法で取り扱えるようにする役割をもつ階層を言います。
マイコンによってはGPIOAを制御するためのレジスタのアドレスが異なります。
ユーザーはそれらについて意識することなくHALの関数を使うことでGPIOAを制御することできるというわけです。
レジスタに直接アクセスするのに比べてメモリを少々使いますが、さほど気にする必要はありません。
便利なHALの関数を使いましょう。
ただしHALの関数では取り扱えない細かい制御もあるので、その時は別の手段を考えれば良いでしょう。
stm32F4 HALのマニュアル(英語)は以下のサイトからダウンロードすることができます。
サイズの大きなPDFファイルですが、必要な時に必要な部分を眺めて調べるようにすれば良いでしょう。
構造体の各メンバの説明なども掲載されています。
見ただけではわからないことも多いので、いろいろ設定して試してみることをお勧めします。
GPIOを出力ピンとして使うにはクロックをEnableにして、Pinメンバにピンを設定して、Modeメンバに GPIO_MODE_OUTPUT_PP を設定します。
GPIOを扱う場合においてもクロックをEnableにしないと動かないのでご注意ください。
GPIOを初期化する構造体メンバ Pin を設定する
ピンの設定ですが、各ピンは以下のように定義されていて、ある1ビットに割り当てられています。
それらを OR して Pinメンバに設定してあげれば同時に設定してあげることも可能です。
例えば GPIO_PIN_ALL を使えばそのGPIOポートの16ビットを全て同時に設定することができます。
ただし各ビットに対して同じ設定をしたい場合に限ります。
#define GPIO_PIN_0 ((uint16_t)0x0001) /* Pin 0 selected */
#define GPIO_PIN_1 ((uint16_t)0x0002) /* Pin 1 selected */
#define GPIO_PIN_2 ((uint16_t)0x0004) /* Pin 2 selected */
#define GPIO_PIN_3 ((uint16_t)0x0008) /* Pin 3 selected */
#define GPIO_PIN_4 ((uint16_t)0x0010) /* Pin 4 selected */
#define GPIO_PIN_5 ((uint16_t)0x0020) /* Pin 5 selected */
#define GPIO_PIN_6 ((uint16_t)0x0040) /* Pin 6 selected */
#define GPIO_PIN_7 ((uint16_t)0x0080) /* Pin 7 selected */
#define GPIO_PIN_8 ((uint16_t)0x0100) /* Pin 8 selected */
#define GPIO_PIN_9 ((uint16_t)0x0200) /* Pin 9 selected */
#define GPIO_PIN_10 ((uint16_t)0x0400) /* Pin 10 selected */
#define GPIO_PIN_11 ((uint16_t)0x0800) /* Pin 11 selected */
#define GPIO_PIN_12 ((uint16_t)0x1000) /* Pin 12 selected */
#define GPIO_PIN_13 ((uint16_t)0x2000) /* Pin 13 selected */
#define GPIO_PIN_14 ((uint16_t)0x4000) /* Pin 14 selected */
#define GPIO_PIN_15 ((uint16_t)0x8000) /* Pin 15 selected */
#define GPIO_PIN_All ((uint16_t)0xFFFF) /* All pins selected */
(例)
GPIO_InitStruct.Pin = GPIO_PIN_1 | GPOP_PIN_5; // PIN1と5を両方同時に設定する
GPIO_InitStruct.Pin = GPIO_PIN_ALL; // 16ビットを同時に設定する
GPIOを初期化する構造体メンバ Mode を設定する
次にGPIOをどう動かすかについて Modeメンバに設定を行います。
それぞれの機能についてはさきほど紹介したマニュアルを参照してください。
Lチカするために出力ピンに設定しますので、
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
に設定します。
GPIOを初期化する構造体メンバ Pull を設定する
GPIOをプルアップするのか、プルダウンするのか、しないのか について設定を行います。
特に必要ないので
GPIO_InitStruct.Pull = GPIO_NOPULL;
に設定します。
GPIOを初期化する構造体メンバ Speed を設定する
動作周波数の設定を行います。
いずれでも構いませんが、ゆっくりで良いでしょう。
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
に設定します。
GPIOを初期化する
あとはGPIOポートと設定した構造体を引数にして HAL_GPIO_Init() を呼びだします。
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
以上、GPIOの初期化について簡単に説明をしました。
初期化の後、次の関数は GPIOA5ピンに “1”(Hレベル)をセットする
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
次の関数は GPIOA5ピンに “0”(Lレベル)をセットする
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
次の関数はGPIOA5ピンの状態を反転するのでした。
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
以上、追加したコードについて概略説明しました。
次回はコンフィグレーターを使ってタイマー割り込み処理を実装してみます。
この続きを読むには こちら からどうぞ。
コメントを書く