Во второй части поста про подключение дисплея от 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 комментариев
Евгений
13 лет назадФайлов таких нету. Их нельзя скачать. Поправьте пожалуйста ссылки на них.
nokia1100_lcd_fnt.h
nlcd11100_graph_2.0.zip — библиотеке в zip-архиве
Chiper
13 лет назадИзвините, просто это старая ссылка. Библиотека обновлена, выложены новые файлы, а ссылки на эти файлы отвалились… 🙁
Поправил.
Но лучше качать здесь: http://digitalchip.ru/opisanie-funktsiy-graficheskoy-biblioteki-dlya-lcd-ekrana-ot-nokia-1100. Выкладываться новые версии будут туда.
Chiper
13 лет назадА еще тут посмотрите: http://digitalchip.ru/obnovlenie-biblioteki-vyivoda-dlya-displeev-nokia
Андрей
11 лет назадА можно ли этой графической библиотекой работать с lcd nokia 1110 без изменений или придется переписывать какие-то функции?
Chiper
11 лет назадМожно. Ничего переписывать не нужно. Просто нужно немного настроить под экран — в начале заголовочного файла библиотеки поправить define (размер экрана). И все.
Андрей
11 лет назадэто хорошо) правда вы говорили, что эти экраны медленные, зато они у нас в магазине стоят 85р., а 1100 стоит 200р.
Chiper
11 лет назадПоиграйтесь параметром #define NLCD_MIN_DELAY
Может у вас заработает при 0. Тогда дисплей по скорости нормальный будет. Все мои экраны это позволяли — работать при нулевой задержке — и были довольно шустрыми. Кроме 1100. Там минимальная задержка 34. А это медленно.
Андрей
11 лет назадспасибо, за совет. попробую.
Андрей
11 лет назадКомпелирую в Arduini IDE. Выдаёт много ошибок наподобии: test2.ino: In function ‘int main()’:
test2:18: error: invalid conversion from ‘char*’ to ‘unsigned char*’
Chiper
11 лет назадНу так замените везде char* на unsigned char*. Это не принципиально.
Андрей
11 лет назадХм, а скажите, чем ему не нравится оператор 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
11 лет назадВ ANSI C нельзя объявлять переменные внутри цикла for/while
правильно будет примерно так:
unsigned int i;
for(i = 1; i < 864; i++) {
nlcd_SendByte(DATA_LCD_MODE,0×00);
}
Андрей
11 лет назадЕсли использовать шрифт 10х16, как правельно его вывести чтоб нижняя часть была не за верхней а под ней? Спасибо.
Андрей
11 лет назадВсё, со шрифтом разобрался. Русские не печатает ((( Для вывода русского что то ещё надо делать?
Chiper
11 лет назадПросто включить его, раскомментировав define.
rastamanoff
11 лет назадЗдравствуйте!
Юзаю Вашу библиотеку,с LCD NOKIA 1100.Дисплей взят от ненужного сотового.
Запустил демо проекты — текст и графика.Работает,но вот незадача : первая строчка изображения или текста начинает выводится на экран не с верху (nlcd_GotoXY(0,0);),а снизу.Тоесть первая строчка внизу ,вторая вверху экрана и тд.
Разрешение дисплея в пикселях выставил :
#define NLCD_X_RES 96 // разрешение по горизонтали
#define NLCD_Y_RES 65 // разрешение по вертикали
В чем может быть проблема?
Chiper
11 лет назадСтранно, не встречался с таким случаем. Может в вашем дисплее другой контроллер стоит, не PCF8814?
rastamanoff
11 лет назадЯ тоже в непонимаю в чем дело.Дисплей «выковырян» с мобилки,на внутреней крышке надпись — 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
9 лет назадЗдравствуйте!
Юзаю Вашу библиотеку,с 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
11 лет назадСпасибо большое за библиотеку.
Вот сделал небольшой отчет о проделаной работе — http://radiomanoff.at.ua/index/lcd_nokia1100/0-55#
Chiper
11 лет назадПрикольно. Но глюк непонятный. У меня такого не было.
Shura
10 лет назадЗдравствуйте!
Большое Спасибо за библиотеку!
Возник вопрос почему размер видеобуфера выбран так странно
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
10 лет назадТочнее (NLCD_Y_RES/8)+1 — понятно почему, а вот
NLCD_X_RES-1 — не понятно?
Chiper
10 лет назадПотому что отсчет индекса в буфере идет от нуля, а размер задается от 1. Вобщем-то то стандартный прием…
Shura
10 лет назад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.
Серга
9 лет назадс экраном 1202 будет работать ?
если нет то нет ли библиотек для 1202 ?
самыё дешёвый и простой в пайке дисплей всё-таки
ujin
9 лет назадбудет….библиотека может использоваться с разными лсд в том числе и 1202