
Datasheet은 해당 링크 에서 확인할 수 있습니다.
Raspberry Pi에서 SSD1306 기반 128×32 OLED 디스플레이를 제어
Linux 커널 I²C 드라이버를 구현하며 실제 동작이 어떻게 이루어지고 있는지를 파악해 봅시다!!.
#define I2C_BUS_AVAILABLE 1 // Raspberry Pi I²C-1 버스
#define SLAVE_DEVICE_NAME "SSD1306" // 드라이버 이름
#define SSD1306_SLAVE_ADDR 0x3C // SSD1306 기본 I²C 주소
#define SSD1306_MAX_SEG 128 // 가로 해상도 (세그먼트)
#define SSD1306_MAX_LINE 3 // 페이지 수 (32줄 → 4페이지, 0~3)
#define SSD1306_DEF_FONT_SIZE 5 // 5×8 폰트
static int I2C_Write(unsigned char *buf, unsigned int len) {
return i2c_master_send(dev_i2c_client_oled, buf, len);
}
Control Byte (8비트) 구조
┌────────────────────────┐
│ 7 6 5 4 3 2 1 0 │
└────────────────────────┘
│ │
│ └─ D/C# (Data/Command#) 비트 (6번째 비트) 1:-> data 0 - > cmd
└──── Co (Continuation bit) (7번째 비트, 거의 0으로 씀)

static void SSD1306_Write(bool is_cmd, unsigned char data) {
unsigned char buf[2] = {0};
buf[0] = is_cmd ? 0x00 : (1 << 6);
// 0x00 = Command, 0x40 = Data
buf[1] = data;
i2c_master_send(dev_i2c_client_oled, buf, 2);
}
Control Byte 의미 (SSD1306 데이터시트 p.20~21)

데이터시트 관련 페이지: p.20~21 (Initialization Flow), p.28~31 (Command Table)

Datasheet에 나와 있는 절차를 따라 software initalization을 진행합니다.
SSD1306_Write(true, 0xAE); // Entire Display OFF
// p.28: 0xAE = Set Display ON/OFF (0=OFF)
SSD1306_Write(true, 0xD5); // Set Display Clock Divide Ratio / Oscillator Frequency
SSD1306_Write(true, 0x80); // Default value (추천값)
// p.32: 0xD5 = Clock 설정, 0x80 = 기본 분주비
SSD1306_Write(true, 0xA8); // Set Multiplex Ratio
SSD1306_Write(true, 0x1F); // 32 COM lines (128×32 OLED용)
// p.31: 0xA8 = Multiplex Ratio, N = 31 (0x1F) → 32줄
SSD1306_Write(true, 0xD3); // Set Display Offset
SSD1306_Write(true, 0x00); // No offset
// p.31: 0xD3 = Vertical shift
-->상세 정보는 38페이지
SSD1306_Write(true, 0x40); // Set Display Start Line = 0
// p.30: 0x40~0x7F = Start Line 설정
SSD1306_Write(true, 0x8D); // Charge Pump Setting
SSD1306_Write(true, 0x14); // Enable charge pump (0x14 = Enable)
// p.63: 0x8D = Charge Pump, 0x14 = Enable (3.3V)
SSD1306_Write(true, 0x20); // Set Memory Addressing Mode
SSD1306_Write(true, 0x00); // Horizontal addressing mode
// p.34: 0x20 = Addressing Mode, 0x00 = Horizontal
SSD1306_Write(true, 0xA1); // Set Segment Remap (Column 127 → SEG0)
// p.31: 0xA0/A1 = Segment Remap
SSD1306_Write(true, 0xC8); // COM Output Scan Direction (Reverse)
// p.31: 0xC0/C8 = COM Scan Direction
SSD1306_Write(true, 0xDA); // Set COM Pins Hardware Configuration
SSD1306_Write(true, 0x02); // Alternative COM pin config (128×32용)
// p.40: 0xDA = COM Pins, 0x02 = Alternative + disable remap
SSD1306_Write(true, 0x81); // Set Contrast Control
SSD1306_Write(true, 0x80); // Contrast = 128 (중간값)
// p.28: 0x81 = Contrast, 0~255
SSD1306_Write(true, 0xD9); // Set Pre-charge Period
SSD1306_Write(true, 0xF1); // Phase1=15, Phase2=1
// p.32: 0xD9 = Pre-charge
SSD1306_Write(true, 0xDB); // Set VCOMH Deselect Level
SSD1306_Write(true, 0x20); // ~0.77×VCC
// p.32: 0xDB = VCOMH, 0x20 = 0.77 VCC
SSD1306_Write(true, 0xA4); // Entire Display ON (RAM 내용 출력)
// p.28: 0xA4/A5 = Resume to RAM / Ignore RAM
SSD1306_Write(true, 0xA6); // Normal Display (1=ON)
// p.28: 0xA6/A7 = Normal / Inverse
SSD1306_Write(true, 0x2E); // Deactivate scroll
// p.29: 0x2E = Deactivate scroll
SSD1306_Write(true, 0xAF); // Display ON
// p.28: 0xAF = Display ON
SSD1306_Fill(0x00); // 전체 화면 지우기 (검정)
데이터시트 관련 페이지: p.29 (0x21, 0x22 명령어)

SSD1306_Write(true, 0x21); // Set Column Address
SSD1306_Write(true, cursorPos); // 시작 컬럼
SSD1306_Write(true, 127); // 끝 컬럼 (128-1)
SSD1306_Write(true, 0x22); // Set Page Address
SSD1306_Write(true, lineNo); // 시작 페이지 (0~3)
SSD1306_Write(true, 3); // 끝 페이지 (32줄 → 4페이지)
데이터시트 관련 페이지: p.32~35 (GDDRAM 구조)
c -= 0x20; // 폰트 배열은 0x20(스페이스)부터 시작
for (temp = 0; temp < 5; temp++) {
data_byte = SSD1306_font[c][temp];
SSD1306_Write(false, data_byte); // Control Byte 0x40 + 5바이트 폰트 데이터
}
SSD1306_Write(false, 0x00); // 글자 끝 여백 1픽셀
데이터시트 관련 페이지: p.25 (GDDRAM Write)
for (i = 0; i < 128 * 4; i++) // 128×32 = 4096비트 = 512바이트
SSD1306_Write(false, data); // 0x00 = 지우기(검정), 0xFF = 채우기(흰색)
데이터시트 관련 페이지: p.30 (0x26/0x27, 0x2F 명령어)

SSD1306_Write(true, is_left_scroll ? 0x27 : 0x26); // 0x26=Right, 0x27=Left
.
SSD1306_Write(true, start_line_no);
SSD1306_Write(true, 0x00); // 5 frames interval (속도)
SSD1306_Write(true, end_line_no);
.
SSD1306_Write(true, 0x2F); // Activate scroll
SSD1306_Write(true, 0x2E); // Deactivate scroll (p.29)
SSD1306_Fill(0x00); // 화면 지우기
SSD1306_String(" ThanK YoU!!! ");
msleep(2000);
SSD1306_Fill(0x00);
SSD1306_Write(true, 0xAE); // Display OFF
⇒ Thank You!! 출력되고 화면 종료
| 함수 | 데이터시트 명령어 | 역할 |
|---|---|---|
SSD1306_DisplayInit() | 0xAE, 0xD5, 0xA8... | 초기화 시퀀스 전체 |
SSD1306_SetCursor() | 0x21, 0x22 | 출력 영역 설정 |
SSD1306_PrintChar() | GDDRAM Write | 픽셀 데이터 쓰기 |
SSD1306_Fill() | GDDRAM Write | 전체 화면 채우기 |
SSD1306_StartScrollHorizontal() | 0x26/0x27, 0x2F | 스크롤 기능 |
SSD1306_Write() | Control Byte + Data | 명령어/데이터 구분 |