Обычно для OLED нужны 4-5 пинов. Но мы можем использовать ShiftOut для эмуляции SPI всего на одном пине данных + питание.
Схема подключения:
- Пин данных → DIN (MOSI) дисплея
- GND → GND дисплея
- VCC → VCC дисплея
- Питание → VDD дисплея (через резистор 10 кОм)
Код для управления OLED через один пин:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define OLED_PIN PB0 // Пин 8
#define OLED_PORT PORTB
#define OLED_DDR DDRB
// Отправка байта через один провод (протокол 1-Wire SPI)
void oled_send_byte(uint8_t data, uint8_t isCommand) {
// Начинаем с LOW
OLED_PORT &= ~(1 << OLED_PIN);
_delay_us(1);
// Отправляем биты (MSB first)
for (uint8_t i = 0; i < 8; i++) {
if (data & 0x80) {
OLED_PORT |= (1 << OLED_PIN);
} else {
OLED_PORT &= ~(1 << OLED_PIN);
}
_delay_us(2);
data <<= 1;
}
// Завершаем HIGH
OLED_PORT |= (1 << OLED_PIN);
_delay_us(2);
}
// Инициализация OLED
void oled_init() {
OLED_DDR |= (1 << OLED_PIN); // Пин как выход
OLED_PORT |= (1 << OLED_PIN); // Начинаем с HIGH
_delay_ms(100);
// Команды инициализации для SSD1306
oled_send_byte(0xAE, 1); // Display off
oled_send_byte(0xD5, 1); // Set display clock divide
oled_send_byte(0x80, 1);
oled_send_byte(0xA8, 1); // Set multiplex
oled_send_byte(0x1F, 1); // 32 строки
oled_send_byte(0xD3, 1); // Set display offset
oled_send_byte(0x00, 1);
oled_send_byte(0x40, 1); // Set start line
oled_send_byte(0x8D, 1); // Charge pump
oled_send_byte(0x14, 1); // Enable charge pump
oled_send_byte(0x20, 1); // Memory mode
oled_send_byte(0x00, 1); // Horizontal
oled_send_byte(0xA1, 1); // Segment remap
oled_send_byte(0xC8, 1); // COM output scan direction
oled_send_byte(0xDA, 1); // COM pins hardware config
oled_send_byte(0x02, 1);
oled_send_byte(0x81, 1); // Contrast
oled_send_byte(0x7F, 1);
oled_send_byte(0xD9, 1); // Precharge period
oled_send_byte(0xF1, 1);
oled_send_byte(0xDB, 1); // VCOM detect
oled_send_byte(0x40, 1);
oled_send_byte(0xA4, 1); // Display on resume
oled_send_byte(0xA6, 1); // Normal display
oled_send_byte(0xAF, 1); // Display on
}
// Отправка пиксельных данных
void oled_draw_pixel(uint8_t x, uint8_t y, uint8_t color) {
// Устанавливаем страницу
oled_send_byte(0x22, 1); // Page start/end
oled_send_byte(0x00, 1);
oled_send_byte(0x07, 1);
// Устанавливаем колонку
oled_send_byte(0x21, 1); // Column start/end
oled_send_byte(0x00, 1);
oled_send_byte(0x7F, 1);
// Отправляем пиксельные данные
for (uint8_t i = 0; i < 128 * 8; i++) {
oled_send_byte(color ? 0xFF : 0x00, 0);
}
}
void setup() {
oled_init();
oled_draw_pixel(0, 0, 1); // Рисуем точку
}
void loop() {}