rev.2502211756 : 첫 작성.
이 포스팅을 통해 ST사 MCU의 장치 중 하나인 Timer에 대해서 알아보자.
Timer의 개념
Timer는 어플리케이션의 시간 기반 작업을 처리하기 위한 요소이다.
즉, 어떤 시간 동안 혹은 후에 특정 작업을 수행해야 된다고 할 때, 시간을 계산해주는 장치이다.
이를 활용해, 다양한 기능을 구현할 수 있다.
예를 들어,
Interrupt를 주기적으로 발생시켜 특정 작업을 수행하거나,
외부의 Event에 대해서 시간을 카운트하거나,
PWM 신호를 생성하는 기능을 구현할 수 있는것이다.
Timer의 동작 원리
Timer의 동작 원리는 이렇다.
우선, Timer를 시작하면 Counter Register가 설정된 클럭에 맞춰 1씩 올라간다.
(1MHz라면 1us씩 1씩 올라가는 셈이다.)
그렇게 점점 커지던 Counter가 ARR(Auto-Reload-Register)에 도달하면 overflow가 발생해 카운터가 0으로 초기화되면서 타이머 인터럽트를 발생시킨다.

Timer의 Parameters 및 Registers
ⓐ Control : 타이머의 동작 모드, 속도, 상태 등을 설정
ⓑ Timer Counter : 현재의 타이머 값을 저장하고 증가 혹은 감소시키는데 사용
ⓒ Prescaler : 타이머의 클럭 주파수를 줄이는데 사용
ⓓ ARR : 타이머의 시간을 결정하는 레지스터, 해당 레지스터 값에 카운터가 도달하면 카운터를 리셋 시키는데 사용
ST MCU에서는 해당 레지스터들을 다음과 같이 표기한다.
Control register = TIMx_CRx
Counter register = TIMx_CNT
Prescaler register = TIMx_PSC
Auto-reload register = TIMx_ARR
이 외에도 STM32에서는 타이머를 활용해 다양한 기능을 구현하기 위한 레지스터들이 있는데 모두 작성할 수 없으니, 필요할 때 사용하면서 알아보자.
STM32 Timer CubeMX 세팅

CubeMX에서 제공하는 Timer에 대한 설정 요소들이다.
하나씩 살펴보자.
ⓐ Slave Mode
여러 타이머를 사용할 때, 타이머들간 동기화를 원하면 사용하는 기능이다.
슬레이브로 설정하면 선택한 옵션을 마스터로 하여 그 마스터에 동기화되어 동작한다는 얘기다.

External Clock Mode : 외부 클럭 신호에 의해 동작
Reset Mode : 마스터 타이머의 신호에 의해 리셋
Gated Mode : 마스터 타이머의 신호에 의해 슬레이브 타이머가 활성화/비활성화
Trigger Mode : 마스터 타이머의 신호에 의해 슬레이브 타이머가 트리거
ⓑ Trigger Source
타이머를 동작시키거나 특정 이벤트를 트리거하는 데 사용된다.

ITR : Internal Trigger, 다른 타이머에서 발생하는 이벤트를 트리거 신호로 설정(STM32 내부 트리거를 사용)
ETR : Exterma; Trigger, 외부 핀에서 입력되는 신호를 트리거로 설정(외부 장치나 센서로부터 신호를 받아서 동작 가능)
Software Trigger : 소프트웨어 명령에 의해 트리거, 주로 사용하는 방식
Hardware Trigger : 특정 하드웨어 이벤트에 의한 트리거(ADC 변환 완료 신호나 DMA 전송 완료 신호 등)
ⓒ Clock Source
타이머의 주기를 설정하는 요소

CN_INT : Inter Clock, MCU 내부 클럭 소스를 사용
ETR : External Clock, 외부 핀에서 입력되는 신호를 소스로 사용
ITR : Internal Trigger, 다른 타이머의 출력 신호를 클럭 소스로 사용
LSE : Low-Speed External, LSE를 클럭 소스로 사용
HSE : High-Speed External, HSE를 클럭 소스로 사용
ⓓ Channel x
각 타이머의 채널을 어떤 용도로 사용할 것인지 결정

Input Capture : 외부 신호의 특정 이벤트(rising edge/falling edge)를 캡처하여 타이머 카운터 값 저장(신호의 주기 및 주파수 측정 가능)
Output Compare : 타이머 카운터 값이 지정된 비교 값(ARR)에 도달하면, 출력 신호를 설정하거나 리셋(PWM 신호를 생성하는데 주로 사용)
PWM Generation : PWM 신호를 생성(모터 속도 제어 및 LED 밝기 조절에 사용)
One-Pulse : 한 번의 펄스만을 생성(특정 이벤트의 트리거로 사용)
Forced-Output :
ⓔ Combined Channels
여러 채널을 결합하여 하나의 채널로 동작하도록 하는 기능
실습
타이머 실습 예제로 delay_us 함수를 만들어볼거다.
참고로, 기본 HAL Driver에서는 ms의 Delay 함수밖에 제공하지 않는다. ( HAL_Delay() )
아래 코드가 delay함수의 code이다.
// delay.h
#include "main.h"
extern TIM_HandleTypeDef htim1;
void delay_init(void);
void delay_ms(uint16_t ms);
void delay_us(uint16_t us);
// delay.c
#include "delay.h"
void delay_init(void)
{
HAL_TIM_Base_Start(&htim1);
}
void delay_ms(uint16_t ms)
{
for (uint16_t tmp = 0; tmp < 1000; tmp++)
{
delay_us(ms);
}
}
void delay_us(uint16_t us)
{
htim1.Instance->CNT = 0;
while(htim1.Instance->CNT < us);
}
위 코드를 보면 Timer 동작 시작을 위해서 초기화 함수에 HAL_TIM_Base_Start() 함수를 넣어줬다.
아래 코드는 delay 함수를 이용해 LED를 Toggle하는 예제이다.
// app.h
#include "main.h"
#include "delay.h"
void app_init(void);
void app_main(void);
// app.c
#include "app.h"
void app_init(void)
{
// Device init
delay_init();
}
void app_main(void)
{
app_init();
// variable
while(1)
{
// main code
GPIOA->BSRR = 0xffff0000; // LED OFF
delay_ms(1000);
GPIOA->BSRR = 0x0000ffff; // LED ON
delay_ms(1000);
}
}