STM32 - Timer

EEC·2025년 2월 21일

STM32

목록 보기
3/9

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 : 마스터 타이머의 신호에 의해 슬레이브 타이머가 트리거

  • 관련 레지스터
    SMCR (Slave Mode Control Register): 슬레이브 모드를 설정하는 주요 레지스터
    TS (Trigger Selection): 마스터 타이머의 트리거 소스를 선택
    SMS (Slave Mode Selection): 슬레이브 모드의 동작 방식을 선택

ⓑ Trigger Source
타이머를 동작시키거나 특정 이벤트를 트리거하는 데 사용된다.

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

  • 관련 레지스터
    SMCR (Slave Mode Control Register): 슬레이브 모드에서 트리거 소스를 선택하는 레지스터
    TS (Trigger Selection): 트리거 소스를 선택하는 비트 필드
    예를 들어, 특정 내부 트리거 또는 외부 트리거 핀을 선택할 수 있다.
    EGR (Event Generation Register): 소프트웨어 트리거를 설정하는 레지스터
    소프트웨어 명령을 통해 타이머 이벤트를 생성할 수 있다.

ⓒ Clock Source
타이머의 주기를 설정하는 요소

CN_INT : Inter Clock, MCU 내부 클럭 소스를 사용
ETR : External Clock, 외부 핀에서 입력되는 신호를 소스로 사용
ITR : Internal Trigger, 다른 타이머의 출력 신호를 클럭 소스로 사용
LSE : Low-Speed External, LSE를 클럭 소스로 사용
HSE : High-Speed External, HSE를 클럭 소스로 사용

  • 관련 레지스터
    PSC (Prescaler Register): 클럭 소스를 분주하여 타이머의 동작 속도를 조정
    ARR (Auto-Reload Register): 타이머 카운터가 재설정되는 주기를 설정
    SMCR (Slave Mode Control Register): 슬레이브 모드에서 트리거 소스를 설정
    TIMx_CR1 (Control Register 1): 타이머의 동작 모드와 상태를 설정

ⓓ Channel x
각 타이머의 채널을 어떤 용도로 사용할 것인지 결정

Input Capture : 외부 신호의 특정 이벤트(rising edge/falling edge)를 캡처하여 타이머 카운터 값 저장(신호의 주기 및 주파수 측정 가능)
Output Compare : 타이머 카운터 값이 지정된 비교 값(ARR)에 도달하면, 출력 신호를 설정하거나 리셋(PWM 신호를 생성하는데 주로 사용)
PWM Generation : PWM 신호를 생성(모터 속도 제어 및 LED 밝기 조절에 사용)
One-Pulse : 한 번의 펄스만을 생성(특정 이벤트의 트리거로 사용)
Forced-Output :

  • 관련 레지스터
    CCRx (Capture/Compare Register): 캡처 또는 비교 값을 설정
    CCMRx (Capture/Compare Mode Register): 각 채널의 동작 모드를 설정
    CCER (Capture/Compare Enable Register): 각 채널의 캡처/비교 기능을 활성화 혹은 비활성화
    PSC (Prescaler Register): 타이머 클럭의 분주 비율을 설정
    ARR (Auto-Reload Register): 타이머 카운터의 최대 값을 설정

ⓔ Combined Channels
여러 채널을 결합하여 하나의 채널로 동작하도록 하는 기능

  • 관련 레지스터
    CCMRx (Capture/Compare Mode Register): 각 채널의 동작 모드를 설정
    CCER (Capture/Compare Enable Register): 각 채널의 캡처/비교 기능을 활성화 혹은 비활성화
    CCRx (Capture/Compare Register): 캡처 또는 비교 값을 설정

실습

타이머 실습 예제로 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);
	}
}
profile
느리지만 확실하게

0개의 댓글