그라운드 임베디드 EN 유튜브 구독

노트 / MCU 펌웨어

GPIO: 핀 하나의 모든 설정

입력과 출력, 푸시풀과 오픈드레인, 풀업, 속도, 대체 기능. STM32 GPIO 레지스터 하나하나가 회로의 어떤 부분인지 정리했습니다.

GROUND EMBEDDED · 정리 노트펌웨어 03GPIO 1RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;// 1)… 2GPIOA->MODER &= ~(0x3u << (5 * 2));// 2)… 3GPIOA->MODER |= (0x1u << (5 * 2));// … 4GPIOA->BSRR = (1u << 5);// 3)…
MODER입력·출력·대체·아날로그OTYPER푸시풀·오픈드레인OSPEEDR출력 속도PUPDR풀업·풀다운핀
핀 하나에 걸린 설정들. 어떤 레지스터가 무엇을 정하는지 순서대로 봅니다.

설정 레지스터 (STM32F4 기준)

레지스터 설정
MODER 입력 / 출력 / 대체 기능(AF) / 아날로그
OTYPER 푸시풀 / 오픈드레인
OSPEEDR 출력 에지 속도
PUPDR 풀업 / 풀다운 / 없음
IDR 입력 값 읽기
ODR 출력 값
BSRR 원자적으로 비트 켜기 / 끄기
AFR 대체 기능 번호 (UART, SPI, 타이머 …)

설정 고르는 법

  • 버튼 입력: 입력 + 내부 풀업, 버튼은 그라운드로
  • LED, MOSFET 게이트: 출력 푸시풀
  • I2C: 대체 기능 + 오픈드레인 (+ 외부 풀업)
  • ADC 입력: 아날로그 모드 (디지털 입력 회로를 끊어 누설과 노이즈 감소)
  • 쓰지 않는 핀: 아날로그 모드 또는 출력 LOW

출력 속도

OSPEEDR을 높이면 에지가 날카로워져 고속 통신에 유리하지만 노이즈와 링잉이 커집니다. LED나 릴레이는 가장 낮게 둡니다.

원자적 쓰기

BR15 ~ BR01을 쓰면 해당 핀 LOWBS15 ~ BS01을 쓰면 해당 핀 HIGH
BSRR 레지스터. 아래 16비트에 1을 쓰면 핀이 켜지고, 위 16비트에 1을 쓰면 꺼집니다. 0을 쓴 비트는 그대로입니다.

ODR |= x는 읽기-수정-쓰기라서 인터럽트와 경쟁할 수 있습니다. BSRR에 쓰면 한 번의 쓰기로 특정 비트만 바뀌어 안전합니다.

핀 하나에 걸린 설정들

설정 고를 수 있는 것 언제
모드 입력, 출력, 대체 기능, 아날로그 핀의 역할
출력 형태 푸시풀, 오픈 드레인 여러 장치가 한 선을 공유하면 오픈 드레인
풀업·풀다운 없음, 풀업, 풀다운 떠 있을 수 있는 입력
속도 낮음 ~ 매우 높음 필요한 만큼만. 빠를수록 노이즈가 커짐

레지스터로 LED 켜기 (STM32 계열 예)

RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;        // 1) 포트 클럭부터 켜기

GPIOA->MODER &= ~(0x3u << (5 * 2));         // 2) PA5 모드 필드 지우기
GPIOA->MODER |=  (0x1u << (5 * 2));         //    01 = 출력

GPIOA->BSRR = (1u << 5);                    // 3) 켜기  (set)
GPIOA->BSRR = (1u << (5 + 16));             //    끄기  (reset)

가장 많이 하는 실수는 1번을 빠뜨리는 것입니다. 클럭이 꺼진 주변장치는 레지스터에 값을 써도 반영되지 않습니다. 코드는 문제없어 보이는데 핀이 꿈쩍도 하지 않는다면 클럭부터 확인합니다.

ODR |= ... 대신 BSRR을 쓰는 이유는 읽고-바꾸고-쓰기 과정이 없어서, 인터럽트가 같은 포트의 다른 핀을 건드려도 서로 덮어쓰지 않기 때문입니다.

무료 전자책이 주제를 한 권으로 이어 읽기 (PDF 3권)→

푸시풀과 오픈 드레인

  • 푸시풀: HIGH와 LOW를 모두 직접 구동합니다. LED, 칩 선택 신호 등 대부분의 출력.
  • 오픈 드레인: LOW만 당기고 HIGH는 외부 풀업에 맡깁니다. I2C처럼 여러 장치가 한 선을 쓰는 버스, 서로 다른 전압 사이의 연결에 씁니다.

푸시풀 출력 두 개를 한 선에 묶고 하나는 HIGH, 하나는 LOW를 내면 전원에서 그라운드로 큰 전류가 흘러 핀이 손상됩니다.

입력은 떠 있으면 안 된다

아무것도 연결되지 않은 입력 핀은 주변 노이즈에 따라 0과 1을 오갑니다. 버튼처럼 한쪽 상태에서만 연결되는 입력에는 내부 풀업이나 풀다운을 켭니다. 쓰지 않는 핀은 아날로그 모드로 두거나 출력 LOW로 두면 소비 전류가 줄어듭니다.

버튼 읽기와 디바운스

bool button_pressed(void) {
    static uint8_t hist = 0xFF;
    hist = (uint8_t)((hist << 1) | ((GPIOC->IDR >> 13) & 1u));   // 1 ms마다 호출
    return hist == 0x00;                                           // 8번 연속 LOW
}

1 ms마다 읽은 값을 8비트에 밀어 넣고, 8번 연속 같은 값일 때만 인정합니다. 접점이 떨리는 수 ms를 자연스럽게 걸러 냅니다.

핀 전류 한계

핀 하나가 낼 수 있는 전류와 포트 전체, 칩 전체의 합계 제한이 따로 있습니다. LED 여러 개를 직접 구동할 때는 합계를 확인하고, 릴레이나 모터 같은 부하는 반드시 트랜지스터를 거칩니다.

영상으로 이어 보기회로와 하드웨어 시리즈 8편전자제품 속 회로 소자는 어떻게 동작할까? · 저항 · 커패시터 · 인덕터 완벽 정리PROJECT COURSE레지스터 설정을 실제 보드에서 해 보고 싶다면밸런싱 로봇 하나를 요구사항, 회로와 PCB, 펌웨어, 앱까지 실무 순서대로 만드는 강의입니다. 10파트 165강.강의 살펴보기 →FREE PDF무료 전자책 3권 받기이 주제를 한 권으로 이어서 읽고 싶다면. BLDC 모터 제어, 직렬통신, 센서를 책 분량으로 묶었습니다. 이메일만 남기면 바로 받습니다.무료로 받기 →