Например TDA7294

РадиоКот > Статьи

Драйвер для LCD от Nokia 3310

Теги: nokia3310.

Автор - Aheir, aheir@radiokot.ru
Опубликовано 16.02.2010.


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

Общий вид

Область отображения 84*48 точек (что позволяет разместить 6 строк текста по 14 символов 5x7 в каждой), питание 2,7..3,3 В, интерфейс SPI с пропускной способностью до 4 Mbit/s. И все бы хорошо, но дело в том что существуют две разновидности этого дисплея. Внешние отличия несущественны, но они есть:

Отличия

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

Глюк

Как выяснилось, в этих дисплеях стоят разные контроллеры: в оригинальном — PCD8544 (документация на который доступна в Сети), а вот что установлено в китайском — доподлинно неизвестно. Поиск по Интернету и собственные наблюдения позволили сделать ряд заключений относительно контроллера неоригинального дисплея, тем более что как-то он все же работает, а значит более-менее корректно инициализируется и принимает данные.
Ниже представлена таблица команд для PCD8544 с известными на сегодняшний день уточнениями для неоригинального контроллера (выделено красным):

Таблица команд

Ничего экзотического в командах контроллера не наблюдается, стандартный набор для графического экрана. Разве что настройки напряжения Vop, позволяющие программно менять контрастность. Оригинальный дисплей на дополнительные команды неоригинала просто не реагирует, так что можно их использовать вне зависимости от контроллера дисплея.
Сдвиг экрана неоригинального контроллера вверх (и цикличность прокрутки экрана) говорит о наличии в его области памяти дополнительных строк изображения, а анализ результата при выводе на экран картинки позволил установить, что «неоригинал» еще и шире на 18 точек. Я предположил, что разрешение экрана составляет 102х64 точки, что впоследствии подтвердилось экспериментально. Следовательно, область экрана 84x48 точек является некоторой частью памяти на 102х64 точек неоригинального контроллера.
Существующие решения по обеспечению совместимости экранов основаны на осуществлении сдвига экрана: либо на полстроки, остатки которой видны на экране (тогда первая строка не отображается и область экрана начинается со второй), либо на «полный оборот» (тогда первая строка отображается на точку ниже, чем должна быть). Однако мои эксперименты показали их пригодность почему-то только для режима отображения текста, при попытке вывести картинку изображение рассыпалось (рискну предположить, что это происходит потому, что при выводе текста каждая строка адресуется перед выводом (т.е. сказали куда вывести — вывели строку, переставили указатель на начало следующей строки — вывели вторую и т.д.), а при выводе картинки данные пишутся в память сплошным потоком, что приводит к рассыпанию из-за большей программной ширины дисплея).
Отсюда получаем два способа вывода нормальной картинки на неоригинальный дисплей: отображать экранный буфер на часть памяти контроллера, программно отслеживая смещение, либо выводить картинку с адресацией каждой строки. Я реализовал первый (как-то оно проще для меня оказалось), хотя у него есть один недостаток: в драйвере требуется однозначно указывать, с каким дисплеем предполагается работа, тогда как вторым способом можно в теории сделать более универсальный драйвер. Видимо, как раз по второму алгоритму и работает телефон, если уж к нему подходят любые экраны. Но лично меня это не расстраивает, потому как сделать две версии прошивки совсем несложно, да и вообще, оригинальных дисплеев у меня всего один (и вряд ли будут еще), а вот неоригинала с десяток имеется... Ладно, поехали уже к практике, теории пока хватит...
Для начала — изготовили простейшую макетную плату. Собственно, процессор Атмега8, пара конденсаторов, разъем программирования и сам экран. Все. Подключение простое: вывод SCK экрана на SCK контроллера; SDIN — на MOSI; D/C, SCE и RES — на любые пины порта, к Vout — конденсатор на землю, VDD — на питание, GND — к земле. Собственно, что-то вроде этого:

Схема

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

Соединение

На плате разведены элементы термодатчика и подсветки индикатора, но ничего из этого не установлено. Питание — 3,3В, я лично запитывал плату непосредственно от USB-программатора.
Индикатор от телефона мне достался без рамки, но к нему можно просто припаяться, а вот с китайским индикатором такой номер не пройдет ввиду отсутствия металлизации, поэтому паяемся к металлическому коннектору, который прижимается к экрану рамкой и пластиком:

Коннекторы

Теперь можно и попрограммировать маленько. МК настроен на тактирование от внутреннего генератора на 4МГц, фьюзы:

Фьюзы

За основу были взяты исходники с уже упоминавшейся странички и доработаны для совместимости с CodeVision AVR и обеспечения требуемого функционала. Вот перечень функций для работы с LCD:


void LcdSend (unsigned char data, unsigned char cmd); //запись данных в LCD
void LcdUpdate (void); //копирование буфера в RAM дисплея
void LcdClear (void); //очистка дисплея
void LcdInit (void); //настройка SPI и дисплея
void LcdContrast (unsigned char contrast); //установка контраста
void LcdMode (unsigned char mode); //режимы дисплея: 0 - blank, 1 - all on, 2 - normal, 3 - inverse
void LcdPwrMode (void); //инвертирует состояние вкл/выкл дисплея
void LcdImage (flash unsigned char *imageData); //вывод изображения
void LcdPixel (unsigned char x, unsigned char y, unsigned char mode); //управление пикселем с координатами x,y
void LcdLine (int x1, int y1, int x2, int y2, unsigned char mode); //рисование линии
void LcdCircle(char x, char y, char radius, unsigned char mode); //рисуем круг с координатами центра и радиусом
void LcdBar(int x1, int y1, int x2, int y2, unsigned char persent); //рисуем батарейку и заполняем ее на %
void LcdGotoXYFont (unsigned char x, unsigned char y); //установить курсор в положение x,y
void clean_lcd_buf (void); //очистка текстового буфера
void LcdChr (int ch); // печатает символ на текущем месте
void LcdString (unsigned char x, unsigned char y); //печатает строку
void LcdChrBold (int ch); //печатает символ на текущем месте, большой и жирный)
void LcdStringBold (unsigned char x, unsigned char y); //печатает большую и жирную строку
void LcdChrBig (int ch); //печатает символ на текущем месте, большой
void LcdStringBig (unsigned char x, unsigned char y); //печатает большую строку

Функционал понятен из названий и комментариев. Результатом работы этих функций становятся вот такие изображения на дисплее:

В работе

Математически реализованы шрифты удвоенной высоты и удвоенного размера, имеются широкие возможности для построения сложных объектов на основе графических примитивов (линии и окружности отрисовываются по алгоритмам Брезенхема). При помощи директив условной компиляции реализована сборка драйвера для того или иного дисплея, выбор осуществляется при помощи строки #define china 1: если дефайн активен - работаем по алгоритмам "китайского" дисплея, иначе — оригинального. По ссылке можно посмотреть видео работы экрана

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

UPDATE от 23.02.2010.

Предлагаю Вашему вниманию вторую версию драйвера.
По результатам эксплуатации исправлены всячеcкие косячки, глючки и прочие жучки)
Основное нововведение - добавлен программный SPI, так что теперь можно вешать дисплей практически на любые порты микроконтроллера (применительно к AVR не реализовывал за ненадобностью поддержку портов от F и далее). Кроме того, добавлено пару функций, наиболее полезной из которых является

void LcdStringInv (unsigned char x, unsigned char y);

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

Файлы:
макетная плата в SL5
драйвер экрана, demo-прошивки и пример программы
драйвер версии 2

Все вопросы, как всегда, в Форум.


ID: 33

Как вам эта статья?

 Нравится
 Так себе
 Не нравится

Заработало ли это устройство у вас?

 Заработало сразу
 Заработало после плясок с бубном
 Не заработало совсем

70
15 4 3
Подробно