승코딩당당당

[STM32] GPIO 레지스터 직접 제어 – LED Blinking 본문

개발/임베디드

[STM32] GPIO 레지스터 직접 제어 – LED Blinking

승코딩당당당 2026. 2. 3. 17:45

 

이번 실습에서는 STM32 MCU 기반 개발 보드인 Nucleo-L073RZ를 사용하여 GPIO 레지스터를 직접 제어하는 방식(Bare-Metal)으로 LED Blinking을 구현하였다.

HAL 라이브러리나 CubeMX와 같은 고수준 추상화 도구를 사용하지 않고, 메모리 맵에 정의된 레지스터 주소에 직접 접근하여 GPIO 클럭 활성화, 핀 모드 설정(Output), 출력 데이터 제어(ODR)를 순차적으로 구성하였다.

특히 PA5 핀을 출력(GPIO Output)으로 설정한 뒤, ODR 레지스터에 대한 XOR 연산을 이용한 토글 방식busy-wait 기반 delay 함수를 사용하여 LED가 주기적으로 깜빡이도록 구현하였다.

 

본 실습을 통해 아래를 직접 코드로 확인할 수 있었다.

  • STM32가 32비트 MCU라는 점
  • GPIO 핀 하나당 2비트로 모드가 관리되는 구조
  • 컴파일러 최적화로 인한 문제를 방지하기 위한 volatile의 필요성
  • 단순 상수 값이 아닌 비트 마스크 기반 레지스터 제어 방식의 중요성

 

이 실습은 추상화된 라이브러리 사용 이전에,
MCU 하드웨어가 실제로 어떻게 동작하는지를 이해하기 위한 기초 임베디드 실습이라는 점에서 의미가 있다.

 

위 이미지에서 연두색 빛이 들어오도록 실습한다.

 

 


 

사용한 개발 프로그램

  • Keil μVision 5 (MDK-ARM)
  • STM32CubeMX

 


 

주소값을 이용하여 LED2 켜 보기

int main(void)
{
	// RCC-IO_A Enable
	*(unsigned int*)0x4002102c = 0x01;
	
	// IO A port
	// 0x50000000 (A port address)	
	// 0x50000400 (B port address)
	// mode conf
	*(unsigned int*)0x50000000 = 0xEBFFF4FF;  // A port reset
	
	// otype
	*(unsigned int*)0x50000004 = 0;
	// speed
	*(unsigned int*)0x50000008 = 0x0C000C00;
	// pull-up/Down
  *(unsigned int*)0x5000000C = 0x24000000;
	// ODR
	*(unsigned int*)0x50000014 = 0x20;

	
	while(1)
	{
		;
	}
}

 


 

PA5 LED Blinking (깜빡깜빡)

  • GPIO Pin: 5
  • GPIO Group: A
  • Mode: GPO
  • Output Type: PushPull
  • Speed: Very High
  • PUPD: No Pull Up/Pull Down
void delay(volatile unsigned int t)
{
	while(t--);
}

int main(void)
{
	// RCC-IO_A Enable
	*(unsigned int*)0x4002102c = 0x01;
	
	// IO A port
	// 0x50000000 (A port address)	
	// 0x50000400 (B port address)
	// mode conf
	*(unsigned int*)0x50000000 = 0xEBFFF4FF;  // A port reset
	
	// otype
	*(unsigned int*)0x50000004 = 0;
	// speed
	*(unsigned int*)0x50000008 = 0x0C000C00;
	// pull-up/Down
  *(unsigned int*)0x5000000C = 0x24000000;
	// ODR
	*(unsigned int*)0x50000014 = 0x20;

	while(1)
	{
		*(unsigned int*)0x50000014 ^= 0x20;
		delay(100000);
	}
}

 

 

*(unsigned int*)0x4002102c = 0x01;
  • RCC – GPIOA 클럭 Enable
    • GPIOA에 클럭 공급
    • 0x4002102c : RCC IO Port Enable 레지스터
    • 0x01 : GPIOA 비트 ON
*(unsigned int*)0x50000000 = 0xEBFFF4FF;
  • PIOA MODE 설정
    • 0x50000000 → GPIOA MODER 레지스터
  • MODER 구조
    • 핀 하나당 2비트
    • 00: Input
    • 01: Output
    • 10: Alternate
    • 11: Analog
  • PA5를 Output 모드로 설정
  • 나머지 핀은 기존 상태 유지 / 초기화
*(unsigned int*)0x50000004 = 0;
  • Output Type 설정 (Push-Pull)
  • 레지스터
    • OTYPER
  • 0 = Push-Pull
  • 1 = Open-Drain
*(unsigned int*)0x50000008 = 0x0C000C00;
  • 레지스터
    • OSPEEDR
  • 출력 전환 속도 설정
  • Very High → 빠른 토글
*(unsigned int*)0x5000000C = 0x24000000;
  • Pull-Up / Pull-Down 설정
  • 레지스터
    • PUPDR
  • 내부 풀업/풀다운 저항 설정
  • PA5 기준으로는 No Pull 상태
*(unsigned int*)0x50000014 = 0x20;
  • Output Data Register (ODR) 초기값
  • 0x20 = 1 << 5
  • PA5 = HIGH