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

Мобильные экранчики в ваших проектах: большой и понятный о гайд о различных дисплеях

Уровень сложности Средний
Время на прочтение 18 мин
Количество просмотров 4.7K
Всего голосов 53: ↑51 и ↓2 +49
Комментарии 89

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

Объявление среди читателей

Я хочу пива.

< Раньше здесь был анонс новой рубрики, но никто не оценил, поэтому оставлю так:( >

Ну и конечно-же не забываем о том, какие статьи ждут нас в ближайшее время!

  1. У нас давненько не было статей в рубрике о принципах работы GPU из 90х и 2000х годов. Я планировал написать про Xbox Original и его GeForce 3 - первый GPU NV с поддержкой программируемого пайплайна, а также про PowerVR MBX - первый массовый мобильный GPU, который использовался, например, в Nokia N95, Dell Axim X51v (в виде Intel 2700G) и iPhone 2G/3G В процессе голосования в моей телеге, читатели выбрали статью именно про мобильный GPU!

  2. Я продолжу развивать тематику бюджетных копий и их ремонта. Буквально вчера я купил подделку iPhone 14 Pro Max в неизвестном состоянии за тыщу рублей. Девайс оказался после воды и ребутился на заставке, однако мне удалось его оживить, перекопав половину платы. Я во всех подробностях расскажу, как диагностировать аппаратные проблемы программными методами, как читать логи и сопоставлять их с аппаратными болячками, а также подниму такой "айфон" и расскажу на что он способен в наше время!

Спасибо за крутяцкую статью. Как говорится, разрешите докопаться.

	lcmData(0x2C);
	lcmData(0x2D);
	lcmCommand(0xB2);
	lcmData(0x01);
	lcmData(0x2C);
	lcmData(0x2D);

За такое всем студентам бил по рукам. Да и сам, когда спустя годы попытаешься понять что здесь происходит опухнешь. Все константы надо вынести в #define и обозвать что она означает. Тогда потом понять почему такая последовательность не возникнет вопросов.

Как минимум ставить комментарии, чтобы потом понять какая команда за что отвечает.

Комментарии да, но иной раз проще define поправить, особенно если вдруг это используется где-то чаще чем один раз. А тут даже на приведённом фрагменте видно что есть однотипные последовательности. Короче, это прям злое-зло.

И зря били, тут дело вкуса.

Я всегда считал init sequence дисплея эдаким чёрным ящиком, который один раз проинициализировал с нужными настройками гаммы, LUT'ом, развёрткой и т.п, читабельным должен оставаться только основной интерфейс к нему. Разве что регистры DBI есть смысл обернуть в константы.

Более того, как я уже подметил выше, большинство коммерческих производителей смартфонов, планшетов и.т.п пихают весь init sequence просто в массив байтов, который нужно переслать на дисплей. НОЛЬ объяснений :)

понять почему такая последовательность не возникнет вопросов.

Я некоторые регистры наизусть помню, другие мне не проблема найти в ДШ :)

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

Ошибиться в чём, если это чёрный ящик? :)

Внешний интерфейс к дисплею должен оставаться более чем читабелен, как и манипуляция общепринятыми регистрами типа того же направления развертки или старта записи в VRAM. Инит никого не заботит, его один раз запилили и забыли. Нужно скорректировать, например, напряжение драйвера в самом контроллере? Посмотрели в ДШ где, что и как и скорректировали.

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

Да и не нужно :)

Вопросы насчёт кодстайла, архитектуры или каких-то конкретных решений - кратчайший путь к срачу и бессмысленному холивару.

Особенно когда спустя пару лет хочешь использовать это в ещё каком-то проекте, и уже в упор не понимаешь, как оно устроено и работает.

Инит никого не заботит, его один раз запилили и забыли

Ещё как заботит. Неправильно написанный инит, например, может приводить к нестабильной работе в определённых условиях, которых на столе у автора инита просто нет.

Например, был случай — STM32L1 глухо вис при выходе из STOP, исправлялось магией, то есть добавлением одного пустого такта после WFI(). Ну или написанием инита контроллера строго по RM, с соблюдением последовательности инициализации, корректного расчёта таймингов и проч. ;)

Не совсем корректное сравнение, дисплейчики - это совсем иной вопрос, поскольку там действительно есть возможность отправить определенный инит и пользоваться дисплеем дальше. Каких-то спорных моментов при соблюдении максимальной частоты шины, таймингов и правильной толщине/длине проводников обычно и не возникает, вендор драйвера дисплея уже всё давно отладил.

Чипсетная периферия - это совсем другой вопрос и вот здесь действительно могут возникать вопросы с временем реакции в тактах и т.д. Я уже пояснил Сергею, что юзать захардкоженные иниты в виде "чёрных ящиков" применимо для некоторых устройств, но неприменимо для всей остальной логики программы и перифии МК в том числе.

Не совсем корректное сравнение, дисплейчики - это совсем иной вопрос, поскольку там действительно есть возможность отправить определенный инит и пользоваться дисплеем дальше. Каких-то спорных моментов при соблюдении максимальной частоты шины, таймингов и правильной толщине/длине проводников обычно и не возникает, вендор драйвера дисплея уже всё давно отладил.

Микроконтроллер ничем не отличается.

Я устал спорить. Пусть каждый останется при своем.

Тоже соглашусь, define - это всегда полезно.
Но вот в случае индикаторов, особенно если речь идет про всякую китайщину, все не так просто.
Очень часто доступная документация на индикатор не описывает, как его правильно инициализировать. Название микросхемы-контроллера упомянут - и все, крутись как хочешь.
Гугленье приводит к каким-нибудь библиотекам, с кучей команд, как в посте.
Да, можно вручную выяснить, что значит каждая команда (по документации на контроллер), но это не поможет понять, каким образом был определен порядок команд, откуда взялись значения, записываемые в регистры. Они все равно останутся "магическими".
А откуда последовательность команд взялась в найденной библиотеке? Не удивлюсь, если в конечном итоге - из NDA документации на индикатор.

Верно. Это на 7735 легко можно найти и инит, и дш. Или на ILI9341 например. А вот когда речь заходит о диковинных дисплеях на контроллерах GC - тут пиши пропало, мне лично пришлось копать исходники Linux какого-то китайского устройства.

С MIPI-матрицами вообще мрак: на них открытых даташитов практически вообще нет. Поэтому в процессе подключения DSI матриц к малинке условной, приходится как есть копипастить весь инит секвенс из существующего устройства, где этот дисплей используется.

В моём кейсе ещё всё относительно понятно. А там тупо:

char initSequence = { 0x1A, 0x3A, 0x5A, 0x3A }, где 0xFF - это сигнализатор о том, что пошла команда или данные. Вот и попытайся разобраться где и что :)

На половину GC (GalaxyCore) документация легко находится, на половину нет. Как повезёт.

В общем, предлагаю Сергею прийти к такому консенсусу: инициализация периферии подобной дисплеям может быть черным ящиком. Работа с регистрами и периферией МК, или чего-то, что хорошо документировано (MMC например) как тупо с hex мейджик-числами - говнокод.

Гугленье приводит к каким-нибудь библиотекам, с кучей команд, как в посте.

В явном виде вставляете комментарий «Some magic numbers here, see <ссылка на откуда вы это взяли>».

В утекших исходниках прошивок устройств часто так же, возможно они эту магию напрямую от производителя дисплея получают.

С большой вероятностью так и есть. Вспомнить те же контроллеры тачей, их драйверы на некоторых девайсах гуляют туда-сюда

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

Это печально

Реальный мир (предполагается массовая заводская электроника) он такой :)

Вспомни ту же дингу! Почти уверен, что инит дисплея там реализован тоже в виде набора команд без дефайнов, возможно даже скопипащенный откуда-то.

А ведь это просто один из десятков устройств на базе одной рефборды и там вероятно никто особо не заморачивался

Это хорошо, если с портянками. Хуже, если с описанием функций из SDK, у которых эти портянки хорошо спрятаны внутри.

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

Очень, очень хорошо, если этот закрытый блоб есть под ту архитектуру, под которую вам надо.

Некоторые вендоры так делают потому, что драйвер опенсорсный а документация под NDA. А может из-за лени или из вредности. И не только с экранами но и с модулями камер например. Были у меня проекты где я подобный треш менял на нормальный код, и местами заменял константы на арифметику.

Это ещё делается потому что инит дисплея отлаживается с помощью кастомной софтины с GUI, а в итоге она генерит просто массив значений, которые надо отправить в регистры. Вот она так и попадает во всякие драйверы.

В практической части статьи мы подключим дисплей по протоколу MIPI DBI к RP2040 с использованием DMA. Интересно? Тогда добро пожаловать под кат!

И где обещанный mipi? Я вижу только spi.

DBI не только аппаратный протокол, но и программный. Линк на спеку есть в статье.

На данный момент самые распространенные дисплеи - это I2C OLED.

Стоят везде, начиная от паяльников и заканчивая авто/мото.

Есть куча типоразмеров, матричные, стоят дешево, портебляют очень мало (0.49", 50% заполнение ~ 6mA).

Обычно монохромные (но цвет может быть белый/голубой/желтый), но есть и 2х цветные и цветные.

В большинстве случаев их хватает с лихвой на все, при этом они гораздо лучше смотрятся любого TFT/LCD, если речь не идет о картинках, а об выводах телеметрии, показометрах и интерфейсах.

P.S. за использование hex-кодов вместо констант есть отдельный щербатый котел...

Тоже верно. Правда SSD1306 тоже со временем выгорают, как и любой другой OLED, учитывая статичность выводимой информации.

Это заблуждение.

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

Хм, я слышал обратное.

Возможно "невыгораемость" связана с одно-двухцветностью таких дисплейчиков?

Возможно. Речь именно о монохроме.

Само выгорание там, естественно, есть, но на глаз оно не заметно.

Тогда да, согласен пожалуй там в целом особо "выгорания" и не заметишь :)

Когда-то Samsung сделали концептуально похожий на SSD1306 полу-OLED, полу-TFT дисплей, вроде даже с AoD! В X120 было как-бы две матрицы с одним контроллером (судя по схеме), вроде-бы в большинстве таких девайсов оледы всё ещё живы и не выгорели.

Там не полу-OLED, там верх сегментный, а остальное матричное, OLED и то и другое.

Точно, вспомнил, именно эта сегментная часть там как раз AoD.

Выгорание очень даже заметно. В используемом с 2016 года примерно 10...15 часов в неделю устройстве с 0,96" 2-цветным монохромным OLED уже второй дисплей поменял.

Но всё же Winstar OLED (или их графические аналоги) по живучести всё равно получше. Дома есть часы на таком индикаторе (купил попробовать этот экранчик и решил на нём что-то сделать), работают с 2021 года, и проблем с яркостью я не заметил.

А вот SSD1306, если что-то действительно по большей части статичное показывать, типа имитации семисегментника, действительно довольно быстро потеряет в яркости.

Подтверждаю, действительно отличные дисплеи! Я использую такой в генераторе сигналов и им полностью доволен

Winstar - переросток, у него область применения такая же, как у ЖК на КБ1013ВГ6 и HD44780, там и интерфейс не отличается. А SSD1306 хорош, когда нужна сверхминиатюрность.

Зависит от того, какая яркость выставлена.

P.S. за использование hex-кодов вместо констант есть отдельный щербатый котел...

Вот я тоже утверждаю, что это вселенское зло.

Я рад. Бахни минус и пройди мимо, статья же кал)

Помимо поиска по числу контактов стоит почитать профильные форумы типа такого. Очень вероятно, что такой экран кто-то до вас уже успешно запустил.

Было бы интересно почитать про подключение матрицы с интерфейсом LVDS. К МК STM32 (жирных серий типа H7) их вполне успешно подрубали.

Не шарю за дифференциалки срвсем

Самое время восполнить это упущение.

были обходные технологии, когда обычный (условно) ttl через 2XOR прогонялся и один вход дата, второй вход +, на второй паре дата и второй минус. таким образом избегают иголок.

да и проверить - дисплеи обычно терминируют эту шину определённым сопротивлением в 100 или 120 ом (не помню).

имхо - видел на сайте где парень запускал sdram модуль через avr. (https://sites.google.com/site/geekattempts/home-1/sdramthing/using-sdram)

уточнение - https://sites.google.com/site/geekattempts/home-1/drive-an-old-laptop-display-from-an-avr/lcd-concepts - https://github.com/ericwazhung/avr-lvds-lcd - там в тексте объясняет про xor (74LS86)

Что думаешь насчет MAX9371? Очевидно что через обычный ттл не хватит достаточно быстро заполнять HD-дисплей, но все же

STM32 (или другие микроконтроллеры) c модулем LTDC (LCD TFT Display Controller) на борту. Как это делается хорошо описано, например, здесь. Также есть интересное видео по использованию этого модуля для управления матрицей ноутбука.

не удалять статью! Я ещё не прочитал! )))

Кстати, SPI устройствами можно управлять с обычного советского программатора на чипе CH341, на нём есть SPI шина. Хотел про это статью написать, но это как-то не очень серьёзно получается.

А чоб нет? :) Хорошее начинание, эдакий аппаратный USB SPI-контроллер! Причём насколько я знаю, CH341 управляется через COM-порт и фактически просто пробрасывает SPI-команды на флэху.

По USB подключается. Да, это для SPI flash, но этим SPI можно управлять не только флэш чипами, но и другими SPI устройствами.

CH341

На обратной стороне есть гребёнка на 2.54мм. Похоже слева и UART есть.
Найдите ошибку в названии одного из SPI контактов.

ничо не очепятка! Мастер вход, выход - периферия))

Ну лишь бы не COPI/CIPO, хехе.

i2c тоже, читал AHT10 так

для этого есть адаптеры от ftdi, с человеческим mpsse, который почти что угодно изобразить может, не только spi.

либо китайские клоны usb blasterов, за те же пару $$ что и программаторы на СН341, и с простым как валенок протоколом.

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

Частично разобрался как управлять SPI на CH341 через libusb, через исследование чужих исходников (но там много магии), могу теперь вручную программировать команды по документации, а не через GUI приложения всякие. Например, подключил слот для SD карт (что продаётся как модуль для Ардуино), и сделал чтение служебной информации с карт.

у ftdi есть человеческая документация и нормальные драйвера, ну и куча io на чипселекты, подключал 8 штук ацп. с оберткой в луа для удобства https://github.com/pavel212/uffi/blob/master/example/ads1263.md

а протокол USB blaster давно разобран и очень простой, ну и прикидывается он тем же мостом от ftdi, так что грубо говоря нужна только единственная функция FT_Write.

А i2c дисплеи вполне можно подключать к соответствующей шине на VGA/DVI/HDMI порту. Правда, иногда нужно добавить обманку: eeprom-микросхему с EDID.

Большой дисплей так, конечно, не подключишь - скорость обновления совершенно смешная получится, но вот символьные 1602 или 2004 показывают себя неплохо при таком использовании.

Пример
Пример

@dlinyj поступил круче. Он нашел, что I2C с VGA экспортируется в Linux и через него можно рулить дисплеями!

Ну я именно в linux это и проделывал. Достаточно поставить i2c-tools и набросать несложный скрипт, чтобы начать выводить информацию на 1602 дисплейчик.

Тю, не так прочел :)

Недавно видел хак для обхода EDID, если драйвер не включает порт:

echo on > /sys/class/drm/card<номер и разъём>/status

Но всё равно надо правильное разрешение экрана где-то устанавливать.

Проголосовал за подключение всех дисплеев, хотя не уверен насчёт вариаций RGB. Если это SCART, то да, если куча барелей, то вроде что-то подобное было на БК-0010-01 и цветному монитору к нему, но не уверен. Лучше бы сделал мультивыбор...

PS: Куда относится стандартный экран на Arduino Mega 2560, который подключается в правый двойной ряд дюпонов?

8080

Если что, есть идея для следующей статьи: как сделать свой лаунчер (домашний экран) для андроид

я когда решил немного походить в дисплеи то тоже взял st7335, на него массы примеров и эти hex уже готово задефайнены. Да и сами примеры шикарные, например 3d с текстурированием и все шустро работает на старойдоброй stm32f1103

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

Они квадратные. Это даже не шутка. просто обрезанный квадрат.

Натс все ответил за меня)) иногда типа округлые дисплеи просто, без шуток, подкрашивают, затемняя нужные участки

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

Ещё TFT-матрицы со стандартным соотношением сторон пилят, чтобы получить вытянутые. Ту часть, со стороны которой шлейф, оставляют, шов заново герметизируют. Остальное, увы, задействовать никак, это «хвост ящерицы». Но контроллер совершенно не замечает исчезновения части физических пикселей.

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

Это сегментные индикаторы, их принцип схож с оными в весах, различных цифровых панелях и т.п. Ими можно рулить, включая сегменты по отдельности, но где и что находится вам придется узнавать самому. Я лично работал в основном с TFT-матрицами, так что с такими лучше обратиться к мастодонту "сегментщику" @MaFrance351

Видал такие в китайских лазерных рулетках, там COG. Подключен был по последовательной шине, вероятно, SPI.
Что за контроллер LCD там - не знаю. Но любом случае, реверс-инжиниринг протокола нужен, чтобы карту сегментов определить.
Это про боковой экран.

Также разбирал аналогичный старый дальномер (для гольфа), у него был перед окуляром простой LCD без контроллера - как в часах наручных.

Если что, на Aliexpress видел потроха таких дальномеров, которые сразу значения по UART выдают.

Там стоит либо "голая" матрица (которой можно дрыгать, например, при помощи МК STM 8 или 32 серии L), либо дисплейный модуль на контроллере NEC или Holtek.

у таких сегментных ЖК индикаторов довольно неприятное управление с кучей уровней,

и если нет возможности перехватить данные до контроллера (а они бывают встроенными в МК) то перехватывать напряжения управления непосредственно сегментов довольно гиблая затея, решаемая конечно, но при очень уж большой необходимости, нынче проще камерой будет распознавать что нарисовано. Или поверх дисплея печатную плату наложить повторяющую дисплей smd фотодиодами в нужных местах и читать уже их.

LVDS/eDP — Протоколы, используемые в матрицах ноутбуков, телевизоров и иногда планшетов. На физическом уровне близки к DSI, на программном — если честно, не знаю, но наслышан о некой стандартизации и высоком уровне совместимости.

Это обычный RGB, который через 7-битный сдвиговой регистр со встроенным умножением тактовой частоты на 7 превращён в 4...5 низковольтных дифпар. С помощью тупого сериалайзера легко делается из RGB, а через десериалайзер из него вытягивается RGB. Сделано для минимизации числа проводов и повышения частоты и разрешения дисплея - потому что для дифпар гораздо проще повысить частоту сигнала, чем для TTL.

Вот как? Хм, а привязка к EDID тогда зачем?

Спасибо за статью, в ней хорошие ответы на вопрос "у меня есть дисплей, как бы его подключить?". В хобби проектах использую ESP32 и возникает обратная проблема - есть микроконтроллер, какой дисплей выбрать чтоб прощё всего было с ним работать? Что посоветуете размером 2-3 дюйма, touch не нужен. Желательно с breakout пинами, потому как код я писать ещё умею, а вот паять - не особо. Например, какой дисплей у вас на КДПВ?

какой дисплей выбрать чтоб прощё всего было с ним работать

Если разрешение небольшое или не нужно сверхбыстрое обновление, то самое простое - на I2C-шине. Работать с I2C проще всех, т.к. он аппаратно есть практически у каждого контроллера, да и подключается по двум линиям.

Зависит от ваших нужд. Но если упомянули 2-3 дюйма, то только TFT панели. См. на алике SPI-дисплеи с 2.5" диагональю и смотрите используемый контроллер (подойдет любой)!

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.