Содержание

Графический дисплей 128×64 / I²C: инструкция, примеры использования и документация

Используйте графический дисплей 128×64 / I²C для вывода текста, отрисовки графиков и отображения простых картинок. Монохромный экран выполнен по технологии LCD c разрешением 128×64 пикселей.

Графические дисплеи применяются в домашних охранных системах, робототехнике, МФУ-устройствах, вендинговых автоматах и турникетах общественного транспорта.

Дисплей похвастается интерфейсом I²C, а это значит можно забыть про вермишель из проводов. Для общения с микроконтроллером понадобится всего два сигнальных провода.

Примеры работы для Arduino

Мозгом для проекта выступит платформа Arduino Uno.

Подключение и настройка

Для начала необходимо собрать железо и выполнить программную настройку.

Что понадобится

Схема подключения

Контакт дисплея Контакт Arduino
1 VCC 5V
2 GND GND
3 SCL SCL
4 SDA SDA

Программная настройка

Вывод изображений

Выведем на экран дисплея монохромное изображение. Для этого воспользуйтесь графическим редактором GIMP и преобразуйте исходную картинку в текстовый массив чисел .h.

Основные правила при конвертации изображения:

Image.ino
// Библиотека для работы с модулям по I²C
#include <Wire.h>
 
// Адрес младшего кристалла
#define RW1065I_ADDR_I2C_LOW 0x3C
// Адрес старшего кристалла
#define RW1065I_ADDR_I2C_HIGH 0x3D
// Адрес кристалла управления
#define NF8475A_ADDR_I2C 0x3B
 
// Определение управляющих байт
// control byte C0=0, DC=1, последний упр.байт, дальше только данные
#define CTRL_0_DATA 0x40
// control byte C0=1, DC=1, после байт данных, потом снова упр. байт
#define CTRL_1_DATA 0xC0
// control byte C0=0, DC=0, последний упр.байт, дальше только команды
#define CTRL_0_CMD 0x00
// control byte C0=1, DC=0, после байт команды, потом снова упр. байт
#define CTRL_1_CMD 0x80
 
// Массив картинки логотипа амперки
// Каждые 8 вертикальных точек собраны в байт
const byte amperkaLogo[8][128] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x1F, 0x3F, 0x7F, 0x79, 0x70,
0x70, 0x79, 0x7F, 0x3F, 0x1F, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0x1F, 0x07, 0xF1, 0xF8, 0xFC, 0x1E, 0x0E, 0x0F, 0x07,
0x07, 0x0F, 0x0E, 0x1E, 0xFC, 0xF8, 0xF1, 0x07, 0x1F, 0xFF, 0xFE, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0x7F, 0xFC, 0xF0, 0xE7, 0xCF, 0x9F, 0xBC, 0x38, 0x78, 0x70,
0x70, 0x78, 0x38, 0xBC, 0x9F, 0xCF, 0xE7, 0xF0, 0xFC, 0x7F, 0x3F, 0x0F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0xE0, 0xC0,
0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0, 0x00, 0x00,
0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xE0,
0x60, 0x60, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0xE0, 0xE0, 0xC0, 0x60, 0x60, 0x60, 0x60, 0xE0,
0xC0, 0x80, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x00, 0x00,
0x00, 0x80, 0xC0, 0xE0, 0x60, 0x60, 0x60, 0xE0, 0xC0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x3F, 0x7F, 0xF1, 0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x71,
0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x0F, 0x1E, 0x1E, 0x0F, 0x03, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x7F, 0x7F, 0xE6, 0xC6,
0xC6, 0xC6, 0xC6, 0xE6, 0xE7, 0x67, 0x00, 0x00, 0xFF, 0xFF, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0,
0x71, 0x3F, 0x1F, 0x00, 0x00, 0xFF, 0xFF, 0x0C, 0x0C, 0x1F, 0x3F, 0xF3, 0xE0, 0xC0, 0x00, 0x00,
0x3F, 0x7F, 0xF1, 0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x71, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
 
void drawImage() {
  // Текущая страница
  byte pp = 0;
  // цикл по 8-ми страницам
  for (pp = 0; pp < 8; pp++) {
    // поз. по горизонтали выводимого байта
    byte c = 0;
    // Вывод строки массива, первая половина в мл. кристалл
    Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
    Wire.write("\x80\x3F\x80\xC0\x80\x40\x80");
    for (byte j = 0; j < 4; j++){
      Wire.endTransmission(false);
      Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
      Wire.write(0x80);
      Wire.write(0xB8|pp);
      Wire.write(0x40);      
      for (byte i = 0; i < 16; i++) {
        byte send_data;
        send_data = amperkaLogo[pp][c];
        Wire.write(send_data); c++;
      }
    }
    Wire.endTransmission(false);
    // Вывод строки массива, вторая половина в ст. кристалл
    Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
    Wire.write("\x80\x3F\x80\xC0\x80\x40\x80");
    for (byte j = 0; j < 4; j++) {
      Wire.endTransmission(false);
      Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
      Wire.write(0x80);
      Wire.write(0xB8|pp);
      Wire.write(0x40);
      for (byte i = 0; i < 16; i++) {
        byte send_data;
        send_data = amperkaLogo[pp][c];
        Wire.write(send_data); c++;
      }
    }
    Wire.endTransmission(true);
  }
}
 
// Одиночная команда в обычном режиме
void normComand1 (byte cmd) {
  // Команда, мл. крист.            
  Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
  Wire.write(0x00);
  Wire.write(cmd);    
  Wire.endTransmission(false);
  // Команда, ст. крист.
  Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
  Wire.write(0x00);
  Wire.write(cmd);    
  Wire.endTransmission(true);
}
 
// Инициализация дисплея
void initLCD() {
  // вкл. дисплея, Addr=0, нач.стр.=0, Page=0, мл.кристалл
  Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
  Wire.write(0x80);
  Wire.write(0x3F);
  Wire.write(0x80);
  Wire.write(0x40);
  Wire.write(0x80);
  Wire.write(0xC0);
  Wire.write(0x00);
  Wire.write(0xB8);
  Wire.endTransmission(false);
 
  // вкл. дисплея, Addr=0. ст.кристалл 
  Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
  Wire.write(0x80);
  Wire.write(0x3F);
  Wire.write(0x00);
  Wire.write(0x40);
  Wire.endTransmission(true);
}
 
// Очистка дисплея
void clearLCD(byte f, byte m) {
  Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
  Wire.write("\x80\x3F\x80\xC0\x80\x40\x80");
  for (byte p = 0; p < 8; p++) {
    Wire.endTransmission(false);
    Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);   
    Wire.write(0x80);
    Wire.write(0xB8|p);
    Wire.write(0x40);
    for (byte i = 0; i < 16; i++) {
      Wire.write(f);
      f ^= m;
    }
    for (byte j=0; j < 3; j++) {   
      Wire.endTransmission(false);
      Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
      Wire.write(0x40);
      for (byte i = 0; i < 16; i++) {
        Wire.write(f); f ^= m;
      }
    }
  }
  Wire.endTransmission(true);
 
  Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
  Wire.write("\x80\x3F\x80\xC0\x80\x40\x80");
  for (byte p = 0; p < 8; p++) {
    Wire.endTransmission(false);
    Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);   
    Wire.write(0x80);
    Wire.write(0xB8|p);
    Wire.write(0x40);
    for (byte i = 0; i < 16; i++) {
      Wire.write(f);
      f ^= m;
    }
    for (byte j=0; j < 3; j++) {
      Wire.endTransmission(false);    
      Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
      Wire.write(0x40);
      for (byte i=0; i<16; i++) {
        Wire.write(f);
        f ^= m;
      }
    }
  }
  Wire.endTransmission(true);
}
 
void setup() {
  // Настройка I²C
  Wire.begin();
  Wire.setClock(400000);
  delay(200);
  // Установка регистра управления в исходное состояние - FF
  // Нормальный режим, P_ON
  Wire.beginTransmission(NF8475A_ADDR_I2C);
  Wire.write(0xFF);
  Wire.endTransmission(true);
  delay (500);  
  // power normal, команда расширенного режима
  Wire.beginTransmission(RW1065I_ADDR_I2C_LOW);
  Wire.write(0x80);
  Wire.write(0x0D);
  Wire.write(0x80);
  Wire.write(0x02);
  Wire.write(0x00);
  Wire.write(0x0C);
  Wire.endTransmission(false);
  Wire.beginTransmission(RW1065I_ADDR_I2C_HIGH);
  Wire.write(0x80);
  Wire.write(0x0D);
  Wire.write(0x80);
  Wire.write(0x02);
  Wire.write(0x00);
  Wire.write(0x0C);
  Wire.endTransmission(true);
  clearLCD(0, 0);
  initLCD();
  // Включение полной яркости подсветки
  // Полная яркость подсветки BL_ON2 - "низкий"
  Wire.beginTransmission(NF8475A_ADDR_I2C);
  Wire.write(0xFB);
  Wire.endTransmission(true);
  delay(100);                      
  // Вывод изображения на дисплей
  drawImage();
}
 
void loop() {
}

Элементы дисплея

Дисплей

Дисплей MT-12864K выполнен на монохромной жидкокристаллической матрице с разрешением 128×64 пикселей. Каждый пиксель поддерживает только два состояния: включён или выключен, 1 или 0, true или false.

Матрица экрана подключена к драйверу дисплея, который выполняет роль посредника между экраном и управляющим микроконтроллером.

Драйвер дисплея

В систему драйвера входит три чипа: два контроллера RW1065I и один регистр управления INF8475A.

Контроллер RW1065I

RW1065I LCD Segment Common Driver — это контроллер сегментов с драйвером общих линий для управления матрицей дисплея с разрешением 64×32 пикселя. Для управления графическим дисплеем разрешением 128×64 пикселей, требуется два таких чипа. Первый RW1065I для управления левой половиной сегментов SEG1–SEG64 с общими линиями COM1–COM32, а второй RW1065I для управления правой половиной сегментов SEG65–SEG128 с общими линиями COM33–COM64.

Доступ к каждому контроллеру осуществляется по интерфейсу I²C с заданными I²C-адресами. На плате дисплея есть возможность сменить адреса контроллеров RW1065I. Это даёт возможность подключить к управляющей плате два дисплея одновременно и выводить на каждый экран различные данные, при этом количество занятых пинов останется прежним.

Для смены адресов контроллеров RW1065I на обратной стороне дисплея установлен переключатель Addr1 с контактными площадками R5 и R6.

Капнув припоем на соответствующие контактные площадки, можно получать две разных группы I²C-адресов:

Addr1
R5 R6 Адрес RW1065I #1 Адрес RW1065I #2
L H 0x3C (по умолчанию) 0x3D (по умолчанию)
H L 0x3E 0x3F

Для управления контрастности и яркости на двух дисплей отдельно, необходимо также сменить адрес вспомогательного контроллера INF8475A.

Регистр управления INF8475A

INF8475A Driver — это вспомогательный контроллер для программной регулировки контрастности дисплея, яркость подсветки и других вспомогательных функций.

Доступ к вспомогательному контроллеру осуществляется по интерфейсу I²C с заданными I²C-адресом. На плате дисплея есть возможность сменить адрес регистра RW1065I. Это даёт возможность подключить к управляющей плате два дисплея одновременно и управлять контрастностью/яркостью каждого экрана отдельно, при этом количество занятых пинов останется прежним.

Для смены адреса вспомогательного контроллера INF8475A на обратной стороне дисплея установлен переключатель Addr2 с контактными площадками R17 и R18.

Капнув припоем на соответствующие контактные площадки, можно получать два разных I²C-адреса:

Addr2
R17 R18 Адрес INF8475A
L H 0x3B (по умолчанию)
H L 0x3A

Для вывода на каждый экран различных данных, необходимо также сменить адреса контроллеров RW1065I.

Контакты подключения

На плате дисплея выведено 4 контакта для подключения питания и взаимодействия с управляющей электроникой.

Вывод Обозначение Описание Подключение
1 VIN Питание дисплея Подключите к питанию 2,9–5,5 В.
2 GND Общая земля Подключите к земле.
3 SCL Тактирование шины I²C Подключите к пину SCL микроконтроллера.
4 SDA Данные шины I²C Подключите к пину SDA микроконтроллера.

Габаритные чертёж

Характеристики

Ресурсы

Документация