← Embedded C 강의 목록으로
🔌
STM32
STM32 · 선수: 16강

17. 범용 타이머·PWM 출력

범용 타이머(TIM)는 채널·PWM·입력 캡처를 제공합니다. 가장 많이 쓰는 PWM은 켜진 시간의 비율(듀티)을 빠르게 조절해 LED 밝기나 모터 속도를 "아날로그처럼" 제어합니다. TIM2 채널1(PA0)로 1kHz PWM을 만들고 듀티를 조절합니다. 세 핵심 레지스터 PSC(분주)·ARR(주기)·CCR(듀티)의 관계와, APB1 타이머 클럭이 PCLK1의 2배가 되는 함정을 익힙니다.

타이머PWMPSCARRCCR듀티
소요 시간
약 1.5~2시간
난이도
📊 중급
선수 조건
🎯 16강
결과물
PSC/ARR/CCR로 PWM 주파수와 듀티를 계산·설정하고, AF 푸시풀 핀으로 TIM2 채널1 PWM을 출력할 수 있습니다.

이 강의에서 배우는 것

  • 1범용 타이머의 시간축(PSC·ARR)과 카운터 클럭을 계산한다
  • 2PWM 모드1의 동작(CNT vs CCR 비교)을 이해한다
  • 3TIM2 채널1로 PWM을 출력하도록 레지스터를 설정한다
  • 4CCR로 듀티를, ARR로 주파수를 조절한다
  • 5APB1 타이머 클럭이 PCLK1의 2배가 되는 규칙을 안다

소개

디지털 핀은 0/1만 내지만, 켜진 시간 비율을 빠르게 바꾸면 평균 전압이 달라져 아날로그처럼 동작합니다. 타이머 출력은 GPIO의 대체 기능(AF)이라 PA0를 AF 푸시풀(0xB)로 둬야 합니다.

핵심 개념

1) 시간축 — PSC·ARR·CCR

c
counter_clk = TIMxCLK / (PSC + 1)
pwm_freq    = counter_clk / (ARR + 1)
duty(%)     = CCR * 100 / (ARR + 1)
/* PSC=71 → 72MHz/72 = 1MHz, ARR=999 → 1kHz, CCR=250 → 25% */
⚠️

타이머 클럭 함정: TIM2~4는 APB1 버스인데, APB1 프리스케일러가 1이 아니면 타이머 클럭은 PCLK1의 2배가 됩니다. 표준 72MHz 설정에서 PCLK1=36MHz지만 TIM2 클럭은 72MHz입니다.

2) PWM 모드1과 설정 순서

PWM 모드1: CNT < CCR 동안 출력 High. 설정 순서는 클럭 → 핀(AF) → 시간축(PSC/ARR) → 듀티(CCR) → 모드(CCMR1 OC1M=110+OC1PE) → 출력(CCER CC1E) → UG(강제 로드) → CEN(시작).

c
TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;  /* PWM1(110) */
TIM2->CCMR1 |= TIM_CCMR1_OC1PE;  TIM2->CCER |= TIM_CCER_CC1E;
TIM2->CR1 |= TIM_CR1_ARPE;  TIM2->EGR |= TIM_EGR_UG;  TIM2->CR1 |= TIM_CR1_CEN;

핵심 예제

c
#include "stm32f10x.h"
int main(void){
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    GPIOA->CRL &= ~0xFu; GPIOA->CRL |= 0xBu;   /* PA0 = AF 푸시풀 */
    TIM2->PSC = 71u; TIM2->ARR = 999u; TIM2->CCR1 = 250u;  /* 1kHz, 25% */
    TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1PE;
    TIM2->CCER |= TIM_CCER_CC1E;
    TIM2->CR1 |= TIM_CR1_ARPE; TIM2->EGR |= TIM_EGR_UG; TIM2->CR1 |= TIM_CR1_CEN;
    while (1) { /* CCR1 을 바꾸면 듀티가 즉시 바뀐다 */ }
}

계산 검산: PSC=71,ARR=999,CCR=250 → 1000Hz·25%. CCR=500 → 50%. ARR=499 → 2000Hz. Logic Analyzer에 PORTA.0을 추가하면 듀티 비율을 확인할 수 있습니다.

자주 하는 실수

Q. 핀에서 PWM이 안 나와요.

A. ① PA0를 AF 푸시풀(0xB)로 설정, ② CCER의 CC1E로 출력 켜기, ③ CR1의 CEN으로 카운터 시작 — 세 가지를 확인하세요.

Q. 주파수가 계산의 절반/2배로 나와요.

A. 타이머 클럭을 잘못 잡았습니다. APB1 프리스케일러가 1이 아니면 TIM2 클럭은 PCLK1의 2배(72MHz)입니다. 36MHz로 계산하면 2배 어긋납니다.

Q. 설정을 바꿨는데 첫 주기에 반영이 안 돼요.

A. EGR의 UG 비트로 업데이트 이벤트를 강제하면 PSC/ARR/CCR이 즉시 로드됩니다. 빠뜨리면 다음 업데이트까지 옛 값으로 돕니다.

정리

  • 타이머: PSC로 카운터 클럭, ARR로 주기, CCR로 듀티를 정한다
  • PWM 모드1은 CNT < CCR 동안 High → 듀티 = CCR/(ARR+1)
  • 타이머 출력은 AF 핀(PA0=0xB)으로 내보낸다
  • 설정 순서: 클럭 → 핀 → 시간축 → 모드/출력 → UG → CEN
  • APB1 타이머 클럭은 PCLK1의 2배(72MHz)임에 주의

과제

  1. 듀티를 0→100%로 서서히 올렸다 내리는 LED 호흡(breathing) 효과 구현
  2. PWM 주파수를 500Hz로 바꾸려면 PSC/ARR을 어떻게 할지 계산
  3. CCR ≥ ARR+1 이면 출력이 항상 High(100%)임을 확인
예제 코드 / 강의 자료

전체 강의 자료와 예제 코드(과제·정답 포함)는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗