Программирование AVR Запуск индикатора OLED WEX025664 на библиотеке u8glib Sat, October 12 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Запуск индикатора OLED WEX025664 на библиотеке u8glib Печать
Добавил(а) microsin   

Эта статья посвящена быстрому старту в использовании OLED-индикатора WEX025664CLPP3N00000 компании Winstar на примере подключения к микроконтроллеру AVR через интерфейс SPI. Использовалась библиотека u8glib [1].

Индикатор основан на контроллере SSD1322 [6]. В Интернете нашел даташит с описанием системы команд, библиотеку u8glib, где была поддержка этого чипа на примере индикатора NHD-3.12-25664 OLED Display. Оказалось, что код для этого индикатора подходит для управления индикатором WEX025664CLPP3N00000.

WEX025664 back side

[Подключение индикатора WEX025664]

В таблице приведена цоколевка коннектора индикатора WEX025664.

WEX025664 connector 30 pin

Мнемоника Описание
1, 30 NC (GND) Зарезервировано для будущего использования, пока должен быть подключен к земле с целью уменьшения помех.
2 VSS Минус питания, общий провод для всех логических сигналов.
3, 29 VCC Силовое для светящихся элементов дисплея, +8..15V. От величины этого напряжения зависит яркость свечения дисплея.
4 VCOMH На этот вывод должен быть подключен фильтрующий танталовый конденсатор, никуда больше он не подключается. В даташите написано, что это выходное напряжение высокого уровня для сигнала COM.
5, 28 VLSS Земля для аналоговых схем. Должен быть подключен к VSS.
6..10 D7..D3 Сигналы данных параллельной шины. В режиме SPI они должны быть подключены к земле (VSS).
11 D2 Сигнал данных параллельной шины. В режиме SPI должен болтаться в воздухе.
12 D1 (MOSI) Сигнал данных параллельной шины. В режиме SPI должен быть подключен к выходу сигнала данных мастера SPI.
13 D0 (SCLK) Сигнал данных параллельной шины. В режиме SPI должен быть подключен к выходу тактового сигнала мастера SPI.
14 E/RD# Сигнал, участвующий в формировании параллельной шины 68XX или 80XX. В режиме SPI не используется, и должен быть подключен к земле (VSS).
15 R/W# Сигнал, участвующий в формировании параллельной шины 68XX или 80XX. В режиме SPI не используется, и должен быть подключен к земле (VSS).
16, 17 BS0, BS1 Входы, которые служат для выбора протокола обмена данными с индикатором (тип используемой шины - 68XX, 80XX, SPI или I2C). Для работы в режиме SPI на эти входы должен быть подан лог. 0 (они должны быть подключены к земле VSS).
18 D/C# Сигнал, который служит для выбора передачи данных (лог. 1) либо команды (лог. 0). В библиотеке u8glib этот сигнал именуется как a0.
19 CS# Chip select, сигнал выборки индикатора, активный уровень лог. 0. Разрешает обмен данными по шине.
20 RES# Сигнал сброса для контроллера и драйвера, активный уровень лог. 0. Для работы этот сигнал не нужен, и на него можно навсегда подать лог. 1.
21 FR Выход, некий служебный сигнал тактирования фрейма. Этот вывод не должен использоваться, и должен оставаться не подключенным.
22 IREF Опорный ток для настройки яркости. Между этим выводом и землей (VSS) должен быть подключен резистор, задающий ток не более 10 мкА (можно поставить резистор номиналом 510..910 кОм). Как мне удалось выяснить, номинал этого резистора никак не влияет на начальную яркость свечения сегментов индикатора.
23 NC Зарезервированный вывод, должен оставаться не подключенным.
24 VDDIO Положительный полюс питания (вход) для буферов подсистемы ввода/вывода, определяет уровни лог. 1. VDDIO не должен превышать уровень VCI, и должен соответствовать уровням лог. 1 мастера шины SPI.
25 VDD Напряжение питания ядра контроллера, выход внутреннего стабилизатора напряжения, если он разрешен (внутренний стабилизатор получает питание от VCI), иначе вход питания. Внимание: допустимый диапазон уровней напряжения, как ни странно, находится в пределах +2.4..2.7V, и его нельзя превышать*! Например, если Вы будете использовать напряжение питания +3.3V, то контроллер будет иногда работать неустойчиво, а от напряжения питания +5V он просто выйдет из строя.
26 VCI Вход внутреннего стабилизатора напряжения.
27 VSL Напряжение низкого уровня для сигнала SEG. Должен оставаться не подключенным.

Примечание *: насколько я понял, напряжение VDD и напряжение лог. 1 зависит от версии индикатора. Есть индикаторы с 3-вольтовым драйвером, как например WEX025664CLPP3N00000 (выделенная жирным шрифтом цифра 3 обозначает 3-вольтовую версию драйвера), а есть с 5-вольтовым. Мне попался 3-вольтовый индикатор.

Для управления индикатором была выбрана макетная плата AVR-USB162, потому что микроконтроллер AT90USB162, установленный на ней, содержит встроенный маломощный стабилизатор напряжения 3.3V, и логические уровни GPIO и SPI микроконтроллера можно переключать перемычкой J3 (5V или 3.3V). Схема подключения к макетной плате AVR-USB162 (микроконтроллер AT90USB162):

WEX025664 connect sch

R1, R3 и соответствующие конденсаторы нужны для фильтрации напряжений питания индикатора. R2 служит для установки опорного тока системы настройки яркости индикатора (см. даташиты на индикатор [4]), его номинал не критичен. Интерфейс индикатора переключен выводами BS0, BS1 в режим SPI, и сигналы данных D0, D1 заведены на сигналы тактов и данных аппаратного интерфейса SPI микроконтроллера AT90USB162.

Для питания индикатора необходим дополнительный источник питания напряжением +12..15V и максимальным током 60 мА. Напряжение питания индикатора +3.3V получено с внутреннего стабилизатора чипа AT90USB162 (перемычку J3 макетной платы AVR-USB162 следует установить в положение 2-3).

[Использование библиотеки u8glib]

Скачайте и установите библиотеку u8glib (см. ссылки [1, 2]). Установка заключается в распаковке папки u8glib из архива в корневой каталог проекта и добавлении всех файлов из каталога src в проект. В пути поиска подключаемых файлов нужно добавить каталог src, потому что там находится заголовочный файл библиотеки u8g.h.

Ссылка на домашнюю страничку проекта: http://code.google.com/p/u8glib/
Страничка U8glib для AVR: http://code.google.com/p/u8glib/wiki/avr 

(или см. ключевые слова для поиска ссылок [1, 2]).

Как подключить библиотеку u8glib к проекту:

1. Загрузите архив u8glib_avr_vX.XX.zip
2. Распакуйте содержимое архива (папку u8glib) в корневой каталог своего проекта
3. Добавьте все файлы (с расширением .c и файл u8g.h) каталога u8glib/src к своему проекту
4. Обновите в проекте путь поиска заголовочных файлов (если это необходимо) 

Для AVR Studio 4 нужно настроить дополнительные опции, пожалуйста см. ссылку:
http://code.google.com/p/u8glib/wiki/avr 

Пошаговые инструкции для Atmel Studio 6:
http://code.google.com/p/m2tklib/wiki/as6

Обычно все проекты для AVR, созданные как для AVR Studio 4, так и для Atmel Studio, так и для Eclipse, так и для MS Visual Studio (да-да, Вы не ослышались, программы для AVR можно разрабатывать и под управлением среды Visual Studio, см. [5]) компилируют исходный код с использованием тулчейна avr-libc (сборка WinAVR или сборка компании Atmel). Это означает использование для проекта makefile и утилиты make. Чтобы добавить в проект компиляцию модулей библиотеки U8glib, нужно соответствующим образом отредактировать makefile проекта. Вот пример такого makefile (этот файл взят из библиотеки LUFA, пример устройства USB из каталога Demos\Device\ClassDriver\GenericHID\):

MCU          = at90usb162
ARCH         = AVR8
#BOARD        = USBKEY
BOARD        = MICROSIN162
F_CPU        = 8000000
F_USB        = $(F_CPU)
OPTIMIZATION = s
TARGET       = GenericHID
#SRC          = $(TARGET).c Descriptors.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
SRC          = $(wildcard *.c) $(wildcard u8glib/src/*.c) $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH    = c:/asm/lufa-LUFA-140928/LUFA
CC_FLAGS     = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -Iu8glib/src/ -ffunction-sections -fdata-sections
LD_FLAGS     =
 
# Default target
all:
 
# Include LUFA build script makefiles
include $(LUFA_PATH)/Build/lufa_core.mk
include $(LUFA_PATH)/Build/lufa_sources.mk
include $(LUFA_PATH)/Build/lufa_build.mk
include $(LUFA_PATH)/Build/lufa_cppcheck.mk
include $(LUFA_PATH)/Build/lufa_doxygen.mk
include $(LUFA_PATH)/Build/lufa_dfu.mk
include $(LUFA_PATH)/Build/lufa_hid.mk
include $(LUFA_PATH)/Build/lufa_avrdude.mk
include $(LUFA_PATH)/Build/lufa_atprogram.mk

Здесь в макроопределение SRC добавлена компиляция файлов u8glib с помощью директивы $(wildcard u8glib/src/*.c). Пути поиска заголовочных файлов обновлены путем добавления к макроопределению CC_FLAGS опции -Iu8glib/src/.

/*-----------------------------------------------------------------------
   Простой пример запуска индикатора WEX025664BLPP3N00000, подключенного
   к макетной плате AVR-USB162.
-----------------------------------------------------------------------*/
#include < avr/io.h >
#include "u8g.h"
 
//Сигналы, которые идут на OLED-индикатор WEX025664BLPP3N00000
#define  DC       PB4   //выход, Data/Command Control.
#define  _CS      PB0   //выход, сигнал выборки (лог. 0).
//Сигналы SPI (для передачи данных в OLED-индикатор WEX025664BLPP3N00000)
#define  _SS      PB0
#define  MOSI     PB2
#define  SCK      PB1
 
u8g_t u8g;
 
static void draw(void)
{
  u8g_SetFont(&u8g, u8g_font_6x10);
  u8g_DrawStr(&u8g, 0, 15, "Hello World!");
}
 
static void InitOLED (void)
{
   // Настроить PB4(/SS), PB5(MOSI), PB7(SCK) как выходы:
   DDRB   |= (1 << _SS)|(1 << MOSI)|(1 << SCK);
   //Инициализация индикатора:
   u8g_InitHWSPI(&u8g, 
                 &u8g_dev_ssd1322_nhd31oled_bw_hw_spi,
                 PN(1, _CS),
                 PN(1, DC),
                 U8G_PIN_NONE);
}
 
int main(void)
{
   SetupHardware();
   InitOLED();
   for (;;)
   {
      draw();
      u8g_FirstPage(&u8g);
      do
      {
         draw();
      } while ( u8g_NextPage(&u8g) );
      u8g_Delay(100);
   }
}

Пример вывода текста "Hello World!" я взял из файла u8glib\examples\hello_world\hello_world.c библиотеки. Изначально этот код был рассчитан на микроконтроллер ATmega88, я запустил его на микроконтроллере AT90USB162, отредактировав опции makefile и поправив код модуля u8g_com_atmega_hw_spi.c. Пояснения к коду:

1. Инициализация индикатора происходит в процедуре InitOLED с помощью вызова функции u8g_InitHWSPI. Эта функция инициализирует аппаратный интерфейс SPI для доступа к индикатору. Функция принимает следующие параметры:

*u8g указатель на глобальную переменную, где хранятся текущие данные индикатора.

*dev указатель на предопределенный тип индикатора. Все возможные типы перечислены в заголовочном файле u8glib\src\u8g.h, Вам нужно выбрать один из этих типов, который подходит к используемому индикатору.

PN(1, _CS) макрос, который задает ножку порта микроконтроллера для выборки индикатора. Первый параметр макроса (1) указывает PORTB (0 соответствует PORTA, 1 соответствует PORTB, 2 соответствует PORTD и т. д.), а второй параметр (_CS) задает номер разряда используемого порта (от 0 до 7).

PN(1, DC) макрос, который задает ножку порта микроконтроллера для выбора Command/Data (сигнал DC).

U8G_PIN_NONE задает сигнал сброса. Это макроопределение означает, что сигнал сброса не используется. По идее тут должен быть макрос наподобие PN(1, _RES). Но на самом деле опытным путем я выяснил, что если указать сигнал сброса, то код индикатора не работает, потому что ошибочно постоянно выставляется низкий уровень сигнала сброс.

2. При компиляции могут быть ошибки, связанные с неиспользуемыми модулями кода библиотеки в каталоге src. Ненужные модули удалите. Я удалил следующие модули (это значительно ускорило компиляцию проекта):

chessengine.c                      u8g_dev_pcd8544_84x48.c
u8g_com_arduino_attiny85_hw_spi.c  u8g_dev_pcf8812_96x65.c
u8g_com_arduino_common.c           u8g_dev_sbn1661_122x32.c
u8g_com_arduino_fast_parallel.c    u8g_dev_ssd1306_128x32.c
u8g_com_arduino_hw_spi.c           u8g_dev_ssd1306_128x64.c
u8g_com_arduino_hw_usart_spi.c     u8g_dev_ssd1309_128x64.c
u8g_com_arduino_no_en_parallel.c   u8g_dev_ssd1327_96x96_gr.c
u8g_com_arduino_parallel.c         u8g_dev_ssd1351_128x128.c
u8g_com_arduino_port_d_wr.c        u8g_dev_st7565_64128n.c
u8g_com_arduino_ssd_i2c.c          u8g_dev_st7565_dogm128.c
u8g_com_arduino_st7920_custom.c    u8g_dev_st7565_dogm132.c
u8g_com_arduino_st7920_hw_spi.c    u8g_dev_st7565_lm6059.c
u8g_com_arduino_st7920_spi.c       u8g_dev_st7565_lm6063.c
u8g_com_arduino_std_sw_spi.c       u8g_dev_st7565_nhd_c12832.c
u8g_com_arduino_sw_spi.c           u8g_dev_st7565_nhd_c12864.c
u8g_com_arduino_t6963.c            u8g_dev_st7687_c144mvgd.c
u8g_com_arduino_uc_i2c.c           u8g_dev_st7920_128x64.c
u8g_com_atmega_parallel.c          u8g_dev_st7920_192x32.c
u8g_com_atmega_st7920_spi.c        u8g_dev_st7920_202x32.c
u8g_com_atmega_sw_spi.c            u8g_dev_t6963_128x128.c
u8g_com_i2c.c                      u8g_dev_t6963_128x64.c
u8g_com_raspberrypi_hw_spi.c       u8g_dev_t6963_240x128.c
u8g_com_raspberrypi_ssd_i2c.c      u8g_dev_t6963_240x64.c
u8g_dev_a2_micro_printer.c         u8g_dev_tls8204_84x48.c
u8g_dev_ht1632.c                   u8g_dev_uc1601_c128032.c
u8g_dev_ili9325d_320x240.c         u8g_dev_uc1608_240x128.c
u8g_dev_ks0108_128x64.c            u8g_dev_uc1608_240x64.c
u8g_dev_lc7981_160x80.c            u8g_dev_uc1610_dogxl160.c
u8g_dev_lc7981_240x128.c           u8g_dev_uc1611_dogm240.c
u8g_dev_lc7981_240x64.c            u8g_dev_uc1611_dogxl240.c
u8g_dev_lc7981_320x64.c            u8g_dev_uc1701_dogs102.c
u8g_dev_ld7032_60x32.c             u8g_dev_uc1701_mini12864.c

3. При портировании кода на другие микроконтроллеры AVR возможно потребуется редактирование модуля u8g_com_atmega_hw_spi.c библиотеки. Также необходимо вручную настроить аппаратный сигнал ~SS как выход (почему так, см. [3]).

WEX025664 Hello World

Исходный код моего тестового проекта и документацию можете скачать в архиве по ссылке [4].

4. Если у Вас индикатор, у которого размер экрана по горизонтали больше 248 точек (это как раз верно для нашего примера с индикатором WEX025664BLPP3N00000), то не забывайте о макроопределении U8G_16BIT (он находится в файле u8g.h). Если его не раскомментировать, то размер экрана уменьшится на 8 точек по горизонтали, и вместо 256 станет 248 (меньше на 4 точки слева и меньше на 4 точки справа). Если макрос U8G_16BIT определен, то затраты памяти несколько увеличатся, но зато будет доступен полный размер экрана.

[Как устранить паразитную засветку]

На фотографии выше Вы наверное заметили полосы засветки, которые появляются за светящимися элементами изображения. Причина в неправильной настройке выхода опорного напряжения VSL. Эта настройка делается с помощью команды 0xB4 (Display Enhancement A) контроллера SSD1322 [6].

Скорее всего, в Вашей схеме подключения внешний вывод VSL остался не подключенным. Однако почему-то в библиотеке u8glib по умолчанию применена неправильная настройка в команде 0xB4, прописанная в массиве команд установки режима u8g_dev_ssd1322_1bit_nhd_312_init_seq[] (см. модуль u8glib\src\u8g_dev_ssd1322_nhd31oled_bw.c, если у Вас индикатор работает в черно-белом режиме) или u8g_dev_ssd1322_2bit_nhd_312_init_seq[] (u8glib\src\u8g_dev_ssd1322_nhd31oled_gr.c, если используются градации серого). В первом байте команды выдается байт 0xA0 в расчете на подключенные внешние цепи к выводу VSL, но здесь ошибка, нужно исправить на 0xA2:

  ...
  U8G_ESC_ADR(0), /* режим инструкции */
  0x0b4,          /* Display Enhancement A */
  U8G_ESC_ADR(1), /* режим данных */
  //0x0a0,   это неправильно!
  0x0a2, // правильная настройка
  0x005|0x0fd,
  ...

WEX0256640 cmd B4 A0 FD WEX0256640 cmd B4 A2 FD

[Как снизить энергопотребление индикатора]

Ток потребления индикатора OLED почти прямо пропорционально зависит:

1. От яркости пикселей.
2. От количества светящихся пикселей.

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

Также ток потребления в некоторой степени зависит от настройки внутреннего тактового генератора (см. команду 0xB3 [6]). Общее правило - чем меньше частота сканирования матрицы OLED, тем меньше потери на перезарядку емкостей, и тем меньше потребление энергии. Однако эта регулировка дает незначительную экономию в сравнении с экономией, которую можно достичь управлением яркостью. Обычно частоту сканирования уменьшают до минимума, пока не станет заметным мерцание экрана.

Для экономии энергии можно также временно выключать экран (команда 0xA4) и включать его при необходимости (команда 0xA5). Можно выключать напряжение питания сегментов +15V. Также имеется команда, переводящая контроллер в режим сна (0xAE), и возвращающая контроллер в рабочее состояние (0xAF).

[Ссылки]

1. u8glib site:code.google.com.
2. Install, setup for AVR Wiki u8glib site:code.google.com.
3. AVR151: настройка и использование SPI.
4. 150220151734WEXtest.zip - исходный код проекта, документация.
5. Использование MS Visual Studio IDE для программирования AVR/Arduino.
6. SSD1322: контроллер/драйвер для дисплеев OLED/PLED.

 

Комментарии  

 
0 #1 Игорь 30.01.2021 10:34
Большое спасибо. Только здесь нашёл, как убрать засветку, которая появилась у меня вне зависимости от того, что VSL не болтался в воздухе.
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page