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

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


Рекомендуемые сообщения

Эта статья является логическим продолжением  вот этой статьи про монохромный OLED дисплей. На этот раз мне в руки достался цветной OLED дисплей, разрешением 96*64 пикселя от магазина Banggood (ссылка на дисплей) Пока не забыл, на странице товара есть ссылка на архив с документацией на дисплей.

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

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

62655aba-99d9-4e7e-bc7f-64a87026f4b2.jpg.30706c92beed7ec64cdc91f2f8b8e268.jpg

Распиновка слева-направо: 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() в предпоследней строке кода. Прежде чем дисплей сможет что-либо выводить на экран, его необходимо настроить (инициализировать). Для этого посылаем команды, приведенные в следующей диаграмме.

init.PNG.09f1217c6857e98ae6f973b28b889914.PNG
init.PNG

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

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 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. Для этого необходимо выбрать прямоугольную область на дисплее, а затем передать значения цвета пикселей по очереди обходя каждый пиксель изображения слева-направо сверху-вниз. Полученные дисплеем значения цвета так же будут выводиться слева-направо сверху-вниз в пределах выбранной области, и обход пикселей будет таким, как представлен на изображении ниже.

addressing.PNG.a3629c0c071ccce5f73e91973a9f584d.PNG

Для выбора области на дисплее необходимо передать команду 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);



}

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

20171009_142928.thumb.jpg.dd8a3edbd25d7eb7689a10cdabc4ea85.jpg

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

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

SSD1331.rar

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...