인터럽트는 CPU가 프로그램을 실행하고 있을 때,
입출력 하드웨어 등의 장치나 또는 예외상황이 발생해서 처리가 필요할 경우에 CPU에 알려서 처리하는 기술이다.
인터럽트는 내부 인터럽트와 외부 인터럽트로 나눌 수 있다.
1. 내부 인터럽트
: 주로 프로그램 내부에서 잘못된 명령 또는 잘못된 데이터 사용시 발생
(예를 들어, 0으로 나눴을 경우/사용자 모드에서 허용되지 않은 명령 또는 공간 접근 시/계산 결과가 Overflow/Underflow가 나는경우)
2. 외부 인터럽트
: 입출력 장치, 타이밍 장치, 전원 등의 외부적인 요인에 의해서 발생하는 인터럽트/주로 하드웨어에서 발생
(예를 들어, 전원 이상/기계 문제/키보드 등 I/O 관련 이벤트/Timer 이벤트)
Timer 기본 설정

설정 전에 기존의 HCLK 값 확인 ex : 100MHz
TIM7 활성화함 (TIM7 Activated)
Prescaler와 Auto-Reload 값을 변경함
(ex : Prescaler: 4999 Auto-Reload : 4999)
-1 한 이유는 카운터가 0부터 세기 때문이다. 8999 대신 9000-1 이런식으로 적어두면 더 직관적이다.


Prescaler는 분주비로 타이머 클럭을 나눠주는데 사용됩니다.
( max 2^16 - 1 까지)
Counter Period는 주기를 정하는데 사용됩니다.
Prescaler , Counter Period는 모두 0부터 시작하기 때문에 설정한 값에 -1을 해줍니다.
ARR은 Auto Reload Register의 약자로 Counter Register의 값이 ARR과 동일해질때, Update Interrupt가 발생한다. (Period 라고도 한다.)
HCLK = 168MHZ
APB1 TIM CLK = HCLK / 2 = 84MHz
APB2 TIM CLK = HCLK = 168MHZ
즉 한번 올라가는데 1 / 84,000,000[s]
한번 증가할때 다음과 같이 설정 할 수 있음
TIM CLK = APM1 TIM CLK / Prescaler
ex) Prescaler를 10,000으로 하게 되면
TIM CLK는 1 / 8400 이 됨. 한번 증가할 때 1 / 8400 [s]
이때 Auto Reload Register를 8400으로 하면 8400번 증가 할때
인터럽트가 1번 발생함. 계산하면 1초에 1번 인터럽트가 발생함.

Counter Register값이 1증가하는데 걸리는 시간
정리하면 PWM의 주파수는 ((Internal Clock)/(Prescaler + 1)) / (Period=ARR)로 계산되며, DutyCycle(%)은 (Pulse)/(Period)*100으로 계산된다.
TIM7_IRQHandler -> HAL_TIM_IRQHandler -> HAL_TIM_PeriodElapsedCallback
TIM7은 APB1 Bus를 이용
static void MX_TIM7_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim7.Instance = TIM7;
htim7.Init.Prescaler = 9999;
htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
htim7.Init.Period = 8399;
htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
MX_TIM7_Init(); //타이머 초기화
HAL_TIM_Base_Start_IT(&htim7); //타이머 인터럽트 활성화
// 1초마다 LED 토글
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM7)
{
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}
}
Ref
https://bo5mi.tistory.com/169
https://louie0724.tistory.com/359
https://velog.io/@sang_yun_911/STM32-TIMInterrupt
https://velog.io/@sang_yun_911/STM32-TIMInterrupt2
https://www.youtube.com/watch?v=GtpHPYGYGNo&list=PLUaCOzp6U-RqMo-QEJQOkVOl1Us8BNgXk&index=8
https://eteo.tistory.com/73