Подключение lcd от телефона Nokia3310

12/10/2009 - 11:06
   В интернете довольно много микроконтроллерных проектов с применением LCD от телефона Nokia3310. Причина большой популярности дисплея в его дешевизне и простоте использования. Вдохновившись удачным опытом работы с мотороловским экраном, я решил взяться за lcd от Nokia. Вот что из этого получилось.

Технические характеристики LCD Nokia3310:

-    Напряжение питания 2,7 – 3,3 В
-    Встроенный контроллер Philips PCD8544
-    Интерфейс SPI
-    Размер дисплея 38х35 мм
-    Размер активной области 30х22 мм
-    Разрешение 84х48 пикселей
-    Диапазон рабочих температур –27…+70 0С

Схема подключения к микроконтроллеру

Схема подключения lcd от Nokia3310 к микроконтроллеру
   Питание схемы 3,3 В. Если понадобится подключать экран к схеме с 5 вольтовым питанием, нужно будет делать схему согласования уровней. Скорее всего, она будет выглядеть так. Сам не проверял, поправьте, если ошибаюсь.
Схема согласования уровней lcd от nokia3310 для 5-ти вольтового питания

Распиновка LCD Nokia3310

Назначение выводов lcd от nokia3310

Программная часть

   Повозившись пару дней с этим дисплейчиком, я накатал аж целых три проекта. На этот раз не стал изобретать велосипед, а взял готовую библиотеку для микроконтроллера MSP430 и переделал ее под AVR.
    Библиотека оказалась очень тяжеловесной, и IAR не захотел ее компилировать для  ATMega8535. В программе был организован видео-буфер на 504 байта и компилятор ругался на нехватку ОЗУ. Зачем нужен видео-буфер? Дело в том, что контроллер этого дисплея позволяет записывать данные в свою память, но не позволяет их считывать. Это сильно ограничивает возможности по работе с дисплеем - нельзя, например, наложить одно изображение на другое. Один из путей решения проблемы - буфер в ОЗУ микроконтроллера, хранящий все, что в данный момент отображается на экране. Запись и считывание данных производятся сначала в буфер, и только потом весь буфер выводится на дисплей.
   Поскольку ATMega8535 пожалуй самый ходовой микроконтроллер в моих поделках, мне захотелось переделать библиотеку под него. Поэтому я удалил видео-буфер и переписал все функции, где он использовался. Добавил англо-русский шрифт, и получился отличный знакогенератор без всяких наворотов.    

Исходник библиотеки.
Тестовый проект.
Описание на контроллер дисплея.

Собственно для работы с дисплеем достаточно трех функций

void LCDInit(void)
   Конфигурирует выводы PORTB в режим выхода, настраивает модуль SPI, подает сигнал сброса контроллеру дисплея и последовательность команд для его настройки.

void LCDClear(void)
  Полностью очищает дисплей.

void LCDStr(unsigned char x, unsigned char row, unsigned char *dataPtr )
  Выводит текстовую строку на дисплей. X – знакоместо. Принимает значения от 0 до 13. Если строка не помещается на дисплее, оставшаяся часть просто не выводится. Row –  номер строки. Может принимать значения от 0 до 5. Верхняя строка считается нулевой.

Пример:
LCDStr(0, 2, “lcd Nokia3310” );

Пример вывода текста на lcd Nokia3310

Comments   

# skiff 2009-10-17 04:52
Доброго время суток!A про соединение индикатора WH1602D-YYH-CTK например.pleas :-)
# Guest 2009-11-22 15:11
Quote:
A про соединение индикатора WH1602D-YYH-CTK например
А зачем специально разжевывать? Во всех популярных компилеров Си есть встроенные функции для вывода
# Guest 2009-12-09 17:13
Вопрос: а можно вывести символ в произвольное место? Т.е. измерять координаты не в знакоместах, а в пикселях? По иксу координату я задать смог, а вот по Y получается только кратное восьми...
# Pashgan 2009-12-09 19:12
В этом проекте не получиться задать произвольное значение Y. Y может быть от 0 до 5. Так организована память контроллера дисплея. Если бы контроллер позволял читать свою память проблем бы не было, а так нужно организовывать буфер в ОЗУ микроконтроллер а, записывать и считывать информацию туда, и только потом целиком выводить на экран. В разделе "библиотеки для IARa" есть библиотека с буфером. У меня еще тестовый проект с ней валяется, могу выложить.
# Guest 2009-12-09 21:04
Итого, как я понимаю, в любом случае выводить придётся "посимвольно" - по 8 бит, причем начиная с ординаты, кратной восьми. Так?

в самой 3310 как я вижу весь текст имеет высоту 8 пикселей, но выводится он с произвольных точек (ордината не обязательно кратна восьми). Интересно, как сделано? надо даташит PCF8814 покурить, может там есть чего.
# Pashgan 2009-12-09 21:49
нет. с буфером можно выводить текст в любое место.
# Guest 2009-12-12 16:28
Я так понимаю что библиотека с буфером это как будто двойная буферизация в видеокарте - рисуем в нашем буфере, потом делаем апдейт аля SwapBuffers(). Так? А данные разые быстро передадутся? (у меня дисплей от 1100, там не SPI а чё-то другое, но принцип вроде похож)

и еще вопрос - сейчас Data Write именно _присваивает_ текущему байту заданное значение. А нет ли способов вместо присваивания делать, скажем, операции "И", "ИЛИ"? типа операции |= и &=

Всё же смотрю на мобилу, катаюсь по менюшкам и не могу понять - как же происходит вывод текста на экран в точку с координатами, некратными восьми...
# Guest 2009-12-12 23:03
файлы к статьям IAR - проект lcd_nokia3310_g raph.rar. Открываем файл driver_nokia331 0 функция void SetMode(unsigne d char mode_pixel). Она устанавливает режим вывода. Их три
И, ИЛИ, Исключающее ИЛИ
# Guest 2009-12-12 23:14
ALPINE, чтобы понять как выводится точка в произвольную область экрана - разберись с функцией void LCDPixel (unsigned char x, unsigned char y). Она в этом же проекте, в сишном файле.
# Guest 2009-12-13 13:10
О, отлично. Спасибо, сейчас буду разбираться. А то я мельком пробежал - решил, что всё выводится столбиками по 8 бит и никак иначе. Видимо, невнимательно смотрел. Перечитываю...
# Guest 2009-12-13 13:19
А, я рановато обрадовался. Режимы вывода "И", "ИЛИ", "искл.ИЛИ" только для этой библиотеки. А я думал это вшито в драйвер дисплея.

Короче говоря, если возиться с дисплеем на низком уровне (ну или писать библиотеку самому с нуля) - то рисовать на нём можно ТОЛЬКО столбиками по 8 бит, затирая то что уже нарисовано под этим столбиком. Других способов рисования драйвер дисплея не предусматривает . Я правильно понял?
# Pashgan 2009-12-14 08:37
да, столбиками по 8 бит, затирая старые данные.
# Guest 2010-04-03 15:21
Решил тоже поиграться с таким дисплеем. Но видимо мне какой-то косячный попался.

Во-первых, разрешение у него 37х84 :o
Во-вторых, столбики не по восемь точек идут, а вот так: 1 столбик на 4 точки, 5 столбов по 6 точек и 1 по 3. И когда я посылаю первую строку байтов, точки выводятся только под действием последних 4-х бит.

Это чё за хрень такая? Так и должно быть или я чё-то не так настроил? :-?
# Pashgan 2010-04-03 16:37
Даже не знаю. Дисплей точно от Nokia3310? Может там контроллер другой - не PCD8544?
# Guest 2010-04-03 19:40
Не, кажись общитался :oops: . Высота всё-таки 48 пикселей. Проблема вот в чём. Посылаю допустим в память 0b00001111 84 раза, при этом с начала экрана выводится строка шириной 1 пикс (а должно по идее 4 пикселя и четыре пробела). Следующие строки идут нормально (по восемь пикселей). Ну и в последней строке остаётся только 3 пикселя. Короче говоря, получился сдвиг на 3 пикселя вверх, о причинах которого мне и хотелось бы узнать.

>Дисплей точно от Nokia3310?
Скорее всего. Брал тут http://shop.siriust.ru/product_info.php/products_id/382
# Pashgan 2010-04-03 20:07
Скинь проект мне на почту, я его гляну. Может там какой косяк.
microsmaster собака rambler.ru
# Guest 2010-04-03 20:38
Отправил
# vvf7723 2010-08-11 12:25
У кого есть информация о дисплее от Nokia 1110?
Какой там чип, как подключаться (хочется по i2c)
# Guest 2010-08-12 16:14
Вот ссылка на проект для PIC контроллера. Думаю его можно переделать для AVR
http://www.embedds.com/nokia-1100-lcd-and-pic-interface-the-best-combination-that-you-can-think-about/
# vvf7723 2010-08-13 05:12
Большое спасибо за ссылку - пригодится.

Но тема все таки все еще актуальна (по ссылке проект с экраном от Nokia 1100, он даже выглядит немного иначе).
# Guest 2010-08-13 15:43
Точно. Обознался..
# Guest 2010-08-21 12:53
Pashgan, расскажи как ты подключился к стекляшке? А то я хочу из пластикового основания дисплей вытащить...
# Pashgan 2010-08-21 16:38
Так я не к стекляшке подключился. На моем дисплее были приклеены металлические контакты.
# Guest 2010-08-21 18:11
Т.е. он был изначально такой как изображён на фото?
# Pashgan 2010-08-21 20:14
да
# Guest 2010-08-21 20:28
Понял. Спасибо :-) . Придётся что-нибудь придумывать.
# Ali 2010-11-09 10:45
на 16герцовом камне, что то не завелось. Согласование сделал по 2 схемке. что то не пашет куда копать где проверять? Камень работает сделал мигалку светодиода, мигает. а вот на экран, что то не бежит ничего.
# Ali 2010-11-10 01:28
Все просто контакта не было.
# Viaceskav(C) 2011-03-07 18:45
а как выводить дополнительные фонты?

вопрос снимается, я плохо код посмотрел :-)
# Pashgan 2011-03-15 19:42
Использование других фонтов здесь не реализовано
# Viaceskav(C) 2011-03-15 21:47
да я уже немного переделал вывод
добавил дополнительный буферок (само собой 504 байта)...
теперь по извращенному можно выводить любые загруженные спрайты, вывод пикселей...
любая графика выводится сначала в буфер, затем буфер побайтово копируется сразу весь на экран.
# JoJo 2011-03-19 20:30
Проект с буфером есть в разделе "файлы"
# Moskvichh 2011-05-19 21:01
PashGan Подскажи, как изменить контраст?
Пишу даже
LCDInit();
LCDContrast(0x0 0);
LCDClear();
LCDStr(0, 0, "Курсова робота");

но никаких изменений,?
# Spok 2011-05-26 02:58
Пожалуйста, объясните, где первая нога? Во всём интернете ни одной картинки и ни одного слова про это!

Вот дисплей: смотрю на него. На экран. Лично у меня он сзади чем-то закрыт: непрозрачный. Если б я мог насквозь видеть, то б эти 8 ног были сверху и рядом с правой (если продолжать смотреть на экран, а не на ноги) был б такой пластмассовый выступ.
# Spok 2011-05-27 16:22
А! Совсем забыл сказать: визуально "верх" сверху. Он на такой пластмасске в форме телефона. Динами сверху, клавиатурка снизу.
# londo 2011-06-12 15:40
А почему может происходить ругательство компилятора на SPIE SPE DORD и иже с ними биты? Я их попробоввал заменить на аналогичные цифры из inc-файла моего МК, но в результате на экран ничего не выводит :sad:
# Илья 2011-10-13 22:44
Исключительное спасибо, брат! все работает. отличная отправная точка для экспериментов. удачи в делах и намерениях.
# 14-th 2012-03-01 20:24
Доброго времени суток всем.
Если тема еще не заглохла, подскажите, кому не трудно, как осуществить все это на АТмеге 8? Скачал тестовый проект и пытаюсь в нем разобраться.
Полностью использовать порт B не получится, ибо на нем висит кварец. Хочу перекинуть на порт D. В хидере lcd_nokia3310pi n.h заменил в дефайнах DDRB и PORTB на DDRD и PORTD соответственно. Распаял к ногам МК. Чуда не произошло, ничего не заработало.
# 14-th 2012-03-01 21:04
Вернул обратно порт B, перераспаял с соблюдением распиновки (mosi, sck и т.п.). В коде поменял номера пинов на те, к которым подпаялся. По-прежнему не работает.
Но, при скидывании шлейфа программатора (в режиме RUN, не PROG) появляется горизонтальная полоска на экране.
# 14-th 2012-03-02 05:07
Не даром говорят "Утро вечера мудренее".
Подпаял другой дисплей - все заработало.
Огромное спасибо за проект!
# ВитГо 2012-10-04 02:57
я подключал как то дисплей от нокиа 1100 (на сириусте всего 50 руб стоит) - но у меня возникла проблема с контактами дисплея которые наклеены на стекло - при попытке подпаятся к ним - дисплей просто потом не работал (вернее сначала работал, потом работал если прижать контакты, а потом уже нифига не работал (ну может изредка).. извел я 3 или 4 дисплея и забросил эту идею..

может быть ктото придумал что нить дельное с подключением таких дисплеев ? чтобы и не паяться и контакт был надежный?
# ВитГо 2012-10-04 02:58
ой. подписаться на ответы забыл..
# Pashgan 2012-10-04 04:00
Можно попробовать аккуратно приклеить провода к контактам дисплея с помощью токопроводящего клея.
# ВитГо 2012-10-04 05:02
плохо себе эту процедуру представляю.. расстояние между выводами маленькое..- капли клея обязательно где нить расползутся и замкнут :-(

никто никаких колодок не делал (или может покупал где нить) для подобных дисплеев?
# Pashgan 2012-10-04 17:08
Другой вариант - сделать что-то вроде гребенки с контактами, прижать их к стеклу и приклеить эпоксидным клеем.
# Дмитрий 2012-10-25 14:32
Здравствуйте! итак, делаю проект с дисплеем от 3310, пользуюсь вашей библиотекой. Теперь возник вопрос-как удалить из font_6x8.h ненужные символы? просто если больше половины не используются, а ПЗУ едят прилично. Просто удалением-не вариант, на экране мусор.
# Pashgan 2012-10-26 18:25
Естественно не вариант, потому что код символа используется в качестве индекса массива.
Какую половину символов нужно убрать?
# ВитГо 2012-10-26 19:23
Я как то оставлял только большие буквы (дисплей мелкий, поэтому мелкие буквы совсем плохо читаются если нужно читать их издалека)
и дополнительно делал токен-печать - это когда по одному коду - печаталось целое слово из словаря.. - если много слов которые повторяются (всякие ON\OFF, SETTINGS, CHANNEL и т.д.) - то можно значительно сократить код..- у меня оптимизация достигла 50%..
коды токенов находились в области маленьких лат. и рус. букв
# Алексей 2012-11-27 04:43
Так же интересует вопрос по исключению не задействованных символов. Если не затруднит, растолкуйте пожалуйста как осуществить :).
# grender 2013-01-06 20:12
Юху! Особенный респект за шрифт Terminus. Этож вроде он?
Взял твои метода по работе с шрифтом(ну и сам шрифт) и впихнул их в свою самоделку на MSP430. Вот такой круговорот кода.
Не подскажешь где брал исходники на MSP430 с буфером?
# Pashgan 2013-01-07 22:14
Шрифт я сам у кого-то позаимствовал. А код для msp430 брал с сайта Olimex https://www.olimex.com/Products/MSP430/Starter/MSP430-169LCD/
# grender 2013-01-08 16:45
Спасибо. Я надеялся что там нормальный код обновления экрана. С выводом текста все легко, а вот с графикой сложно из-за 84 бит на строку.
# ВитГо 2013-01-08 21:32
а какая разница сколько бит в строке ?
сами процедуры не сильно отличаются..
Code:
void LCD_pixel (unsigned char x, unsigned char y, unsigned char mode) { // вывод пиксела

if ((x<128)&&(y<64)) {
unsigned char i=y>>3;
unsigned char bt=1<<(y & 0x7);
if (mode!=0) lcd_buff[128*i+x]|=bt;
else lcd_buff[128*i+x]&=(~bt);
}
}

точки я думаю понятно как рисовать..
это для экрана 128 на 64 точки, поставьте свои размеры и вперед..
правда конечно буфер экрана нужен ! без него никак при графике
а для линий смотрите в интернете алгоритм Брезенхейма - он есть для линий и для дуг..
в принципе для линий я и на СИ и на Асме писал - действительно не сложный и быстрый
вот на си
Code:
void LCD_line(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, char mode) { // процедура рисования линии
signed char dx, dy, sx, sy;
unsigned char x, y, mdx, mdy, l;

dx=x2-x1; dy=y2-y1;

if (dx>=0) { mdx=dx; sx=1; } else { mdx=x1-x2; sx=-1; }
if (dy>=0) { mdy=dy; sy=1; } else { mdy=y1-y2; sy=-1; }

x=x1; y=y1;

if (mdx>=mdy) {
l=mdx;
while (l>0) {
if (dy>0) { y=y1+mdy*(x-x1)/mdx; }
else { y=y1-mdy*(x-x1)/mdx; }
LCD_pixel(x,y,mode);
x=x+sx;
l--;
}
} else {
l=mdy;
while (l>0) {
if (dy>0) { x=x1+((mdx*(y-y1))/mdy); }
else { x=x1+((mdx*(y1-y))/mdy); }
LCD_pixel(x,y,mode);
y=y+sy;
l--;
}
}
}

текст тоже можно написать процедуру чтобы выводить с точностью до пиксела.. причем символы не рисовать по точкам, а именно выводить верхнюю\нижнюю часть...
К сожалению код сюда уже не уместился...
# ВитГо 2013-01-08 21:33
Ну и вот вывод текста с точностью до пиксела
Code:
void LCD_char(unsigned char ch, unsigned char mode) { // Вывод символа
const unsigned char *fontpointer;


if (ch<127) { // знакогенератор латиницы
fontpointer=NewFontLAT; ch=ch-32; }
else { // знакогенератор русских букв
fontpointer=NewFontRUS; ch=ch-192;}

if (mode==2) mode=lcd_blink; // если нужно отображать в режиме мерцания - то берем значение инверсии из lcd_blink

unsigned char lcd_YP=7- (lcd_Y & 0x07); // битовая позиция символа в байте
unsigned char lcd_YC=(lcd_Y & 0xF8)/8; // байтовая позиция символа на экране

for (unsigned char x=0; x<6; x++) {

unsigned char temp=pgm_read_byte(fontpointer+ch*6+x);

if (mode!=0) {
temp=~temp;
if (lcd_Y>0) LCD_pixel(lcd_X, lcd_Y-1, 1); // если печать в режиме инверсии - сверху отчертим линию
}

temp&=0x7F;

lcd_buff[lcd_YC*128+lcd_X]=lcd_buff[lcd_YC*128+lcd_X] | (temp<<(7-lcd_YP)); // печать верхней части символа

if (lcd_YP<7) lcd_buff[(lcd_YC+1)*128+lcd_X]=lcd_buff[(lcd_YC+1)*128+lcd_X] | (temp>>(lcd_YP+1)); // печать нижней части символа

lcd_X++;
if (lcd_X>126) return;
}
}

# grender 2013-01-09 11:52
О! За Брезенхейма отдельный респект!
А по поводу 84 бит, это фишка этого дисплея.
Я хотел использовать без обработки формат XBM(который фактически является массивом на Си и его можно просто инклудить), еще его особенность что если длина строки не кратна 8ми то бит добивается нулями.
А тут у экрана 84 бита на строку, а в XBM 88 бит на строку и чтобы вывести все приходится при новой строке явно указывать ее номер. Еще чудес добавляет то, что вывод 1ого байта это вывод колонки из 8ми пикселей. Я с компа привык к нормальной построчной адресации. Тут такого нет. Вот и хочется написать обертку чтобы было. И сделать свою демку с графикой. А если упрусь в возможности контроллера, то возьму покруче, но это уже MSP430-ый офтоп.
Кстати вывод я только что переделал на вертикальную адресацию и там стало все хорошо ибо теперь по длине картинки 48бит.

ПС. Знаю что немного путано(
# ВитГо 2013-01-11 03:19
ДА, после обычного компа и "обычных" дисплеев LCD с их вертикальным выводом байта вначале кажутся не очень удобными.... но поверьте это только в начале :-)))
# hawk 2013-06-12 10:26
Pashgan приветствую. Решил сделать термометр с выводом комнатной и уличной температуры с использованием данного дисплея. Купил три дисплея (китайских)-зап орол два из них :cry: Кое как подключился к одному. Заметил что в последних 3-4 строках какой то мусор.
вот мой код Code:#include <mega8.h>
#include "driver_nokia3310.h"

void main( void )
{
unsigned char* counterProg = 0;
LCDInit();
LCDClear();

while(1){
counterProg++;
LCDStr(0, 3,counterProg);
delay_ms(100);
}
}
Вот что получаю

Вопрос: откуда берется надпись "Pashgan"?
Почему вместо counterProg получаю какую то муть и как увеличить контрастность дисплея?
И можно ли убрать мусор из последних строк?
# hawk 2013-06-12 10:51
UPD 1. Перезагрузил устройство, надпись "Pashgan" пропала, но появился мусор
UPD 2.По поводу контрастности разобрался
# Дмитрий 2013-08-12 10:42
hawk то что у тебя мусор в последней строке это потому что дисплей китайский, а по поводу твоего кода объяснить не могу (потому что сам в си не силен) но подсказать как решить эту проблему могу.
Я поступил следующим образом
Функция sprintf стандартной библиотеки stdio.h
sprintf – функция для вывода форматированных данных в строку.

Code:
#include <mega8.h>
#include <stdio.h>
#include "driver_nokia3310.h" // использую lcd от siemens c55
unsigned char array[6];
unsigned char temp;


void main( void )
{
LCDInit();
LCDClear();
LCDContrast(75);
sprintf(array,"t %u",temp);


while(1)
{
LCDClear();
sprintf(array,"t %u",temp);
LCDStr(3, 6, array);
delay_ms(500);
temp++;
}
}


Ну а по поводу мусора я решил проблему повысив разрешение с 84*48 до 101*64 так кат у меня LCD от Siemens C55. В твоем случаи попробуй поставить чуть больше разширение методом тыка.
# Kodex 2013-09-28 06:52
CTK-500 вроде проглядывается? Где взял? Что там полезное есть? Где б разводку достать...
# Pashgan 2013-09-28 20:08
Ага, он самый. На работе покупали. Давно еще. Там программатор, RS232, разъемы под DIP, восемь кнопок, восемь светодиодов и все порты выведены на разъемы. И что-то еще по мелочи. Разводки не видел.
По-моему сейчас он уже не продается. Вместо него STK600.

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