💾 EEPROM이란?
1. EEPROM은 전기를 이용해 지우고 다시 쓸 수 있는 비휘발성 메모리임
2. MCU 등 임베디드 시스템에서 설정값, 보정값, 카운터, 고유 ID 등의 저장에 널리 사용됨
🧠 기본 개념
- 비휘발성 메모리: 전원이 꺼져도 데이터가 유지됨
- 읽기/쓰기 모두 가능
- 바이트 단위 접근 가능 (Flash보다 세밀한 제어)
- Flash보다 쓰기 수명이 길고 구현 간편
⚙️ 동작 특성
항목 |
설명 |
저장 방식 |
플로팅 게이트 트랜지스터 기반 비휘발성 저장 |
읽기 |
빠름, 일반적으로 I2C/SPI 통신 기반 |
쓰기 |
보통 수 밀리초(5~10ms), 일부는 페이지 버퍼 지원 |
쓰기 단위 |
바이트 단위 or 페이지 단위 (보통 16/32/64바이트 단위로 최적화됨) |
지우기 단위 |
없음 — 바이트 단위로 덮어쓰기 가능 |
내구성 |
보통 1,000,000회 이상의 쓰기 수명 (Flash보다 우수) |
전원 안정성 |
매우 안정적 — 쓰기 완료 시 전원 차단에도 데이터 유지 가능 |
🧩 EEPROM 종류
유형 |
설명 |
내장 EEPROM |
일부 MCU에 내장됨 (예: ATmega328P, STM32 일부 시리즈 등) |
외장 EEPROM |
I2C 또는 SPI 인터페이스로 연결 (예: 24C32, 25LC256 등) |
📦 외부 EEPROM 예시
모델 |
인터페이스 |
크기 |
쓰기 단위 |
특징 |
24C02 |
I2C |
2Kbit (256B) |
바이트 |
저용량, 주소 제한 있음 |
24C256 |
I2C |
32Kbyte |
페이지 (64B) |
널리 사용되는 표준형 |
25LC512 |
SPI |
64Kbyte |
페이지 (128B) |
빠른 속도, SPI 기반 |
📚 MCU에서 EEPROM 사용 사례
용도 |
설명 |
설정값 저장 |
예: 센서 오프셋, 무선 채널, 디바이스 모드 등 |
부트카운터 저장 |
전원 ON 횟수 기록, 사용량 통계 등 |
고유 식별자 저장 |
UUID, device ID, 페어링 정보 등 |
공장 보정값 저장 |
캘리브레이션 값, 기기별 커스터마이징 데이터 저장 |
✅ EEPROM vs Flash 비교
항목 |
EEPROM |
Flash Memory |
쓰기 단위 |
바이트/페이지 |
섹터 단위 (보통 4KB) |
쓰기 전 지우기 필요 여부 |
❌ 불필요 |
✅ 필수 |
쓰기 속도 |
빠름 (단일 바이트 또는 페이지) |
느림 (섹터 지우기 → 쓰기) |
쓰기 수명 |
약 1,000,000회 |
약 100,000회 |
인터페이스 |
I2C, SPI |
내부 직접 접근, XIP 가능 |
전원 차단 안전성 |
높음 |
낮음 (쓰기 중 꺼지면 데이터 손상 위험) |
구현 난이도 |
낮음 |
중간~높음 (섹터 오프셋 계산 등 필요) |
🔐 사용 시 주의사항
- 쓰기 사이클 관리 필요: 동일 주소 반복 쓰기보다는 wear leveling 구조 적용 권장
- 전원 꺼짐 보호: 일부 EEPROM은 내부 보호 회로 내장, 안정성 높음
- 페이지 경계 주의: 페이지 크기 초과시 자동 wrap-around 가능 → 데이터 손상 주의
- 쓰기 완료 확인: write delay (
_delay_ms()
) 또는 ACK polling 필요
💡 EEPROM 사용 예시 (Arduino + 24C256)
#include <Wire.h>
#define EEPROM_ADDR 0x50
void writeEEPROM(int addr, byte data) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((addr >> 8) & 0xFF); // high byte
Wire.write(addr & 0xFF); // low byte
Wire.write(data);
Wire.endTransmission();
delay(5); // write delay
}
byte readEEPROM(int addr) {
Wire.beginTransmission(EEPROM_ADDR);
Wire.write((addr >> 8) & 0xFF);
Wire.write(addr & 0xFF);
Wire.endTransmission();
Wire.requestFrom(EEPROM_ADDR, 1);
return Wire.read();
}
댓글