もともとは同僚から「マイコンなら標準のタイマーの一つはもっているはずだ」と言われたことから始まっています。調べて,自分の覚書としてまとめてみた。
動作確認のため,以下の環境を使いました。
- NUCLEO-F303K8 CPUはSTM32F303K8
- STM32CubeIDE 1.7.0 ( for mac )
- HALライブラリー
基本
- SysTickカウンターが回っている。
ここではSysTick - STCVR - CURRENT が, 周波数 HCLK でカウントダウンされる。
私のテストプロジェクトでは, HSI(8MHz) * 8 = HCLK(64MHz)となっている。
- カウンターが0になると,SysTick - STRVR - RELOAD 値に戻される。同時に割り込みが発生する。
上記では 0xf9ff(=63999)なので, (0xf9ff + 1) / 64MHz = 1msec ごとに割り込みが発生している。
HALライブラリーを使う今回のプロジェクトでは, SysTick_Handler(void)
がコールされる。実態は stm32f3xx_it.c に記載されている。
-
HAL_Delay()
はこれを使っている。またHAL_GetTick()
は,これを使ってカウントして,起動後からの時間を msec で得ることができる。 -
現在の SysTick値を読むこともできる。
printf("HAL_GetTick = %d. ",HAL_GetTick());
printf("SysTick_VAL = %d.\r\n",SysTick->VAL);
割り込み周期を変えるとき
-
SysTick->LOAD
に直接代入しても良いし,HAL_SYSTICK_Config()
を使っても良い。(後者は割り込みのセット等も行なっている)
HAL_SYSTICK_Config(SystemCoreClock/2); // Systick interrupt to 1/2 sec
当然 HAL_Delay() も影響を受けるので注意。
割り込んだ時のコードを追加したい時
main.c じゃなくて,まずは stm32f3xx_it.c に追記します。
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
HAL_SYSTICK_Callback();// ここを追加
/* USER CODE END SysTick_IRQn 1 */
}
んでmain.cに追記します。
void HAL_SYSTICK_Callback() {
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}
HAL_SYSTICK_Callback()
をmain.cで再定義することになります。
参考
void HAL_SYSTICK_IRQHandler(void)
{
HAL_SYSTICK_Callback();
}
/**
* @brief SYSTICK callback.
* @retval None
*/
__weak void HAL_SYSTICK_Callback(void)
{
/* NOTE : This function Should not be modified, when the callback is needed,
the HAL_SYSTICK_Callback could be implemented in the user file
*/
}
参考 PIOのSTM32では, SysTick_Handler()
は main.c に記載されているので,ちょっとわかりやすい。
#include "stm32f3xx_hal.h"
void SysTick_Handler(void)
{
HAL_IncTick();
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
}
int main(void)
{
HAL_Init();
// init PB3
__HAL_RCC_GPIOB_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_SYSTICK_Config(SystemCoreClock/3 - 1); // call SysTick_Handler(void) every 1/3 seconds
while (1)
{
}
}
参考URL