Как стать автором
Обновить

Вывод текста на OLED дисплей с контроллером SH1106 по шине SPI через библиотеку HAL

Время на прочтение8 мин
Количество просмотров18K
Всего голосов 18: ↑16 и ↓2+14
Комментарии24

Комментарии 24

Наглядный пример того — как не нужно делать.
Уровень железа: инициализация интерфейсов, простые функции записи/чтения для регистров жк экрана. Этот слой всегда уникальный, как для мк, так и для жк экрана. Не нужно надеяться на халл, имеет смысл написать в быстром cmsis варианте — с прямым обращением к регистрам. Но даже этот слой можно поделить на две части, чтобы потом меньше напрягаться.
Отдельно: запись одной цветной точки, запись прямоугольника, очистка цветом, работа со слоями, простейшая математика. Нет регистров, нет абстракций — у вас набор функций для доступа к жк от железного уровня. Впрочем жк экраны бывают разными, большими и маленькими. Этот слой будет отличаться для экранов с внутренней и внешней видеопамятью. Просто два набора функций.
Сверху: печать текста, линии, кривые, векторная графика, и так далее. Вот это уже можно написать всего один раз, и использовать во всех своих проектах.

При таком подходе замена жк экрана на другую модель занимает максимум пол часа — написать несколько функций уровня железа. А иногда они уже готовые попадаются в интернете — достаточно просто переименовать для своих целей имена функций.
Не хочется разжигать холивар HAL vs CMSIS. Умею работать с тем и другим. Хотелось бы услышать поконкретней, какая именно функция HAL является критической по скорости чтобы ее переписывать на регистры?
Пальпация слона с целью обнаружения болезни — весьма затратное предприятие, он толстый везде. Но саму проблему я указал более чем точно — тотальное разделение.
На отдельном слое работы с примитивами — HAL и CMSIS должен отсутствовать!!! У вас для этого есть нижний слой — набор функций работы с железом.
Чтобы добавить дополнительный слой графики — достаточно написать новый примитив.
Чтобы печатать текст — нужна отдельная функция которая печатает символы. Текст всегда одинаковый, а вот символы (формат хранения) бывают разными.

Сколько времени у вас займет переписывание кода для возможности печатать разным шрифтом, добавить слой графики, сменить жк экран, сменить мк???
>Пальпация слона с целью обнаружения болезни — весьма затратное предприятие, он толстый везде.

Вот тут, я с Вами согласен, избыточность HAL иногда просто поражает.

>Но саму проблему я указал более чем точно — тотальное разделение.

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

>На отдельном слое работы с примитивами — HAL и CMSIS должен отсутствовать!!! У вас для этого есть нижний слой — набор функций работы с железом.

Т.е. Вы предлагаете рисовать все по точкам и на низком уровне перебрасывать массив? Если бы я хотел написать универсальную библиотеку под разные дисплеи это бы имело смысл.

>Сколько времени у вас займет переписывание кода для возможности печатать разным шрифтом, добавить слой графики, сменить жк экран, сменить мк???

Тут я совсем перестал вас понимать, возможно, уровня моего просветления не хватает. Вы хотите сказать что переход на другой процессор на CMSIS легче и быстрее чем HAL? Про слои тоже уже звучит как мантра.
Пять простых функций уровня железа:
Одиночная команда без данных, команда с фиксированным количеством данных (два байта), команда с данными переменной длинны, только данные переменной длинны, поднять CS. Последнюю команду можно не использовать, но придётся добавить параметр в две предыдущих. Вот здесь можно использовать дма, и простейшую машину состояний — чтобы не отдавить себе хвост.

Примитивы эксплуатируют команды самого дисплея, буквально командуют дисплеем. При этом графика получается самая простая: нарисовать точку, заполнить прямоугольник, и очистить цветом и так далее. Это позволяет менять дисплеи — переписывая немногочисленные примитивы. Либо использовать уровень абстракции под все дисплеи (почти), благо механика у них практически одинаковая. У вас будет набор #define с абстрактными командами дисплея, куда нужно вписать уже реальные команды. Этот процесс можно немного упростить, так как уже есть библиотеки сразу на много дисплеев. Они используют именно такой принцип.

Верхний уровень — это уже полноценная графика. То самое — что можно не изобретать заново, а просто взять готовое из чужих проектов. У вас будут связанные *.с и *.h файлы, при этом подстановка будет видеть только подключённые файлы — а не весь CMSIS, HAL, вместе с командами дисплея прямо из майна. Между прочим это очень удобно.

GCC потом всё это заоптимизирует, и просто выкинет лишнее.

Насчёт быстрого перехода всё очень просто — переписывается или изменяется только небольшая часть из всего имеющегося. Причём очень малая часть!!! Но с вашим подходом придётся переписывать буквально всё.
Неоднозначно получилось. Конечно любая функция HAL тормознее CMSIS. Имел в виду, в конкретном коде что в HAL тормозит общий результат и требует переписывания на регистрах.
Попытка использовать Вашу библиотечку с ходу не удалась. Во первых тяжёлое наследие AVR в виде #include <avr/pgmspace.h> (хотя бы файлик приложили) и (const uint8_t SmallFont[]) PROGMEM! В STM32 такого нет.
А зачем этот include нужен?
В STM есть:
const uint8_t SmallFont[] =
Ссылку же давал на готовую либу в архиве или на моем сайте imax9.narod.ru
#define SH_CsHi HAL_GPIO_WritePin(GPIOA, CS_Pin, GPIO_PIN_SET)
#define SH_CsLo HAL_GPIO_WritePin(GPIOA, CS_Pin, GPIO_PIN_RESET)
GPIOA надо бы заменить на CS_GPIO_Port, а то у меня это PC1. И всё равно пока не заработал.
Совсем забыл, на STM32F103 у меня не заработало с DMA, пришлось менять функцию пересылки на:
HAL_SPI_Transmit(&hspi3,dt,128,10);
Возможно проблема описана в публикации STM32 — I2C — HAL_BUSY сам я не проверял, перешел на STM32F4 серию.
Давайте, сначала определимся откуда плясать.
1. Какой процессор/плата у вас?
2. Какой экран SSD1306 или SH1106, интерфейс I2C или SPI?
3. Светодиодами Вы уже помигали?
4. Как вы определяете определяете управляющие сигналы и сам SPI?
5. Мусор на экране после инициализации увидели?
6. Логический анализатор какой-нибудь есть?
1. Nucleo-L053R8 & Nucleo-G474RE
2. SH1106 SPI
3. Первым делом.
4. Master Tx Only
5. Нет
6. Logic-U & Saleae logic
Но дело было не в бобине. Не хватало двух команд в sh1106Init, а именно
SH1106_WC(0x8D); // set DC-DC enable
SH1106_WC(0x14);
Странно, у меня заводится и без них, похоже еще у китайцев и разные контроллеры там. Размер дисплея у Вас какой?
Хорошо, спасибо, добавлю в инициализацию. С остальным справились? Все заработало?
Дисплей я использовал от девборды для ADF4111. Заказал ещё три отдельных дисплея все GLCD 0,96 дюйма, пришли все разные. Инициализацию подсмотрел у китайцев с помощью анализатора и у Александра Алексеева тут eax.me/stm32-ssd1306. Засада в том, что в вашей библиотеке используются массив шрифтов char (байт), а у него uint16_t (два байта). В его библиотеке нет подходящего шрифта. В Вашей есть, но не стыкуется. Имеющийся генератор фонтов GLCD Font Creator от Микроелектроники генерит байтные массивы. Разбираюсь с этим.
Засада в том, что в вашей библиотеке используются массив шрифтов char (байт), а у него uint16_t (два байта).

Никто Вам не запрещает работать через указатели и обращаться хоть к байту, полуслову или слову. Библиотеку Алексеева не исследовал, но мне кажется может возникнуть вопрос с ориентацией шрифта, у меня вертикальный, там, судя по всему горизонтальный. Поизучайте статью на датагоре Визуализация для микроконтроллера. Часть 1. OLED дисплей 0.96" (128х64) на SSD1306
У вас яркость дисплея регулировалась? я как не крутил, выставлял разную контрастность, дисплей никак на команду не реагировал.
Странно, еще раз перепроверил, яркость действительно на результат не влияет. Кусок кода остался от ssd1309, вроде когда переносил показалось что влияет, i2c вариант у коллеги по цеху, как выцеплю — результат сообщу.
Хорошо, интересно посмотреть что у других получилось. Хотел сделать дисплей в машину что бы яркость вместе с панелью регулировалась, но тут вышла засада.
Выцепил, вот что выяснил, яркость регулируется только на I2C на обоих контроллерах, различаю первые 4, особенно хорошо видно при малой контрастности. Что вам мешает регулировать контрастность, тот же вид, только в анфас.
У меня как раз I2C дисплеи, первые четыре это 0x0-0x3 значения?

Что вам мешает регулировать контрастность, тот же вид, только в анфас.

Так вроде у контроллера только этот параметр и есть, т.е. он за яркость отвечает. крутил его от минимума до максимума — никакой разницы не увидел.
У меня как раз I2C дисплеи, первые четыре это 0x0-0x3 значения?

Нет, нуля не должно быть: 0x11, 0x22, 0x33, 0x44
Последние значения при высокой контрастности неразличимы.
Так вроде у контроллера только этот параметр и есть, т.е. он за яркость отвечает. крутил его от минимума до максимума — никакой разницы не увидел.

Не только, вот кусок инициализации из мой библиотеки для i2c:
SSD1306_WRITECOMMAND(0xAE); //display off
SSD1306_WRITECOMMAND(0xA8); //--set multiplex ratio(1 to 64)
SSD1306_WRITECOMMAND(0x3F); //
SSD1306_WRITECOMMAND(0x81); //--set contrast control register
SSD1306_WRITECOMMAND(contrast);
if (mirror)
{SSD1306_WRITECOMMAND(0xC0); //Set COM Output Scan Direction
SSD1306_WRITECOMMAND(0xA0);} //--set segment re-map 0 to 127
else {SSD1306_WRITECOMMAND(0xC8); //Set COM Output Scan Direction
SSD1306_WRITECOMMAND(0xA1);} //--set segment re-map 127 to 0
...

SSD1306_WRITECOMMAND(0xD9); //--set pre-charge period
SSD1306_WRITECOMMAND(bright);
SSD1306_WRITECOMMAND(0xAF); //--turn on SSD1306 panel //

Подробнее можете прочитать урок посвященный этому индикатору на моем сайте

Не получается, разница между 0х00 и 0хFF минимальная

По datasheet вполне от 00 - FF можно отправлять значения, может ещё можно настройкой преобразователя изменять яркость?

Тоже хотел родключить PSRAM к контроллеру STM32

https://community.st.com/s/question/0D53W00000NVsy1SAD/esppsram64h-and-stm32h743-qspi-mode

Интересовал режим с мапингом, но контроллеры с функцией мапинга на запись стоят дорого. QuadSPI не пробовали включать?

Какая производительность чтения в простом режиме SPI для PSRAM?

Извиняюсь, пропустил ваше сообщение. QuadSPI не пробовал, но пощупать хотелось бы.

Скорости точно не помню - все упиралось в тормозной SPI, можете сами посчитать. Сейчас покрылось пылью в ящике - пока занят другим направлением.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации