Реклама ⓘ
Главная » Arduino
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

Цветной OLED дисплей 96х64 пикселя

Эта статья является логическим продолжением вот этой статьи про монохромный OLED дисплей. На этот раз мне в руки достался цветной OLED дисплей, разрешением 96*64 пикселя с магазина Banggood. Пока не забыл, на странице товара есть ссылка на архив с документацией на дисплей: http://files.banggood.com/2016/08/SKU407528.zip

Кроме того достаточно информации по дисплею встречается в сети, так же есть готовые библиотеки для нетерпеливых (от Adafruit, Seeed-Studio и конечно же монстр среди библиотек для дисплеев U8Glib). Я же покажу работу с дисплеем безо всяких библиотек, покажу в среде программирования ArduinoIDE, что бы было понятно новичкам (матерые программисты наверняка разберутся).

Итак, дисплей может подключаться при помощи параллельных интерфейсов (6800, 8080) и последовательного интерфейса SPI. В модуле, который попал мне в руки, реализован SPI протокол.

Цветной OLED дисплей 96х64 пикселя

Распиновка слева-направо: 2 вывода для питания, SCL - предназначен для тактового сигнала, SDA - по этому входу в контроллер дисплея поступают данные, RES - предназначен для сброса дисплея, DC (data/command) - логический сигнал на этом входе сообщает дисплею что в данный момент передается, данные или команда (об этом чуть позже подробнее), CS - обычный chip select протокола SPI, низкий уровень на этом входе сообщает дисплею, что данные, поступающие по нему, предназначены именно для дисплея. Подробно вдаваться в суть протока SPI я не буду, стоит только уточнить, что дисплей работает в режиме SPI_MODE3 (CPOL=1, CPHA=1).

Вас могут смутить обозначения SDA и SCL, ведь они применяются для обозначения выводов устройств, работающих по протоколу I2C, но всё на самом деле не так плохо. Поскольку по линии SDA идут данные от микроконтроллера к дисплею - он подключается к выводу MOSI микроконтроллера (D11 на ардуино). По SCL идут тактовые сигналы, а значит он подключается к выводу SCK микроконтроллера (D13 на ардуино).

Для выводов RES, DC и CS можно выбрать любые выводы (у меня D10 для CS, D8 для DC и  D9 для RES). Библиотека SPI не будет управлять этими выводами, это придется делать вручную. Разберемся для чего нужен каждый из этих выводов.

CS - самое простое, логический 0 говорит дисплею о том, что данные предназначены для него, логическая 1 - о том что передача данных завершена.

RES - служит для сброса дисплея, для этого надо на некоторое время подать на этот вывод логический 0. Это необходимо сделать один раз в начале программы перед инициализацией дисплея.

DC - логический 0, подаваемый на этот вывод, сообщает дисплею о том, что передаются команды, логическая 1 - передаются данные.

На основании этого создаем две функции для отправки команды и данных соответственно. 

#include <SPI.h>

const int ss = 10; //slave select
const int dc = 8; // data/command data=1 command=0
const int reset = 9; //oled reset=0

void oledCommand(uint8_t val) //общая функция отправки команды дисплею
{
  digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI
  digitalWrite(dc, LOW); //DC равен 0, это значит что отправляется команда
  SPI.transfer(val); //отправляем команду стандартной функцией библиотеки SPI
  digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена
}

void oledData(uint8_t val) //общая функция отправки данных дисплею
{
  digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI
  digitalWrite(dc, HIGH); //DC равен 1, это значит что отправляются данные
  SPI.transfer(val); //отправляем данные стандартной функцией библиотеки SPI
  digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена
}
void setup() {

 pinMode(ss, OUTPUT);
 pinMode(dc, OUTPUT);
 pinMode(reset, OUTPUT);

 SPI.begin();
 SPI.setDataMode(SPI_MODE3);
 oledInit();
}
void setup() {

 pinMode(ss, OUTPUT);
 pinMode(dc, OUTPUT);
 pinMode(reset, OUTPUT);

 SPI.begin();
 SPI.setDataMode(SPI_MODE3);
 oledInit();
}

Обратите внимание на функция oledInit() в предпоследней строке кода. Прежде чем дисплей сможет что-либо выводить на экран, его необходимо настроить (инициализировать). Для этого посылаем команды, приведенные в следующей диаграмме.

В программе это будет выглядеть так:

void oledInit() //функция инициализации дисплея
{
  digitalWrite(reset, HIGH); //процедура сброса дисплея
  delay(100);
  digitalWrite(reset, LOW);
  delay(100);
  digitalWrite(reset, HIGH);
  delay(100);
  //процедура инициализации дисплея
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0xAE); //display OFF
  SPI.transfer(0xA0); //remap & color depth setting
  SPI.transfer(0x72);          //b01110010 расшифровка ниже
  /* 
  b01 - 65k format, (00 -256 color, 10 - 65k color format 2)
  1 - enable COM split odd even (0 - disable)
  1 - scan COM95 to COM0 (0 - COM0 to COM95) отражение по короткой стороне
  0 - disable left-right swaping (1 - enable swaping)
  0 - RGB color (1 - BGR color)
  1 - RAM column 0 to 95 (0 - 95 to 0)
  0 - horizontal address increment (1 - vertical)
  */
  SPI.transfer(0xA1); //set display start line (0-63)
  SPI.transfer(0x0);
  SPI.transfer(0xA2); //set vertical offset (0-63)
  SPI.transfer(0x0);
  SPI.transfer(0xA4); //normal display (A5 - all pixel ON, A6 - all pixel OFF, A7 - inverse display)
  SPI.transfer(0xA8); //set MUX ratio N+1 mux
  SPI.transfer(0x3F); //default 0x3F
  SPI.transfer(0xAD); //select internal Vcc supply
  SPI.transfer(0x8E); //default 0x8E
  SPI.transfer(0xB0); //set power saving mode
  SPI.transfer(0x0B); //default 0x0B (disable power saving mode) 0X1A - enable
  SPI.transfer(0xB1); //set reset, pre-charge period
  SPI.transfer(0x31); //default 0x31
  SPI.transfer(0xB3); //oscillator frequency
  SPI.transfer(0xF0); //default 0xF0
  SPI.transfer(0x8A); //set second pre-charge color A
  SPI.transfer(0x64); //default 0x64
  SPI.transfer(0x8B); //set second pre-charge color B
  SPI.transfer(0x78); //default 0x78
  SPI.transfer(0x8C); //set second pre-charge color C
  SPI.transfer(0x64); //default 0x64
  SPI.transfer(0xBB); //set pre-charge voltage level
  SPI.transfer(0x3A); //default 0x3A
  SPI.transfer(0xBE); //set COM deselect voltage level
  SPI.transfer(0x3E); //default 0x3E
  SPI.transfer(0x87); //set master current
  SPI.transfer(0x06); //default 0x06
  SPI.transfer(0x81); //set contrast for color A
  SPI.transfer(0x91); //default 0x91
  SPI.transfer(0x82); //set contrast for color B
  SPI.transfer(0x50); //default 0x50
  SPI.transfer(0x83); //set contrast for color C
  SPI.transfer(0x7D); //default 0x7D
  SPI.transfer(0xAF); //display ON, normal mode
  digitalWrite(ss, HIGH);
}

Теперь дисплей готов к выводу изображения. Но стоит рассмотреть некоторые команды. В частности очень важны следующие строки:

SPI.transfer(0xA0); //remap & color depth setting

SPI.transfer(0x72); //b01110010 расшифровка ниже

/* b01 - 65k format, (00 -256 color, 10 - 65k color format 2) - здесь мы выбираем в каком формате будут задаваться цвета и сколько цветов будет возможно использовать

Поскольку выбираем 65 тысяч цветов, то значение цвета в один байт не поместится, только в два байта.

1 - enable COM split odd even (0 - disable)

1 - scan COM95 to COM0 (0 - COM0 to COM95) отражение по короткой стороне

0 - disable left-right swaping (1 - enable swaping) 0 - RGB color (1 - BGR color) задаем привычный нам формат RGB

1 - RAM column 0 to 95 (0 - 95 to 0)

0 - horizontal address increment (1 - vertical) */ Выбираем как будут выводиться данные на дисплей, слева-направо сверху-вниз (привычный нам способ, потому что и пишем так и массивы задаем) или сверху-вниз слева-направо. Эти методы адресации рассмотрены в предыдущей статье, лишь отмечу что мы будем использовать горизонтальную адресацию.

Поскольку для задания цвета у нас есть всего 2 байта, а формат RGB предполагает 3, то необходимо произвести преобразование. Для красного цвета отводятся первые 5 бит, затем 6 бит зеленого цвета, замыкают 5 бит синего, поэтому функцию преобразования цвета я назвал color565

uint16_t color565(uint8_t r, uint8_t g, uint8_t b) //функция преобразования цвета R8G8B8bit в формат R5G6B5bit
{
  uint16_t c;
  c = r >> 3;
  c <<= 6;
  c |= g >> 2;
  c <<= 5;
  c |= b >> 3;

  return c;// получаем 16-битное значение цвета и возвращаем его
}

Поскольку данными необходимо передавать только цвет, то функцию передачи данных можно переделать в функцию передачи цвета, но 16-битное значение цвета необходимо будет разбить на два 8-битных и послать их одно за другим.

void oledDataColor(uint16_t color) //измененная функция для отправки 16-битного значения цвета
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, HIGH);
  SPI.transfer(color >> 8); //разбиваем 16-битное значение на 2 8-битных
  SPI.transfer(color);
  digitalWrite(ss, HIGH);
}

Теперь можно рисовать, и начну я с базового элемента любого растрового изображения - пикселя. Для отображения графических примитивов предусмотрены готовые функции, но не для пикселя и окружности, поэтому будем изобретать велосипед.

Я упоминал про горизонтальную адресацию, команды и данные, и сейчас я свяжу это всё воедино и поведаю как вывести изображение на дисплей (но делать я этого конечно же не буду).

Представим, что необходимо вывести изображение размером N на N пикселей, левый верхний угол изображения должен находиться в координатах х=X, у=Y. Для этого необходимо выбрать прямоугольную область на дисплее, а затем передать значения цвета пикселей по очереди обходя каждый пиксель изображения слева-направо сверху-вниз. Полученные дисплеем значения цвета так же будут выводиться слева-направо сверху-вниз в пределах выбранной области, и обход пикселей будет таким, как представлен на изображении ниже.

Для выбора области на дисплее необходимо передать команду 0x15,значения Х и У левого верхнего угла области, затем команду 0x75 и значения Х и У правого нижнего угла области. Все эти значения передаются командами, то есть вывод DC подтянут к нулю. Затем подаем на DC логическую единицу и посылаем значения цвета каждого пикселя. Функции отправки команд, данных и цвета я уже привел. Далее необходимо включить фантазию и принять факт что один пиксель - это изображение состоящее из одного пикселя, и процедуру вывода изображения применить к одному единственному пикселю. В итоге получается вот такая функция:

//функция задает цвет выбранной точке
void oledPixel(uint8_t x, uint8_t y, uint16_t color) {
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x15);
  SPI.transfer(x);
  SPI.transfer(95);
  SPI.transfer(0x75);
  SPI.transfer(y);
  SPI.transfer(63);
  delay(1);
  digitalWrite(dc, HIGH);
  SPI.transfer(color >> 8);
  SPI.transfer(color);
  delay(1);
  digitalWrite(ss, HIGH);
}

Далее пойдут уже готовые функции для вывода линии, прямоугольника и залитого прямоугольника. 

//функция отрисовывает линию определенного цвета между двумя указанными координатами
void oledLine (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x21);
  SPI.transfer(x1); //x start
  SPI.transfer(y1); //Y start
  SPI.transfer(x2); //X end
  SPI.transfer(y2); //Y end
  delay(1);
  //здесь синтезированный в формат 565 цвет разбирается отбратно
  //я понимаю что это костыль, но во первых для задания цвета необходимо использовать один аргумент вместо трех
  //а во вторых, я использовал именно такой способ для общего понимания работы с цветом при работе с данным дисплеем
  SPI.transfer((color >> 11) & 0x1F); //R color
  SPI.transfer((color >> 5) & 0x3F); //G color
  SPI.transfer(color & 0x1F); //B color
  delay(1);
  digitalWrite(ss, HIGH);
}

//функция рисует прямоугольник заданной высоты ширины и цвета, левый верхний угол прямоугольника задается первыми двумя аргументами
void oledRect (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x26); //настройка заливки прямоугольника
  SPI.transfer(0x0); //отключаем заливку прямоугольника
  SPI.transfer(0x22);
  SPI.transfer(x); //x start
  SPI.transfer(y); //Y start
  SPI.transfer(x + w); //X end
  SPI.transfer(y + h); //Y end
  delay(1);
  SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame
  SPI.transfer((colorFrame >> 5) & 0x3F); //G color
  SPI.transfer(colorFrame & 0x1F); //B color
  delay(10);
  digitalWrite(ss, HIGH);
}

//то же самое, но прямоугольникк залит определенным цветом (6 аргумент задает цвет заливки)
void oledRectFill (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame, uint16_t colorFill)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x26); //настройка заливки прямоугольника
  SPI.transfer(0x1);  //включаем заливку прямоугольника
  SPI.transfer(0x22);
  SPI.transfer(x); //x start
  SPI.transfer(y); //Y start
  SPI.transfer(x + w); //X end
  SPI.transfer(y + h); //Y end
  delay(1);
  SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame
  SPI.transfer((colorFrame >> 5) & 0x3F); //G color
  SPI.transfer(colorFrame & 0x1F); //B color
  SPI.transfer((colorFill >> 11) & 0x1F); //R color fill
  SPI.transfer((colorFill >> 5) & 0x3F); //G color
  SPI.transfer(colorFill & 0x1F); //B color
  delay(10);
  digitalWrite(ss, HIGH);
}

Так же предусмотрена функция очистки прямоугольной области дисплея и она же используется для очистки всего дисплея.

void oledClear(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x25);
  SPI.transfer(x1);
  SPI.transfer(y1);
  SPI.transfer(x2);
  SPI.transfer(y2);
  delay(1);
  digitalWrite(ss, HIGH);
}

void oledClearAll()
{
  oledClear(0, 0, 95, 63);
}

И ещё команды скролинга дисплея. В них я глубоко не вникал, заставил картинку двигаться вертикально, но не смог заставить двигаться горизонтально. На том и хватит, я вряд ли буду использовать эти команды.

//настройка скролинга дисплея
void oledScrollSetup (uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x27);
  SPI.transfer(a);
  SPI.transfer(b);
  SPI.transfer(c);
  SPI.transfer(d);
  SPI.transfer(e);
  delay(1);
  digitalWrite(ss, HIGH);
}

void oledScrollOn()
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x2F);
  digitalWrite(ss, HIGH);
}

void oledScrollOff()
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x2E);
  digitalWrite(ss, HIGH);
}

 

Приведу весь код "скетча".

#include <SPI.h>

const int ss = 10; //slave select
const int dc = 8; // data/command data=1 command=0
const int reset = 9; //oled reset=0

void oledCommand(uint8_t val) //общая функция отправки команды дисплею
{
  digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI
  digitalWrite(dc, LOW); //DC равен 0, это значит что отправляется команда
  SPI.transfer(val); //отправляем команду стандартной функцией библиотеки SPI
  digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена
}

void oledData(uint8_t val) //общая функция отправки данных дисплею
{
  digitalWrite(ss, LOW); //slave select устанавливаем в 0, это активирует SPI
  digitalWrite(dc, HIGH); //DC равен 1, это значит что отправляются данные
  SPI.transfer(val); //отправляем данные стандартной функцией библиотеки SPI
  digitalWrite(ss, HIGH); //slave select устанавливаем в 1, это означает что работа с SPI завершена
}

void oledDataColor(uint16_t color) //измененная функция для отправки 16-битного значения цвета
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, HIGH);
  SPI.transfer(color >> 8); //разбиваем 16-битное значение на 2 8-битных
  SPI.transfer(color);
  digitalWrite(ss, HIGH);
}

void oledInit() //функция инициализации дисплея
{
  digitalWrite(reset, HIGH); //процедура сброса дисплея
  delay(100);
  digitalWrite(reset, LOW);
  delay(100);
  digitalWrite(reset, HIGH);
  delay(100);
  //процедура инициализации дисплея
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0xAE); //display OFF
  SPI.transfer(0xA0); //remap & color depth setting
  SPI.transfer(0x72);          //b01110010 расшифровка ниже
  /* 
  b01 - 65k format, (00 -256 color, 10 - 65k color format 2)
  1 - enable COM split odd even (0 - disable)
  1 - scan COM95 to COM0 (0 - COM0 to COM95) отражение по короткой стороне
  0 - disable left-right swaping (1 - enable swaping)
  0 - RGB color (1 - BGR color)
  1 - RAM column 0 to 95 (0 - 95 to 0)
  0 - horizontal address increment (1 - vertical)
  */
  SPI.transfer(0xA1); //set display start line (0-63)
  SPI.transfer(0x0);
  SPI.transfer(0xA2); //set vertical offset (0-63)
  SPI.transfer(0x0);
  SPI.transfer(0xA4); //normal display (A5 - all pixel ON, A6 - all pixel OFF, A7 - inverse display)
  SPI.transfer(0xA8); //set MUX ratio N+1 mux
  SPI.transfer(0x3F); //default 0x3F
  SPI.transfer(0xAD); //select internal Vcc supply
  SPI.transfer(0x8E); //default 0x8E
  SPI.transfer(0xB0); //set power saving mode
  SPI.transfer(0x0B); //default 0x0B (disable power saving mode) 0X1A - enable
  SPI.transfer(0xB1); //set reset, pre-charge period
  SPI.transfer(0x31); //default 0x31
  SPI.transfer(0xB3); //oscillator frequency
  SPI.transfer(0xF0); //default 0xF0
  SPI.transfer(0x8A); //set second pre-charge color A
  SPI.transfer(0x64); //default 0x64
  SPI.transfer(0x8B); //set second pre-charge color B
  SPI.transfer(0x78); //default 0x78
  SPI.transfer(0x8C); //set second pre-charge color C
  SPI.transfer(0x64); //default 0x64
  SPI.transfer(0xBB); //set pre-charge voltage level
  SPI.transfer(0x3A); //default 0x3A
  SPI.transfer(0xBE); //set COM deselect voltage level
  SPI.transfer(0x3E); //default 0x3E
  SPI.transfer(0x87); //set master current
  SPI.transfer(0x06); //default 0x06
  SPI.transfer(0x81); //set contrast for color A
  SPI.transfer(0x91); //default 0x91
  SPI.transfer(0x82); //set contrast for color B
  SPI.transfer(0x50); //default 0x50
  SPI.transfer(0x83); //set contrast for color C
  SPI.transfer(0x7D); //default 0x7D
  SPI.transfer(0xAF); //display ON, normal mode
  digitalWrite(ss, HIGH);
}

uint16_t color565(uint8_t r, uint8_t g, uint8_t b) //функция преобразования цвета R8G8B8bit в формат R5G6B5bit
{
  uint16_t c;
  c = r >> 3;
  c <<= 6;
  c |= g >> 2;
  c <<= 5;
  c |= b >> 3;

  return c;// получаем 16-битное значение цвета и возвращаем его
}

//функция задает цвет выбранной точке
void oledPixel(uint8_t x, uint8_t y, uint16_t color) {
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x15);
  SPI.transfer(x);
  SPI.transfer(95);
  SPI.transfer(0x75);
  SPI.transfer(y);
  SPI.transfer(63);
  delay(1);
  digitalWrite(dc, HIGH);
  SPI.transfer(color >> 8);
  SPI.transfer(color);
  delay(1);
  digitalWrite(ss, HIGH);
}

void oledSetArea(uint8_t x, uint8_t y, uint8_t w, uint8_t h) {
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x15);
  SPI.transfer(x);
  SPI.transfer(y);
  SPI.transfer(0x75);
  SPI.transfer(x + w);
  SPI.transfer(y + h);
  delay(1);
  digitalWrite(ss, HIGH);
}

//функция отрисовывает линию определенного цвета между двумя указанными координатами
void oledLine (uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x21);
  SPI.transfer(x1); //x start
  SPI.transfer(y1); //Y start
  SPI.transfer(x2); //X end
  SPI.transfer(y2); //Y end
  delay(1);
  //здесь синтезированный в формат 565 цвет разбирается отбратно
  //я понимаю что это костыль, но во первых для задания цвета необходимо использовать один аргумент вместо трех
  //а во вторых, я использовал именно такой способ для общего понимания работы с цветом при работе с данным дисплеем
  SPI.transfer((color >> 11) & 0x1F); //R color
  SPI.transfer((color >> 5) & 0x3F); //G color
  SPI.transfer(color & 0x1F); //B color
  delay(1);
  digitalWrite(ss, HIGH);
}

//функция рисует прямоугольник заданной высоты ширины и цвета, левый верхний угол прямоугольника задается первыми двумя аргументами
void oledRect (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x26); //настройка заливки прямоугольника
  SPI.transfer(0x0); //отключаем заливку прямоугольника
  SPI.transfer(0x22);
  SPI.transfer(x); //x start
  SPI.transfer(y); //Y start
  SPI.transfer(x + w); //X end
  SPI.transfer(y + h); //Y end
  delay(1);
  SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame
  SPI.transfer((colorFrame >> 5) & 0x3F); //G color
  SPI.transfer(colorFrame & 0x1F); //B color
  delay(10);
  digitalWrite(ss, HIGH);
}

//то же самое, но прямоугольникк залит определенным цветом (6 аргумент задает цвет заливки)
void oledRectFill (uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t colorFrame, uint16_t colorFill)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x26); //настройка заливки прямоугольника
  SPI.transfer(0x1);  //включаем заливку прямоугольника
  SPI.transfer(0x22);
  SPI.transfer(x); //x start
  SPI.transfer(y); //Y start
  SPI.transfer(x + w); //X end
  SPI.transfer(y + h); //Y end
  delay(1);
  SPI.transfer((colorFrame >> 11) & 0x1F); //R color frame
  SPI.transfer((colorFrame >> 5) & 0x3F); //G color
  SPI.transfer(colorFrame & 0x1F); //B color
  SPI.transfer((colorFill >> 11) & 0x1F); //R color fill
  SPI.transfer((colorFill >> 5) & 0x3F); //G color
  SPI.transfer(colorFill & 0x1F); //B color
  delay(10);
  digitalWrite(ss, HIGH);
}


void oledClear(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x25);
  SPI.transfer(x1);
  SPI.transfer(y1);
  SPI.transfer(x2);
  SPI.transfer(y2);
  delay(1);
  digitalWrite(ss, HIGH);
}

void oledClearAll()
{
  oledClear(0, 0, 95, 63);
}

//настройка скролинга дисплея
void oledScrollSetup (uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint8_t e)
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x27);
  SPI.transfer(a);
  SPI.transfer(b);
  SPI.transfer(c);
  SPI.transfer(d);
  SPI.transfer(e);
  delay(1);
  digitalWrite(ss, HIGH);
}

void oledScrollOn()
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x2F);
  digitalWrite(ss, HIGH);
}

void oledScrollOff()
{
  digitalWrite(ss, LOW);
  digitalWrite(dc, LOW);
  SPI.transfer(0x2E);
  digitalWrite(ss, HIGH);
}

void setup() {

  pinMode(ss, OUTPUT);
  pinMode(dc, OUTPUT);
  pinMode(reset, OUTPUT);

  SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  oledInit();
  oledClearAll();
  randomSeed(millis);
}

void loop() {
 oledClearAll();
  oledPixel(10, 10, color565(255, 0, 0));
  oledLine(45, 32, 40, 63, color565(0, 255, 0));
  oledRectFill(60, 0, 10, 20, color565(0, 0, 255), color565(255, 255, 0));
  oledRect(40, 0, 10, 20, color565(255, 255, 0));

  int x = 20, y = 31, w = 10, h = 10;
  oledSetArea(x, y, w, h);
  for (int i = 0; i < (w*h); i++) {
    oledDataColor(color565(random(0, 255), random(0, 255), random(0, 255)));
  }
  
 delay(5000);

}

Результат работы на фото (специально сдвинул экспозицию в минус): вывод точки, линии, залитого и пустого прямоугольника и массива из точек случайного цвета.

Плюсы данного дисплея очевидны: малое потребление из-за отсутствия подсветки, малая толщина дисплея, большие углы обзора, ну и наконец он цветной. Чип SSD1331 позволяет обращаться к каждой точке напрямую ( в отличии от монохромного дисплея на чипе SSD1306), что намного упрощает работу с ним. Ну и библиотеки для этого дисплея уже написаны, а то я тут всё велосипеды изобретаю.

P.S. В архиве скетч, библиотеки для ArduinoIDE и даташиты.

Прикрепленные файлы:

Теги:

Опубликована: 0 0
Я собрал 0 0
x

Оценить статью

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (0) | Я собрал (0) | Подписаться

Статью еще никто не комментировал. Вы можете стать первым.
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Arduino UNO
Arduino UNO
Паяльная станция Hakko 936 Тестер ESR, полупроводников, резисторов, индуктивностей
вверх