GPIO 정의 General Purpose Input/Output “범용 입출력 핀”
— MCU(마이크로컨트롤러)가 외부 장치와 데이터를 주고받기 위해 쓰는 다목적 핀

ATmega328P(아두이노 UNO의 MCU)
3개의 8비트 포트를 가짐
→ PORTB (8bit), PORTC (8bit), PORTD (8bit)
| PORTB | Port B — I/O 포트 그룹 | 8비트 (PB0~PB7) | SPI, PWM, Digital 핀 8~13 |
| PORTC | Port C — I/O 포트 그룹 | 7비트 (PC0~PC6) | 아날로그 입력 A0~A5 |
| PORTD | Port D — I/O 포트 그룹 | 8비트 (PD0~PD7) | Digital 핀 0~7, UART |
I/O Switch 입력의 상태

아날로그 > 디지털로 변환해야한다
여기서 주변 전기장에 의해 플로팅 발생으로 인해서 신호가 잘못 인식됨
따라서 풀업 풀다운으로 붙잡아준다.
사진에서는 0.8~2 V 가 플로팅 구간

저항이 VCC와 입력 사이에 존재

저항이 GND와 INPUT 사이에 존재
DataSheet IO Atmega328p 내부 구조

VCC와 입력 사이에 저항 존재 > 풀업 저항 존재
표에 나와있는 레지스터 조건으로 동작시키면 Pull up 을 사용하게된다.
| 이름 | 레지스터 | 역할 |
| DDxn | DDRx (Data Direction Register) | 0이면 Input, 1이면 Output |
| PORTxn | PORTx | Output일 땐 출력값 제어, Input일 땐 풀업 제어 |
| PUD | MCUCR(SFIOR)에 있음 | Pull-up Disable (1이면 풀업 전체 비활성화) |
표에 따르면
| 레지스터 | 설정값 | 의미 |
| DDRx = 0 | 입력 모드 | 핀을 Input으로 설정 |
| PORTx = 1 | 풀업 ON | 내부 풀업 저항 연결 |
| PUD = 0 | 풀업 기능 사용 가능 | MCU 전체의 풀업 기능이 켜져 있음 |
레지스터 초기화
Clock은 MCU의 속도를 조절하고,
Register는 Peripheral(주변장치)을 제어한다.
- Clock → “MCU가 얼마나 빠르게 동작할지”를 결정하는 타이밍 신호
- Register → “MCU 안의 장치(주변장치)”들을 실제로 제어하는 조작
Register 의 3가지
Control : 초기 설정 역할을 하는 레지스터 (설정 메뉴)
Status : 변화에 따른 상태 확인 레지스터 (전송 상태 , 동작 상태 등)
Data : 읽거나 쓸 수 있는 데이터 레지스 (우편함 같이 값)

ex) R/W 인 PUD를 1로 바꾸면 Pull up 안쓰겠다 라고 설정 가능
GPIO 는 status 존재하지 않음
UART 같은 경우 송수신 완료 상태 플래그 레지스터 존재
⚙️ Peripheral(주변장치)의 역할 # 참고
| 분야 | 주변장치 | 예시 설명 |
| 단순 입출력 (I/O) | 🔸 GPIO | LED ON/OFF, 스위치 입력 등 “단순 전압 입출력” |
| 통신 (Communication) | 🔸 UART, SPI, I2C | 센서, 다른 MCU, PC 등과 “데이터 통신” |
| 시간 제어 (Timing) | 🔸 TIMER, PWM | 주기적 인터럽트, 모터 제어, 신호 생성 |
| 아날로그 처리 (Analog) | 🔸 ADC, DAC | 센서 값(전압)을 디지털 값으로 변환 |
| 전원/인터럽트 제어 | 🔸 WDT, INT | 예외 상황 대응, 슬립모드 제어 |
Data Register
PORTx = 데이터 출력 레지스터(Data Register) -> Data register

DDRx = Data Direction Register (데이터 방향 레지스터) -> Control register

PINx = Input Pins Register (입력 핀 레지스터) -> Data register

PORTB는 “입력용”으로 직접 값을 읽는 게 아니라, “입력 시 풀업저항 설정용”으로만 쓸 수 있고,
값을 읽을 때는 반드시 PINB를 사용해야 합니다.
※ PIN은 입력용? PORT 는 출력용? 이건 이후에 코드를 보면서 알아나가자 (확답 x 맞는 거 같음)

예제 Led 불켜기
/*
* Blink_D7_328P.c
*
* Created: 2025-10-19 오후 7:14:12
* Author : 김동하
*/
#define F_CPU 16000000UL // CPU 클럭을 16Mhz 선언
#include <avr/io.h> // 래지스터 라이브러리
#include <util/delay.h> // delay 함수
int main(void)
{
// D5 = PD5 를 출력으로 설정
DDRB |= (1 << DDB5); // DDRB 포트 페리페럴을 (8비트)
while (1)
{
// LED ON (PD7 High)
PORTB |= (1 << PORTB5);
_delay_ms(1100);
// LED OFF (PD7 Low)
PORTB &= ~(1 << PORTB5);
_delay_ms(1100);
}
}
DDRB

PORTB

# 궁금점 PB5랑 PORTB5 랑 뭐가 다름
결론 : avr/io.h 에 정의되어 있는 읽는 사람 입장에서 의미를 명확히 표현한 정수
이 숫자가 어느 레지스터에서 사용되는 비트인지 명확하게 구별하기 위해
| 정수 | 물리 핀 | DDRB | PORTB | PINB |
| 0 | PB0 | DDB0 | PORTB0 | PINB0 |
| 1 | PB1 | DDB1 | PORTB1 | PINB1 |
| 2 | PB2 | DDB2 | PORTB2 | PINB2 |
| 3 | PB3 | DDB3 | PORTB3 | PINB3 |
| 4 | PB4 | DDB4 | PORTB4 | PINB4 |
| 5 | PB5 | DDB5 | PORTB5 | PINB5 |
※구조체로 직접 Register 만들기

매크로 처리된 변수를 사용하지 않고 직접 레지스터 주소를 지정하는 구조체를 만들어서 구현해보자
목적 : 사진의 레지스터 부분만을 접근하기 위한 레지스터 구조체를 직접 구성해보자

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#define PORTB_REG 0x23 // PINB 레지스터 시작 주소
struct io_port
{
unsigned char pin; // 0x23 (PINB)
uint8_t ddr; // 0x24 (DDRB)
uint8_t port; // 0x25 (PORTB)
};
int main(void)
{
struct io_port *portB = (void *)PORTB_REG;
portB->ddr = 0x20; // DDRB = 0x20 → PB5 출력 설정
// 0x20 => 0010 0000
while (1)
{
portB->port = 0x20; // PORTB = 0x20 → PB5 HIGH (LED ON)
_delay_ms(1000);
portB->port = 0x00; // PORTB = 0x00 → PB5 LOW (LED OFF)
_delay_ms(1000);
}
}
직접 구조체를 만들어서 그 구조체의 메모리값을 데이터 시트에 맞게 지정해서 조작해도 된다
C언어 문법 #궁금점 : 특정 메모리 주소를 키리키게 만들기 위함
(void*)의 의미 — “주소로 인식시켜라”
(void*)는 “아무 타입도 없는 포인터(주소)” 이건 어떤 타입인지 모르겠지만 주소임”이라고 컴파일러에게 알려주는 것
즉 그 구조체가 0x23에 존재한다는 걸 알려주는 코드
struct io_port *portB = (void*)0x23;
| 코드 | 의미 |
| struct io_port portB; | 구조체 변수 하나를 RAM에 새로 만든다. (일반적인 변수 생성) |
| struct io_port *portB = (void*)0x23; | 구조체 포인터를 만들고, 그 포인터가 특정 ‘메모리 주소(0x23)’를 가리키게 한다. (기존 하드웨어 주소에 직접 접근) |
'Atmega328p' 카테고리의 다른 글
| {Atmega328p}-Timer , Counter (0) | 2025.10.29 |
|---|---|
| {Atmega328p}-ADC (0) | 2025.10.26 |
| {Atmega328p}-ISR (0) | 2025.10.26 |
| {Atmega328p}-UART 통신 (0) | 2025.10.24 |
| {임베디드}-임베디드 시스템 (0) | 2025.10.21 |