STM32 nucleoを使う (2) STM32CubeIDEを使う

STM32CubeIDEを使ってみましょう。
プロジェクトを作成し、コードの記述とデバッグまで行います。

STM32CubeIDEには、STM32CubeMXの機能が内蔵されているので、クロック設定、ピンの配置、ペリフェラルの設定がグラフィカルにでき、初期コードの生成ができます。
1chipマイコンを使う場合、マイコンの設定や内蔵のペリフェラルの設定が多く、初期設定だけで凄い労力が必要でしたが、必要な内容を自動で生成してくれるため、とても便利になりました。

CubeMXで生成されるコードはHAL(Hardware Abstraction Layer)とLL API(Low-Layer Application Programming Interface)に対応しています。
HALにより抽象化されているため簡単に各ペリフェラルの機能を使うことができます。
ペリフェラルの動きをより理解するにはSTM32のマニュアルを参照することをお勧めします。

最初のプロジェクトとして、ユーザーLEDとSWを使ったプログラムを作ってみましょう。
SWを押している間、LEDを点灯させます。

#プロジェクトの作成
Home画面のStart new STM32 Projectを押します。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/b1565d2d-0f06-cc11-6ae4-04dce97e1a42.png)

ターゲットを選択する画面になります。
Buard Selectorタブを選択し、NUCLEO-F303REを選択します。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/5efd9d62-5dc0-3f76-fc85-bbd87594f140.png)

プロジェクトの名前とオプションを設定します。
C言語を選択しました。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/54d58fb4-e416-6a98-820d-4d855728c102.png)
この後もオプション等の確認がありますが、デフォルトで進めます。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/92362e20-8976-efd8-fdd5-2716a075cf3c.png)
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/8a3ee60a-bee2-61e1-46d4-1375256cbf2e.png)

#Pin設定とConfiguration
プロジェクトが作成されピンのレイアウトが表示されます。
ボードを選択したのであらかじめPC13にSWのB1、PA6にLEDのLD2が設定されています。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/ed781dc3-2046-c3c4-7eea-759757e52dc5.png)

System Coreを展開しGPIOを選択すると、GPIOの設定一覧表示となります。
PA5は出力、PC13は外部割込み（立下りエッジ）とモードが設定されています。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/40cd6acf-a037-a714-1d4a-e4bc5f1c6e02.png)

#コードの記述
生成されたコードを見てみます。
Project ExploreからSwAndLedTest/Core/Srcと開くとソースファイルがあります。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/39275650-948b-aece-19b6-717b71b1f40e.png)

main.cを開きます。
![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/cdac4295-33a2-d5df-632a-eb2778119858.png)
main関数、HALの初期化関数があります。


main関数は初期化関数の呼び出しとメインルーチンとなる無限ループが記載されています。

コードを追加するには
/* USER CODE BEGIN xxx */
と
/* USER CODE END xxx */
の間に記述します。この範囲は後で生成をやり直しても内容が変わりません。

#プログラムの記述
SWが押されている間LEDを点灯させるので、ポートの読み込みと出力を行います。
ポートの入力にはHAL_GPIO_ReadPin関数、ポートの出力にはHAL_GPIO_WritePin関数を使います。
HALのマニュアルはここにあります。（英語）
https://www.st.com/resource/en/user_manual/dm00122016-description-of-stm32f3-hal-and-low-layer-drivers-stmicroelectronics.pdf

/* USER CODE BEGIN WHILE */と/* USER CODE END WHILE */の間にプログラムを記述します。

```
/* USER CODE BEGIN WHILE */
while (1)
  if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == GPIO_PIN_RESET)
  {
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
  }
  else
  {
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
  }
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
```

###HAL_GPIO_ReadPin関数

```
GPIO_PinState HAL_GPIO_ReadPin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
```

Pinの状態を読み込みます。GPIOの種類とGPIOピン番号を指定します。
SWのB1であればPC13に割り付けてあるのでGPIOはGPIOC、GPIOピン番号は13となりますが、自動生成でマクロが定義されていますのでマクロで指定しましょう。
GPIOはB1_GPIO_Port、GPIOピン番号はB1_Pinです。

###HAL_GPIO_WRitePin関数

```
void HAL_GPIO_WritePin (GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, GPIO_PinState
PinState)
```

PinにHまたはLを出力します。GPIOの種類とGPIOピン番号、それと出力する状態を指定します。


#ビルド
コードの記述ができたらビルドを行います。
Buildボタンでビルドを行います。
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/8aae523b-fd1b-27d5-3517-020ae7bdd64e.png)
コードに問題が無くビルドが終わるとBuild Finishedと表示されます。失敗した場合はBuild Failedと表示されるのでConsoleの内容を基に問題を見つけて直します。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/f96065c0-8662-9a49-894f-b79af5aa9c00.png)

#実行
Runボタンを押すとプログラムを実行します。
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/a1d2aa22-82d1-2572-f93c-44f2b1cc45be.png)

#デバッグ
実行では途中でプログラムを止めたりステップ実行ができません。デバッグを行う場合はデバッグボタンを押します。
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/798a5c5e-95fd-9420-23b6-f0eb345ab544.png)

##ブレークポイントを設定する。
止めたい行の行番号をダブルクリックするとブレークポイントを設定できます。
ブレークポイントには青い丸印がつきます。
SWが押されてLEDを点灯する位置にブレークポイントを設定しました。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/f21c9f28-c7b0-604b-a28f-48f5d9987b9c.png)
プログラムがブレークポイントに到達すると一時停止します。
その後、ステップ実行や変数の内容の確認ができます。
ステップ実行はステップ毎に実行しますが、STEP InfoとSTEP Overの2種類があるので使い分けましょう。
##STEP Info
関数の呼び出しをステップ実行するときは、呼び出す関数内に移動します。
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/945ca0c7-1ca5-dab3-f2b6-244d18838c66.png)
SWを押して、HAL_GPIO_WritePinで停止した後にSTEP_Infoを実行すると、HAL_GPIO_WritePinに移動します。
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/f915bb33-1e25-1139-24a6-ba4d36143e88.png)

##STEP Over
STEP Overは関数単位で実行します。
![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/a0971825-6736-f7b5-711b-7d75ca229f93.png)
HAL_GPIO_WritePinで停止した後にSTEP_Overを実行すると、HAL_GPIO_WritePinを実行し次のif文で停止します。
![25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/715b7786-741e-4737-2146-846dc4f229bb.png)

##ブレークポイントの解除
ブレークポイントを設定している行番号部分を再度ダブルクリックすると解除します。

##Resume
停止した状態から再度実行する場合はResumeボタンを押します。
停止している位置から実行します。
![26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68712/e343ae4b-3c89-dcf5-b258-1d53cf0b936e.png)

デバッガ―の機能としては、変数やメモリの参照等の便利機能がいろいろあるので試してみることをお勧めします。