Skip to content

Bare metal C Ch07 GPIO

Hongjayeong-02 edited this page Sep 21, 2026 · 2 revisions

Ch07. GPIO

목표
GPIO code를 gpio.c / gpio.h로 모듈화하고, PB0 LED 출력과 PC13 Button 입력을 구현한다.


1. 사용 Pin

기능 | Pin -- | -- LD1 Green LED | PB0 B1 User Button | PC13

3. BSRR를 사용하는 이유

GPIOB->BSRR = (1UL << LED_PIN);

은 read 없이 한 번의 write로 pin을 set한다.

bit  0~15 : Set
bit 16~31 : Reset

PB0:

GPIOB->BSRR = (1UL << 0);
GPIOB->BSRR = (1UL << 16);

4. 모듈화

main.c  → 무엇을 할지
gpio.c  → GPIO를 어떻게 제어할지
gpio.h  → 외부에 공개할 interface

5. 실제 프로젝트 구조

Ch07_gpio/
├── Inc/
│   └── gpio.h
└── Src/
    ├── gpio.c
    └── main.c

6. 전체 코드

Inc/gpio.h

#ifndef GPIO_H
#define GPIO_H

#include <stdbool.h>

/* ---- LED (PB0, LD1 녹색) ---- */ void led_init(void); void led_on(void); void led_off(void);

/* ---- Push Button (PC13, B1) ---- */ void button_init(void); bool get_btn_state(void);

#endif /* GPIO_H */

Src/gpio.c

#include "stm32f4xx.h"
#include "gpio.h"

#define LED_PIN 0U /* PB0 = LD1 (녹색) / #define BTN_PIN 13U / PC13 = B1 */

void led_init(void) { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;

GPIOB-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (LED_PIN * 2));
GPIOB-&gt;MODER |=  (0x1UL &lt;&lt; (LED_PIN * 2));

}

void led_on(void) { GPIOB->BSRR = (1UL << LED_PIN); /* Set */ }

void led_off(void) { GPIOB->BSRR = (1UL << (LED_PIN + 16)); /* Reset */ }

void button_init(void) { RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;

GPIOC-&gt;MODER &amp;= ~(0x3UL &lt;&lt; (BTN_PIN * 2));  /* Input */
GPIOC-&gt;PUPDR &amp;= ~(0x3UL &lt;&lt; (BTN_PIN * 2));  /* No pull (보드가 자체 처리) */

}

bool get_btn_state(void) { return (GPIOC->IDR & (1UL << BTN_PIN)) != 0U; /* active-HIGH */ }

Src/main.c

#include "gpio.h"

int main(void) { bool btn_state;

led_init();
button_init();

while (1)
{
    btn_state = get_btn_state();

    if (btn_state)
    {
        led_on();
    }
    else
    {
        led_off();
    }
}

}


7. 코드 동작

led_init()

GPIOB clock을 켜고 PB0을 output으로 설정한다.

led_on()

GPIOB->BSRR = (1UL << LED_PIN);

led_off()

GPIOB->BSRR = (1UL << (LED_PIN + 16));

button_init()

GPIOC clock을 켜고 PC13을 input/no-pull로 설정한다.

get_btn_state()

return (GPIOC->IDR & (1UL << BTN_PIN)) != 0U;

PC13 input 상태를 boolean으로 반환한다.


8. Hardware 흐름

B1
│
▼
PC13
│
▼
GPIOC->IDR
│
▼
get_btn_state()
│
├─ true  → led_on()
│
└─ false → led_off()
│
▼
GPIOB->BSRR
│
▼
PB0
│
▼
LD1

9. 실습 기록

Notion 기록:

text = 800 bytes
data = 0 bytes
bss  = 2560 bytes

10. 핵심 정리

  • GPIO input은 IDR로 읽는다.

  • 출력 set/reset은 BSRR로 처리할 수 있다.

  • B1(PC13)은 project 기록상 active-HIGH다.

  • 이 Chapter부터 peripheral driver를 .c/.h로 분리한다.

Clone this wiki locally