STM32は多くの開発ツールが無償で使えるマイクロコンピュータです。
STM32CubeIDE、STM32CubeMX、STM32CubeProg、TouchGFXなど無償で使用できます。
ここでは、「FPGAの使い方」の中に出てくる「STM32マイコンボードから周波数を設定」
の項目の周波数設定ソフトウェアを作成しました。
STM32CubeMXの設定
(1)STM32CubeMXを起動
(2)端子の設定
端子の設定を行います。
新しくGPIOで追加した端子は、PA8、PA9、PA10、PB5です。
それぞれ、SET、RESET、DATA、SCLKに対応します。
(3)クロックの設定
(4)Project Nameの設定
コード生成
(1)コードを作成します
GENERATE CODEボタンをクリックします。
コードが作成されると以下のメッセージが表示されますので、Open Projectをクリック
します。
ここで作成されるコードは、これまでの設定を反映しCubeMXが自動で作成します。
(2)ワークスペースの設定
ワークスペースの選択メッセージが表示されますので、
設定してLaunchをクリックします。
コードの追加
STM32F446Nucleoボードの青いボタン(User Button)を押した時にFPGAボードの
Arty S7へ発振周波数を設定するパルスを出力するようにソフトウェアを作成します。
ここでは、OSも割込みも使わず一番簡単に作成します。
(1)周波数設定用関数作成
周波数を設定する関数「SetClkGen」を作成します。
(2)メインループにUserKey検出部を追加
UserButtonが押されて離れた立ち上がりを検出し、その時SetClkGen()を呼び出して
います。
ct = 1398は1[KHz]を設定するための値です。スイッチが押されるたびにctが1/2になり、
周波数が1/2になります。ct < 1で1[KHz]に戻ります。
1[KHz]→500[Hz]→250[Hz]→125[Hz]→・・・→ 1[KHz]
です。
while文の中で、10[ms]毎にUserButtonをサンプリングし、立ち上がりを検出します。
プロジェクトのビルド
(1)プロジェクトをビルドします
(2)基板へ書き込みます
STM32F446ボードをUSBケーブルでPCに接続し、書込みを行います。
FPGAボード(Arty S7)と接続して電源投入
下図のように接続します。
それぞれUSBケーブルでPCへ接続します。
OUT波形をオシロスコープで観測
1[KHz]
500[Hz]
250[Hz]
125[Hz]
FreeRTOSを使用してProjectを作成
ここではOSのFreeRTOSを使用して周波数設定プログラムを作成します。
CubeMXでFreeRTOSを使うように設定すると、Code生成した時にDefault TASK
が生成されます。Default TASKでUSER Button検出を行います。
(1)別名でプロジェクトを保存
今までのプロジェクト(STM32F446RE_ClkGen)を開いた状態で
別名(STM32F446RE_ClkGenOS)で保存します。
(2)FreeRTOSの設定
左側のCategoriesからMiddleware and Software Packsを選択してFreeRTOSをチェック
します。
ModeでInterfaceをCMSIS_V2に設定します。
ここでConfigurationのTasks and Queuesを見ると、Default TASKが生成されています。
Advanced settingsのUSE_NEWLIB_REENTRANTはEnabledにします。
(3)コード生成
GENERATE CODEをクリックしてコードを生成します。
FreeRTOSを使用する設定にしたため、下記Warningがでます。
Noをクリックして戻り、SYSでTimebase SourceをSysTick以外に変更します。
TIM6に変更しました。
再度GENERATE CODEをクリックします。
Open Projectをクリックします。
Launchをクリックします。
CubeIDEが起動します。
main.cに以下のコードを追加します。
/* USER CODE BEGIN 0 */
void SetClkGen(uint16_t ctim)
{
int i;
// RESET PULSE
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_RESET);
osDelay(10);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_9, GPIO_PIN_SET);
osDelay(10);
for (i = 0; i < 24; i++)
{
// upper 8 bits = 0
if(i < 16)
{
if(ctim & 0x0001)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
}
}
else
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);
}
// SCLK PULSE
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_SET);
osDelay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, GPIO_PIN_RESET);
osDelay(1);
ctim = ctim >> 1;
}
// SET PULSE
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
osDelay(1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
}
/* USER CODE END 0 */
/* USER CODE BEGIN PV */
GPIO_PinState C13st1 = 0;
GPIO_PinState C13st2 = 0;
GPIO_PinState C13st3 = 0;
uint16_t ct = 1398;
/* USER CODE END PV */
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for(;;)
{
C13st3 = C13st2;
C13st2 = C13st1;
C13st1 = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13);
//osDelay(1);
osDelay(10);
if((C13st3 == GPIO_PIN_RESET) && (C13st2 == GPIO_PIN_RESET) && (C13st1 == GPIO_PIN_SET)){
SetClkGen(ct);
ct /= 2;
if(ct < 1)
{
ct = 1398; // 1KHz
}
}
}
/* USER CODE END 5 */
}
ソースコードの変更
FPGAの記事の中で、PLLのIPでシステムクロックを変更して設定値と出力周波数の対応をわかりやすいように変更しました。
この変更に伴い、STM32のソフトウェアも、1[KHz]を出力するときは1000を設定するように変更します。
main.cの2か所変更します。
1か所目
初期値の設定(1000[Hz])
2か所目
設定値ct < 1の時に初期値を再設定(1000[Hz])
USER BUTTONを押した時の波形はFPGAの記事を参照してください。