Develop Knowledge/STM32F4 by ChrisP

4강. Timer Interrupt

정수열 2023. 2. 2. 22:30

본 단행본은 inflearn에 있는 ChrisP 강사님의 "HAL, CubeMX, TrueSTUDIO를 이용한 STM32F4 무료 강좌"를 정리한 글입니다.

 

강좌 바로 보기 >> https://www.inflearn.com/course/stm32f4/dashboard

 

[무료] HAL, CubeMX, TrueSTUDIO를 이용한 STM32F4 무료 강좌 - 인프런 | 강의

고성능 마이크로컨트롤러인 STM32F 시리즈를 처음 접하는 분들이 쉽게 시작할 수 있도록 무료 컴파일러 TrueSTUDIO 및 코드자동생성 프로그램 CubeMX 설치부터 칩 기능의 개념설명, 소스코드작성(HAL

www.inflearn.com

 

- Timer와 Timer Interrupt

개념 설명은 동영상에서 아주 잘 해주시므로, 여기서는 핵심만 집고 넘어가보겠습니다.

기본 개념은 이렇습니다.

 

APB1 타이머를 쓰면 84MHz, APB2 타이머를 쓰면 168MHz 클럭을 발생시킵니다.

여기서는 APB1 타이머를 쓴다고 가정하고 이야기를 해보겠습니다.

1. Timer는 1/84,000,000초마다 1클럭을 세서 누적시킵니다.

2. Auto Reloaded Register까지 클럭이 누적되면, Timer Update Interrupt를 발생시킵니다.

이 Timer Update Interrupt 주기마다 시간을 세게 됩니다. 예를 들어, Timer Update Interrupt가 50ns마다 걸리면, 50ns의 시간을 셀 수 있게 됩니다.

 

시간을 세는 예시를 들어보겠습니다.

만약, Auto Reloaded Register = 1,000-1 이라면,

타이머 클럭은 0,1,2,..., 999까지 세게 됩니다. 즉, 1,000 클럭을 누적시킵니다.

그 다음 클럭이 넘어가는 순간, 타이머 클럭은 0으로 초기화 되고 Timer Update Interrupt가 발생됩니다.

따라서, 이 타이머는 1/84,000,000 * 1,000 = 1/84,000s 주기를 발생시킵니다.

 

그런데 주기가 너무 빠릅니다. 이 주기를 완화시키기 위해, Prescaler를 적용합니다.

Prescaler는 주기에 곱하는 값입니다.

만약 Prescaler = 8,400-1 이라면, 주기는 1/84,000 * 84,00 = 0.1s가 되는 식입니다.

 

이를 종합해서, 주기를 구하는 공식은 이렇게 됩니다. (APB1 타이머 기준.)

(Counter period는 Auto Reloaded Register를 의미합니다.)

 

 

- Timer 종류

 

 

- 회로도

없음

 

- CubeMX 설정

1. Pinout & Configuration

TIM7 -> Activated

TIM7에서는..

Prescaler -> 9999

Counter Mode -> Up

Counter Period -> 8399

 

이 설정은 1초를 만들기 위한 설정이다.

Counter Period는 위에서 말한 Auto Reloaded Register를 의미한다.

그리고, Counter Period와 Prescaler는 영부터 세기 때문에, 원래 값에서 1을 뺸 값을 넣어주어야 한다.

 

왜 -1을 빼야 하는지 이해가 안간다면 다음의 예시를 생각해보자.

5를 세야 하는데, 1부터 세는게 아니라 0부터 센다고 해보자.

1부터 세면 1,2,3,4,5 -> 1,2,3,4,5 -> ... 이런식으로 평범하게 세면 되지만,

0부터 세면 0,1,2,3,4 -> 0,1,2,3,4 -> ... 이런식으로 세게 될 것이다.

따라서, 원래 값에서 1을 빼주어야만 한다.

 

- 코드 생성

본 실습을 위해서는 7SEG.c, 7SEG.h 파일을 인클루드 해주어야 한다.

7SEG.c
0.00MB
7SEG.h
0.00MB

#include "7SEG.h"

// Timer Interrupt 시작
HAL_TIM_Base_Start_IT(&htim7);

// 7-Segment 시작
_7SEG_GPIO_Init();

// Timer Update Interrupt가 발생될 때 마다, 이 콜백 함수 안의 내용이 실행된다.
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static unsigned char cnt = 0;
    
	// 인터럽트가 TIM7 이라면
	if(htim->Instance == TIM7)
	{
		// 1초마다 LED 토글
		HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
		
		// 7-Segment 시간 표시
		_7SEG_SetNumber(DGT1, cnt/10, OFF);
		_7SEG_SetNumber(DGT2, cnt%10, ON);
		cnt++;
	}
}