본문 바로가기
Embedded/STM32

[STM32] 간략한 Timer 사용 방법(1ms 주기 설정)

by Gordon_ 2025. 2. 16.

첨부파일

429ZI_TImer.ioc
0.01MB
main.c
0.01MB


개발 환경

 

개발 보드 : nucleo-f429zi board

개발 프로그램

- STM32 CubeMX : 6.12.0

- STM32 CubeIDE : 1.16.0


개요

  임베디드 시스템에서 타이머는 매우 기본적인 기능중 하나로 실습시 반드시 해보는 기능중 하나입니다. 타이머를 사용하는 이유는 특정 테스크를 특정 시간마나 반복하여 동작하거나 특정 시간 이후 실행하기 위해 자주 사용됩니다. 또한, 시스템 전체를 멈추는 HAL_Delay함수(AVR의 경우 _delay_ms 함수)를 사용시 다른 기능도 중단되므로 해당 함수 대신 사용하는 기능이다. 

  타이머의 동작 방법은 사람이 손가락으로 시간을 세는 것과 같다고 할 수 있습니다. 사람이 손가락을 사용하여 10초를 센다고 하였을 때, 우리는 1초마다 손가락을 하나씩 접어 결국 10초 후 모든 손가락이 접었을 때 10초가 지났다는 것을 알 수 있죠. 또한 다시 10초를 세기 위해 모든 손가락을 펼 것입니다. 이와 마찬가지로 MCU도 Clock과 Register를 통해 시간을 셀 수 있습니다. 예를 들어, 1kHz의 클럭을 가지는 MCU내 타이머을 10ms의 주기로 설정하려 한다면, MCU는 매 클럭의 주기(1kHz의 주기는 1ms)마다 1씩 증가하는 Register를 가지고 있습니다. 해당 Register의 값은 1ms 마다 증가하므로 10이 되었을 때 10ms가 되었음을 사용자에게 알려주고 다시 0부터 다시 세기 시작합니다. 이처럼 결국 특정 시간(사람: 매 초, MCU: 클럭의 주기)마다 숫자를 세어(사람: 손가락을 접는 행동, MCU: Register 값을 증가) 특정 목표 값에 도달(사람: 모든 손가락을 접음을 확인, MCU : Register의 값을 확인)하는 것이 같습니다. 사실 타이머의 구조와 동작 방법은 매우 복잡합니다. 하지만 우리는 단순히 사용에 목적을 두는 글이므로 해당 내용은 넘어가도록 하겠습니다. 하지만, 반드시 알아야하는 것은 언급하도록 하겠습니다.

  이제 본격적으로 타이머를 사용하기 위한 준비과정을 시작하도록 하겠습니다.


사용하려는 타이머 Clock 확인

 먼저 타이머에 입력되는 Clock를 확인하여야 합니다. Clock는 하드웨어마다 다르고 또한 Clock 설정을 어떻게 했는지에 따라 다릅니다. 먼저 하드웨어 사양을 확인하여 클럭을 확인 하도록 하겠습니다.

클럭에 따라 사용하는 클럭 소스, 출처 : STM32F429 datasheet

  위 사진을 보면 TIM으로 시작하는 것이 타이머입니다. 다양한 타이머가 있다는 것을 확인 할 수 있지만, 타이머에 따라 APB1 또는 APB2에 묶여 있음을 확인 할 수 있습니다. 우리는 TIM3를 사용 할 예정입니다. 그리고 해당 타이머는 APB1에 해당하는 것을 확인 할 수 있습니다.

 

APB1 Timer clock 확인

  이제 STM32CubeIDE로 돌아와 Clock Configuration를 확인 하면 APB1 Timer clocks가 몇 Hz인지를 확인 할 수 있습니다. 그렇다면 우리는 TIM3에 입력 되는 클력은 84MHz라는 것을 확인 하였습니다.

 

TIM3 설정

TIM3의 Clock Source 설정

  이제 TIM3의 Clock Source를 Internal Clock으로 설정하여 APB1 Clock를 사용하도록 합니다. 

 

Prescaler와 Counter Period 설정

  Prescaler는 Clock Source를 나누는 역할을 합니다. -1를 한 이유는 시작 값이 0부터 시작하기 때문입니다. 만약 시작값인 0으로 설정하였다면, Clock Source 그대로 84MHz를 사용한다는 뜻입니다. 또 만약 Prescaler가 1이 었다면 84MHz에서 2를 나누기에 42MHz가 되었을 것입니다. 저는 계산을 하기 쉽게하기 위해 83으로 설정하여  TIM3 Clock을 1MHz으로 설정하였습니다.

TIM3 클럭에 대한 수식

  Counter Period는 목표 값을 설정하는 것입니다. 우리는 TIM3 Clock를 1MHz으로 설정하였으니 Couting register의 값이 1us 마다 값이 1씩 증가합니다. Counting register의 값이 1000에 도달 했다는 의미는 1us초를 1000번 세었으니 1ms가 되었다는 의미입니다. 그러므로 Counter Period 값을 1000으로 설정하였습니다. -1을 한 이유도 Prescaler와 같이 시작 값이 0이기 때문입니다.

Clock를 설정하기 위한 수식
1ms로 설정하기 위한 수식 예

 

 

결과 확인

  이제 TIM3의 대한 설정이 완료 되었으니 내장 LED를 깜빡여 결과를 확인하도록 하겠습니다. 하지만 1ms 마다 깜빡이면 사람의 눈으로 확인하지 못하니, 1초마다 깜빡이도록 하겠습니다.

  먼저 타이머 인터럽트를 설정하도록 하겠습니다. NVIC Settings에 들어가 Interrupt를 Enable 합니다.

 

TIM3에 대한 Timer Interrupt 설정

 

main 함수에서 TIM3 interrupt를 사용하기 위해 아래 처럼 코딩합니다.

 

 

그 다음 HAL_TIM_PeriodElapsedCallback 함수를 정의 하도록 하겠습니다.

먼저 정의 하기 전 선언부터 하도록 하겠습니다.

HAL_TIM_PeriodElapsedCallback 선언
HAL_TIM_PeriodElapsedCallback 정의

 

HAL_TIM_PeriodElapsedCallback 함수는 TIM3의 주기를 1ms으로 설정하였으므로 1ms 마다 자동적으로 호출됩니다.

그리고 cnt 변수를 사용하여 1000를 다시 세므로 LD2는 1초마다 토글 되는 것을 확인 할 수 있습니다.