
Во второй части поста про подключение дисплея от Nokia 1100 была приведена небольшая библиотека по работе с этим экраном в текстовом режиме. После того, как я опубликовал пост, возникла небольшая переписка с пользователем под ником -Валера-. Он просил помочь реализовать графический вывод на экран от Nokia1100. После некоторого размышления над этим, я приступил к написанию второй версии библиотеки для работы с дисплеем Nokia 1100 в графическом режиме. И вот результат моей работы.
Первая версия библиотеки работала только в текстовом режиме. Вторая версия библиотеки по функционалу частично повторяет библиотеку версии 1, но она имеет и кардинальное отличие. В этой версии библиотеки используется видеобуфер в оперативной памяти. Без этого буфера реализовать работу с графикой не представляется возможным, так как дисплей от Nokia 1100 позволяет только записывать данные в память контроллера экрана PCF8814, считать данные из него невозможно, хотя контроллер PCF8814 это и позволяет. Чем руководствовались разработчики этого экрана непонятно, какие задачи стояли неизвестно, но что имеем, то имеем.
Видеобуфер нам нужен для того, что бы узнать, что у нас содержится в определенной ячейке памяти и применить к этому содержимому соответствующую битовую операцию. После чего обновить значение в видеобуфере и вывести результат на экран.
Буфер организован как массив размерностью 96×8 значений unsigned char. То есть массив соответствует организации видеопамяти в контроллере экрана PCF8814 — 8 банков по 96 байт (столбец из 8 пикселей) в каждом. Т.е. по горизонтали отсчет идет в пикселях, а по вертикали в блоках по 8 пикселей.
Алгоритм работы с буфером по выводу графики такой. По логическим координатам в пикселях вычисляем соответствующий физический адрес ячейки (функция nlcd_GotoXY_pix), содержащей необходимый пиксель. Берем данные из буфера, производим соответствующую битовую операцию над полученным значением. Затем записываем результат обратно в видеобуфер. Переходим к соответствующей ячейке в видеопамяти экрана и записываем полученный результат туда, для отображения результата на экране.
Как все работает, можно посмотреть в самой библиотеке. Код я постарался максимально прокомментировать. Затруднений в понимании возникнуть недолжно. Но если будут вопросы, пишите в комменты, попробую помочь.
Для демонстрации работы с библиотекой я написал небольшой тестовый проект. Быдлокод, но для демонстрации библиотеки пойдет. Все линейно и крутится в бесконечном цикле. Вот код:
#include <avr/io.h> #include <util/delay.h> #include <avr/pgmspace.h> #include "nokia1100_lcd_lib.h" // Подключаем драйвер LCD-контроллера NOKIA1100 char Text[] PROGMEM = "GRAPH DEMO INIT"; int main(void) { nlcd_Init(); _delay_ms(100); while(1) { nlcd_GotoXY(1,4); nlcd_PrintF(Text); // Выводим строку из программной памяти _delay_ms(4000); nlcd_GotoXY(0,0); nlcd_PrintF(PSTR(" GRAPH MODE DEMO")); // Другой способ задания строк в программной памяти nlcd_PrintF(PSTR("----------------")); nlcd_PrintF(PSTR(" DigitalChip.ru ")); nlcd_PrintF(PSTR(" present ")); nlcd_PrintF(PSTR(" NOKIA 1100 LCD ")); nlcd_PrintF(PSTR(" demonstration ")); nlcd_PrintF(PSTR("----------------")); _delay_ms(8000); // nlcd_GotoXY(2,7); nlcd_PrintF(PSTR("Clear screen")); _delay_ms(4000); nlcd_Clear(); // nlcd_GotoXY(1,7); nlcd_PrintF(PSTR("Pixel function")); for (unsigned char i = 0; i<96; i++) { for (unsigned char j = 0; j<57; j++) { nlcd_Pixel(i,j,PIXEL_ON); j++; } i++; } _delay_ms(4000); // nlcd_Clear(); nlcd_GotoXY(0,7); nlcd_PrintF(PSTR("Line function ")); nlcd_Line (3,4,90,41, PIXEL_ON); nlcd_Line (95,0,30,55, PIXEL_ON); nlcd_Line (20,20,70,60, PIXEL_ON); _delay_ms(4000); // nlcd_Clear(); nlcd_GotoXY(0,7); nlcd_PrintF(PSTR("Circle function ")); nlcd_Circle(50,30,20, FILL_OFF, PIXEL_ON); _delay_ms(4000); // nlcd_GotoXY(0,7); nlcd_PrintF(PSTR("Fill circle ")); nlcd_Circle(40,25,15, FILL_ON, PIXEL_ON); _delay_ms(4000); // nlcd_GotoXY(0,7); nlcd_PrintF(PSTR("Fill rectangle ")); nlcd_Rect (10,10,55,38,FILL_ON, PIXEL_ON); _delay_ms(4000); // nlcd_GotoXY(0,7); nlcd_PrintF(PSTR("Rectangle invers")); nlcd_Rect (20,20,45,34,FILL_OFF, PIXEL_INV); _delay_ms(4000); // nlcd_GotoXY(0,7); nlcd_PrintF(PSTR("Pixel inversion ")); for (unsigned char i = 0; i<96; i++) { for (unsigned char j = 0; j<57; j++) { nlcd_Pixel(i,j,PIXEL_INV); j++; } i++; i++; } _delay_ms(4000); // nlcd_Clear(); nlcd_PrintF(PSTR(" GRAPH MODE DEMO")); nlcd_PrintF(PSTR("----------------")); nlcd_PrintF(PSTR(" End of demo ")); nlcd_PrintF(PSTR(" ")); nlcd_PrintF(PSTR(" see more on ")); nlcd_PrintF(PSTR(" digitalchip.ru ")); nlcd_PrintF(PSTR("----------------")); _delay_ms(8000); nlcd_Clear(); } }
Ну и небольшое видео по работе этой программки:

Ну вот, собственно, и все. Какую версию библиотеки использовать — решать вам. Если вы работаете только с текстом (меню там всякие, сообщения и т.д.), то целесообразно применять версию 1. Она занимает меньше места, компактная и не использует ОЗУ для хранения буферов. Самое то для ограниченных в ресурсах микроконтроллеров.
Ну а если в вашем проекте используется графика, то тут только вторая версия. Но она более требовательна к ресурсам. И программной памяти больше занимает, и в оперативной памяти нехилый такой видеобуфер хранит.
За сим откланиваюсь. Велком в комментарии.
NOKIA1100_3.c — демонстрационный проект
Файлы библиотеки:
nokia1100_lcd_lib.h
nokia1100_lcd_lib.c
nokia1100_lcd_font.h
nlcd11100_graph_2.1.zip — библиотеке в zip-архиве
Прошивка демо-проекта — откомпилированный проект
VSM-модели экранов Nokia для Proteus
Вливайтесь в обсуждение
  27 комментариев
Евгений
11 лет назадФайлов таких нету. Их нельзя скачать. Поправьте пожалуйста ссылки на них.
nokia1100_lcd_fnt.h
nlcd11100_graph_2.0.zip — библиотеке в zip-архиве
Chiper
11 лет назадИзвините, просто это старая ссылка. Библиотека обновлена, выложены новые файлы, а ссылки на эти файлы отвалились… 🙁
Поправил.
Но лучше качать здесь: http://digitalchip.ru/opisanie-funktsiy-graficheskoy-biblioteki-dlya-lcd-ekrana-ot-nokia-1100. Выкладываться новые версии будут туда.
Chiper
11 лет назадА еще тут посмотрите: http://digitalchip.ru/obnovlenie-biblioteki-vyivoda-dlya-displeev-nokia
Андрей
9 лет назадА можно ли этой графической библиотекой работать с lcd nokia 1110 без изменений или придется переписывать какие-то функции?
Chiper
9 лет назадМожно. Ничего переписывать не нужно. Просто нужно немного настроить под экран — в начале заголовочного файла библиотеки поправить define (размер экрана). И все.
Андрей
9 лет назадэто хорошо) правда вы говорили, что эти экраны медленные, зато они у нас в магазине стоят 85р., а 1100 стоит 200р.
Chiper
9 лет назадПоиграйтесь параметром #define NLCD_MIN_DELAY
Может у вас заработает при 0. Тогда дисплей по скорости нормальный будет. Все мои экраны это позволяли — работать при нулевой задержке — и были довольно шустрыми. Кроме 1100. Там минимальная задержка 34. А это медленно.
Андрей
9 лет назадспасибо, за совет. попробую.
Андрей
9 лет назадКомпелирую в Arduini IDE. Выдаёт много ошибок наподобии: test2.ino: In function ‘int main()’:
test2:18: error: invalid conversion from ‘char*’ to ‘unsigned char*’
Chiper
9 лет назадНу так замените везде char* на unsigned char*. Это не принципиально.
Андрей
9 лет назадХм, а скажите, чем ему не нравится оператор for, в каждой функции где он есть for(unsigned int i=0;i<864;i++) nlcd_SendByte(DATA_LCD_MODE,0x00); ?
вот такие ошибки: …\nokia1100_lcd_lib.c:88: error: ‘for’ loop initial declaration used outside C99 mode
Chiper
9 лет назадВ ANSI C нельзя объявлять переменные внутри цикла for/while
правильно будет примерно так:
unsigned int i;
for(i = 1; i < 864; i++) {
nlcd_SendByte(DATA_LCD_MODE,0×00);
}
Андрей
9 лет назадЕсли использовать шрифт 10х16, как правельно его вывести чтоб нижняя часть была не за верхней а под ней? Спасибо.
Андрей
9 лет назадВсё, со шрифтом разобрался. Русские не печатает ((( Для вывода русского что то ещё надо делать?
Chiper
9 лет назадПросто включить его, раскомментировав define.
rastamanoff
9 лет назадЗдравствуйте!
Юзаю Вашу библиотеку,с LCD NOKIA 1100.Дисплей взят от ненужного сотового.
Запустил демо проекты — текст и графика.Работает,но вот незадача : первая строчка изображения или текста начинает выводится на экран не с верху (nlcd_GotoXY(0,0);),а снизу.Тоесть первая строчка внизу ,вторая вверху экрана и тд.
Разрешение дисплея в пикселях выставил :
#define NLCD_X_RES 96 // разрешение по горизонтали
#define NLCD_Y_RES 65 // разрешение по вертикали
В чем может быть проблема?
Chiper
9 лет назадСтранно, не встречался с таким случаем. Может в вашем дисплее другой контроллер стоит, не PCF8814?
rastamanoff
9 лет назадЯ тоже в непонимаю в чем дело.Дисплей «выковырян» с мобилки,на внутреней крышке надпись — Nokia Corporation,Type:RH-18,Model:1100.
Вот что-бы вывести показания с DS1307,и получить вот такую картинку-http://radiomanoff.at.ua/lcd1100/IMG_20140502_192507_01-001.jpg
в коде пишу так
sprintf(array, «%02d:%02d:%02d», hour, minute, second );
sprintf(array_2, » %02d», date);
sprintf(array_4, «20%02d год», year);
nlcd_GotoXY(1,2);//получается верхняя строчка
nlcd_PrintWide(array);//выодит часы,минуты,секунды
nlcd_GotoXY(3,4);
//функция вывода дня недели
if(week == 1) nlcd_Print(«понедельник»);
else if (week == 2) nlcd_Print(«вторник»);
else if (week == 3) nlcd_Print(«среда»);
else if (week == 4) nlcd_Print(«четверг»);
else if (week == 5) nlcd_Print(«пятница»);
else if (week == 6) nlcd_Print(«субота»);
else nlcd_Print(«воскресенье»);
nlcd_GotoXY(0,6);
nlcd_PrintWide(array_2);//выводит день месяца
if(month == 1) nlcd_Print(» января»);
else if (month == 2) nlcd_Print(» февраля»);
else if (month == 3) nlcd_Print(» марта»);
else if (month == 4) nlcd_Print(» апреля»);
else if (month == 5) nlcd_Print(» мая»);
else if (month == 6) nlcd_Print(» июня»);
else if (month == 7) nlcd_Print(» июля»);
else if (month == 8) nlcd_Print(» августа»);
else if (month == 9) nlcd_Print(» сентября»);
else if (month == 10) nlcd_Print(» октября»);
else if (month == 11) nlcd_Print(» ноября»);
else nlcd_Print(» декабря»);
nlcd_GotoXY(0,0);
nlcd_PrintWide(array_4);//выводит год
rastamanoff
7 лет назадЗдравствуйте!
Юзаю Вашу библиотеку,с LCD NOKIA 1100.Дисплей взят от ненужного сотового.
Запустил демо проекты — текст и графика.Работает,но вот незадача : первая строчка изображения или текста начинает выводится на экран не с верху (nlcd_GotoXY(0,0);),а снизу.Тоесть первая строчка внизу ,вторая вверху экрана и тд.
Проблема решена,достаточно при инициализации строку
lcd1100_write(lcd1100_CMD,0xac); //Выставить начальный ряд (R0) дисплея
поменять на
lcd1100_write(lcd1100_CMD,0xa8); //Для оригинала Nokia1100
Все выплыло с мануала на pcf8814 — таблица 18(значения С2,С1,С0 — 000)
А дисплей заводской,выковырян с рабочей мобилки
rastamanoff
9 лет назадСпасибо большое за библиотеку.
Вот сделал небольшой отчет о проделаной работе — http://radiomanoff.at.ua/index/lcd_nokia1100/0-55#
Chiper
9 лет назадПрикольно. Но глюк непонятный. У меня такого не было.
Shura
9 лет назадЗдравствуйте!
Большое Спасибо за библиотеку!
Возник вопрос почему размер видеобуфера выбран так странно
static unsigned char nlcd_memory[NLCD_X_RES-1][(NLCD_Y_RES/8)+1];
У меня при этом программа виснет.
если же поставить
static unsigned char nlcd_memory[NLCD_X_RES][(NLCD_Y_RES/8)];
то все работает нормально.
Shura
9 лет назадТочнее (NLCD_Y_RES/8)+1 — понятно почему, а вот
NLCD_X_RES-1 — не понятно?
Chiper
9 лет назадПотому что отсчет индекса в буфере идет от нуля, а размер задается от 1. Вобщем-то то стандартный прием…
Shura
9 лет назадsizeof( nlcd_memory[NLCD_X_RES-1][(NLCD_Y_RES/8)+1] )=855
sizeof( nlcd_memory[NLCD_X_RES][(NLCD_Y_RES/8)+1] )=864
в комментариях написано: 9 банков по 96 байт, а выделяется 855 байт, поэтому после выполнения процедуры nlcd_Clear() в которой есть строка
for(i=0;i<864;i++) nlcd_SendByte(DATA_LCD_MODE,0x00);
происходит повреждение данных, которые располагаются в памяти непосредственно
за nlcd_memory.
Серга
7 лет назадс экраном 1202 будет работать ?
если нет то нет ли библиотек для 1202 ?
самыё дешёвый и простой в пайке дисплей всё-таки
ujin
7 лет назадбудет….библиотека может использоваться с разными лсд в том числе и 1202