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

14. RCC·GPIO 레지스터로 LED

13편의 토대(CMSIS·RCC·클럭)를 처음으로 실전에 씁니다. STM32의 "Hello, World"인 LED 점멸을 HAL 없이 레지스터만으로 구현합니다. Blue Pill의 온보드 LED는 PC13에 액티브 로우로 달려 있죠. 핵심은 STM32F1 특유의 GPIO 설정 — 핀마다 4비트(MODE 2 + CNF 2)를 CRL(핀0~7)·CRH(핀8~15)에 쓰는 방식입니다. 이 4비트 조합을 이해하면 F1의 모든 GPIO 설정이 같은 패턴으로 풀립니다.

GPIOCRL/CRHODRBSRRPC13푸시풀
소요 시간
약 1.5시간
난이도
📊 중급
선수 조건
🎯 13강
결과물
RCC로 GPIO 클럭을 켜고 CRL/CRH의 4비트(MODE+CNF)로 핀을 푸시풀 출력으로 설정해, ODR/BSRR/BRR로 PC13 LED를 토글할 수 있습니다.

이 강의에서 배우는 것

  • 1RCC로 GPIO 클럭을 켜고 F1의 CRL/CRH로 핀 모드를 설정한다
  • 2MODE/CNF 4비트 조합으로 푸시풀 출력 2MHz(0x2)를 만든다
  • 3ODR로 토글하고 BSRR/BRR로 원자적 set/reset을 한다
  • 4액티브 로우 LED(PC13)의 ON/OFF 논리를 이해한다
  • 5지우고(clear) 쓰기(set) 패턴으로 다른 핀을 보존한다

소개

F4/L4의 MODER와 달리 F1은 핀마다 4비트를 CRL/CRH에 씁니다. 핀 n의 4비트는 (n%8)*4 위치에 놓입니다(핀0~7 → CRL, 핀8~15 → CRH).

핵심 개념

1) F1 GPIO 4비트 = MODE + CNF

비트이름의미
[1:0]MODE00=입력, 10=출력2MHz, 11=출력50MHz
[3:2]CNF(출력)00=푸시풀, 01=오픈드레인, 10=AF푸시풀

LED 구동은 빠를 필요 없으니 MODE=10(2MHz)+CNF=00(푸시풀) → 4비트 0b0010 = 0x2. PC13은 CRH의 (13-8)*4=20번 비트부터 4비트.

2) 지우고 쓰기 + 출력 레지스터

c
GPIOC->CRH &= ~(0xFu << 20);   /* PC13 자리 4비트 클리어 */
GPIOC->CRH |=  (0x2u << 20);   /* 0010 설정 */

GPIOC->ODR ^= (1u << 13);       /* 토글(읽고-쓰기) */
GPIOC->BSRR = (1u << 13);       /* 원자적 set (PC13=1) */
GPIOC->BRR  = (1u << 13);       /* 원자적 reset (PC13=0) */
ℹ️

BSRR/BRR은 읽기 없이 특정 핀만 원자적으로 1/0으로 만듭니다 — 인터럽트 환경에서 ODR 읽기-수정-쓰기보다 안전합니다. PC13 LED는 액티브 로우라 핀=0이 ON.

핵심 예제

c
#include "stm32f10x.h"
#define LED_PIN 13u
static void delay(volatile uint32_t c){ while(c--){} }
int main(void) {
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;                 /* GPIOC 클럭 */
    GPIOC->CRH &= ~(0xFu << ((LED_PIN-8u)*4u));
    GPIOC->CRH |=  (0x2u << ((LED_PIN-8u)*4u));         /* 푸시풀 출력 2MHz */
    while (1) {
        GPIOC->ODR ^= (1u << LED_PIN);                  /* PC13 토글 */
        delay(200000u);
    }
}

CRH 비트 조작 검산: 리셋값 0x44444444 → PC13만 0x2로 → 0x44244444. Logic Analyzer에 PORTC.13을 추가하면 주기적 사각파가 보입니다.

자주 하는 실수

Q. 분명히 설정했는데 핀이 안 움직여요.

A. GPIO 클럭(RCC->APB2ENR |= RCC_APB2ENR_IOPCEN)을 먼저 켰는지 확인하세요. 클럭이 없으면 CRH/ODR에 써도 반영되지 않습니다.

Q. 옆 핀 설정까지 같이 바뀌어요.

A. =로 통째 덮어쓰면 다른 핀이 날아갑니다. 항상 &= ~(0xF<<shift)로 그 자리만 지우고 |=로 새 값을 넣으세요.

Q. CRH인데 왜 PC13이 (13-8)*4인가요?

A. CRL은 핀0~7, CRH는 핀8~15를 담습니다. CRH 안에서 핀8이 0번째라 핀13은 (13-8)=5번째 → 비트 20부터입니다.

정리

  • F1 GPIO는 핀당 4비트(MODE+CNF)를 CRL/CRH에 쓴다(푸시풀 출력 2MHz=0x2)
  • 4비트만 바꿀 땐 지우고-쓰기 패턴으로 다른 핀을 보존한다
  • 출력은 ODR(토글)·BSRR/BRR(원자적 set/reset)로 한다
  • PC13 LED는 액티브 로우 — 핀=0이 ON
  • 모든 동작의 전제는 RCC 클럭 인에이블이다

과제

  1. PA5(핀0~7 영역)를 푸시풀 출력으로 설정하는 CRL 비트 조작을 계산
  2. ODR 토글 대신 BSRR/BRR만 써서 LED를 점멸하도록 바꾸기
  3. PC13과 PA5 두 LED를 서로 반대 위상으로 점멸
예제 코드 / 강의 자료

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

GitHub에서 보기 ↗