Обновление библиотеки вывода для дисплеев Nokia

Nokia 1100 - картинка 1

После того, как Валерий Гончаренко сделал приятный подарок в виде нескольких дисплеев Nokia, я немного переработал свою библиотеку вывода для дисплеев Nokia. Изменения коснулись обоих вариантов библиотеки, как графической (2.1), так и текстовой (1.1). В графический вариант внесено больше изменений, чем в текстовый, добавлены несколько новых функций.

Так как библиотеки разделены на два варианта, то имеет смысл рассказать об этом. Разделение на два варианта было сделано с целью экономии ресурсов там, где нам не нужны расширенные функции. В общем случае нумерация библиотек складывается следующим образом: номер варианта.номер версии.

Варианты и версии библиотеки

Текстовый вариант библиотеки имеет нумерацию 1.x и содержит только функции вывода на экран текстовой информации. Занимает в памяти программ минимум места и не создает никаких буферов в оперативной памяти. Содержит только функции вывода текста на экран. Рекомендуется для микроконтроллеров AVR с минимумом системных ресурсов (программной и оперативной памяти).

Второй вариант библиотеки — графический. Имеет нумерацию 2.x и содержит весь набор функций текстового варианта с добавлением функций для работы с графикой. В отличии от текстового варианта занимает намного больше памяти, как программной, так и оперативной. В оперативной памяти создается видеобуфер, содержащий копию того, что выведено на экран, так как дисплеи от Nokia позволяют только записывать данные в контроллер дисплея (хотя сам контроллер позволяет как записывать, так и читать данные). Буфер занимает в памяти 864 байта, плюс еще несколько переменных. Соответственно, применять этот вариант библиотеки можно на микроконтроллерах, которые имеют достаточное количество оперативной памяти.

Скорость работы

Основной претензией к работе библиотеки с экранами Nokia, в частности экраном Nokia 1100, было низкое быстродействие. Этот дисплей от Nokia 1100 можно было назвать супертормозным. Библиотека имеет параметр NLCD_MIN_DELAY (задается в файле nokia1100_lcd_lib.h). Это минимальная задержка при передаче байтов данных в контроллер дисплея. Так вот, в первой версии библиотеки (как 1.0, так и в 2.0) этот параметр имел значение 270 микросекунд для дисплея  Nokia 1100! Передача данных в контроллер дисплея была очень медленной. При меньшей задержке вывод на экран не работал. В отличии от 1100 в дисплеях Nokia 1202 можно было (да и сейчас это можно, и даже нужно) установить задержку в 0, после чего вывод на экран происходит мгновенно.

Во второй версии (именно версии, не варианте) библиотеки (1.1 и 2.1) ускорена работа с дисплеем, причем на порядок. Теперь минимальная задержка при передаче данных в контроллер 1100 — 34 микросекунды! Сравните: 270 было, 34 стало  (1202 работает при 0 — рекордсмен по скорости). Теперь вывод на экран стал намного более приемлемым. Реализовано это дополнительным командами инициализации.

Ошибка в видеобуфере

Так как изначально библиотека писалась под единственный имеемый в наличии дисплей Nokia 1100, то в расчетах при написании были допущены ошибки, которые устранены во второй версии библиотеки. Теперь размер буфера вычисляется автоматически по заданным параметрам. Сейчас можно задать параметр разрешения дисплея (файл nokia1100_lcd_lib.h) и использовать библиотеку с дисплеями с разным разрешением экрана, но со сходной системой команд.

Кодировка символов

Раньше вывод символов кириллицы был реализован частично в кодировке CP866. Теперь вывод символов реализован с кодировкой CP1251 (win1251), как более распространенной. Выводятся только символы кириллицы, псевдографика не выводится.Т.е. теперь не нужно подготавливать специальным образом строки для вывода кириллицы. Просто пишем nlcd_Print («Велик и могуч русский язык!»); и все работает корректно.

Про модификацию библиотеки под эту кодировку писал Maxim Grigorov в своем блоге. С точки зрения программиста изменения у него реализованы более грамотно, через функцию lcd_symbol_decode(c), но я сделал без функции, напрямую. Вызов функции занимает некоторое время (минимальное, но все же), а у меня пересчет идет прямо в процедуре вывода символа. Без всяких проверок на корректность данных, незачем тратить время на ерунду, мы не для настольных компьютеров быдлокодим программируем, нам каждый байт дорог :).

Вывод символов двойной ширины

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

Прототип функции:

void nlcd_PrintWide(unsigned char * message);

Используется точно также как и nlcd_Print.

Тест широкого шрифта на экране Nokia 1100

Тест широкого шрифта на экране Nokia 1100

Тест широкого шрифта на экране Nokia 1202

Тест широкого шрифта на экране Nokia 1202

Разрешение экрана

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

// Разрешение дисплея в пикселях
#define NLCD_X_RES    96        // разрешение по горизонтали
#define NLCD_Y_RES    68        // разрешение по вертикали

Работать с разрешением в функциях стало проще, теперь не надо править всю библиотеку под свой экран, если разрешение отличается от принятого в 1100 (96×65). Выше в примере заданы размеры экрана 1110i и 1202.

Вывод прямоугольника

Исправил ошибку в функции рисования прямоугольника. Проявлялась при рисовании с параметром наложения PIXEL_INV.

Вывод изображений

Ну и как же без вывода картинок. Написал первую версию этой процедуры. Куча ограничений. Практически никаких проверок на корректность данных. Зато работает очень быстро.

Долго сидел и думал, как ее написать. Можно написать при помощи функции nlcd_Pixel, т.е. выводить изображение попиксельно. Можно реализовать практически все проверки на корректность и т.д. Но работать будет очень долго. Это не наш путь.

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

Ограничения заключаются в том, что размер картинки по вертикали должен быть кратен 8. По горизонтали — без ограничений (в разумных пределах). Затем, координаты вывода левого верхнего угла картинки по вертикали опять же должны быть кратны 8. По горизонтали — без ограничений. Если функцию вызвать, например, с такими параметрами: nlcd_Pict (10,10,picture);, то картинка picture будет выведена по координатам: по горизонтали 10, во вертикали 8 (левый верхний угол картинки). Т.е. вертикальная координата приводится к значению, кратному 8.

Еще одно из ограничений в том, что картинка должна хранится в программной памяти, так как используется pgm_read_byte (). Думаю, что это логично, так как картинки занимают довольно много памяти, и хранить их в оперативке — не наш метод.

Картинки имеют следующий формат:

  • байт 0 — размер по горизонтали в пикселях (без ограничений, но в разумных пределах);
  • байт 1 — размер по горизонтали в пикселях (кратный 8);
  • далее массив данных побайтно (столбец из 8 бит) и построчно. Единица в значении бита говорит о том, что пиксел зажжен (светится).

Для подготовки данных, по подсказке Валерия Гончаренко (thanx), использую программу от Alex_EXE. После получения массива с данными картинки, добавьте в начало массива два байта с размером картинки по горизонтали и по вертикали (ну и размер массива нужно изменить на 2 байта).

Генератор картинок

Генератор картинок

В итоге должно получится что-то типа этого:

PROGMEM static const char nlcd_image[] =
{ 24,24,
0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x00,
0x00, 0xE0, 0x78, 0x1F, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF,
0x01, 0xFF, 0xFE, 0xFF, 0xDB, 0xDB, 0xDB, 0x00, 0xFF, 0xC0, 0xC0, 0x00,
0x07, 0x07, 0x07, 0x06, 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07,
0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x07, 0x07, 0x02, 0x00};

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

Ну и вывод этой картинки выглядит так:

nlcd_Pict(40,8,nlcd_image);

Несколько примеров того, как выглядят изображения на экранах:

Nokia 1100 - картинка 1

Nokia 1100 — картинка 1

Nokia 1100 - картинка 2 - инверсная

Nokia 1100 — картинка 2 — инверсная

Nokia 1202 - картинка 1

Nokia 1202 — картинка 1

Nokia 1202 - картинка 2 - инверсная

Nokia 1202 — картинка 2 — инверсная

Ну и напоследок сравнение, как выглядит картинка на разных дисплеях.

Сравнение отображения экранов Nokia 1100 и 1202

Сравнение отображения экранов Nokia 1100 и 1202

На экране 1202 картинка чуть более контрастная, чем на 1100. Но сам экран чуть меньше, чем 1100. На фотке видно, что вертикальное разрешение у 1202 чуть больше, чем у 1100 (68 против 65).

Скачать вторую версию библиотеки можно на странице с описанием функций, но там надо откорректировать само описание. Сделаю это чуть позже. Наверно, если будет время.

 

Вливайтесь в обсуждение

  116 комментариев

  • Надо ли менять настройки этой библиотеки для работы с дисплеем от Nokia 1202? Или заведется без изменений?

    • Заведется без всяких изменений.
      Единственное, что надо настроить, это разрешение экрана:
      // Разрешение дисплея в пикселях
      #define NLCD_X_RES 96 // разрешение по горизонтали
      #define NLCD_Y_RES 68 // разрешение по вертикали

      и пины, к которым подключен дисплей — в файле nokia1100_lcd_lib.h

      Все. В остальном она полностью работает с 1202

    • Еще задержку поставьте минимальную, параметр NLCD_MIN_DELAY.
      Я для 1202 ставил ноль  и вывод на экран просто мгновенный, все просто летало.

  • Владимир

    12 лет назад

    Данные библиотеки написаны под GCC?

    • Да, под GCC-AVR. Я писал в WinAVR Studio.

      • Владимир

        12 лет назад

        А под CVAVR есть такая библиотека? Переделывать код мне мозгов ещё не хватит.

        • Я под CVAVR непишу. Не сложилось.

          Переделать библиотеку по CVAVRдовольно легко. Весь код довольно подробно прокомментирован. Достаточно базовых знаний, что бы переписать библиотеку под CVAVR.

          • Владимир

            12 лет назад

            Уж так сложилось, что CVAVR мне даётся хоть как то, а WinAVR вообще никак. Может это моя ошибка, что начал с изучения CVAVR. Хоть сейчас многие и ругают его за его «ущербность», но для меня на данный момент другой альтернативы нет.

  • Владимир

    12 лет назад

    Пытаюсь перевести часть кода под CVACR. в результате бьюсь уже пару часов.
    Вывод символа 12х16 работает. Мне надо вывести строку этим шрифтом. Попытался написать функцию выводастроки.
    //*******************************************************************
    void char_12_16(char c,char x, char y) // вывод символа
    {
        unsigned char i;
        gotoxy(x,y);
        for ( i = 0; i < 12; i++ )
                {
                    lcd_write(DATA,deg12x16[c][i]);
                }
        gotoxy(x,y+1); 
        for ( i = 12; i < 24; i++ )
                {
                    lcd_write(DATA,deg12x16[c][i]);
                }
    }
    //*******************************************************************
    void char_12_16str(char*str, char x, char y) // вывод строки
    {
        char u;
        while(*str) {
         for(u=0;u<*str;u++)
          {

           char_12_16(*str++,x+(13*u),y);

          }
         }
    }

    Вывожу вот так:
    char_12_16(8,5,2); // символ выводится
    char_12_16str(LcdBuff1,5,6); // вместо строки мусор!

    • Ужас!!!

      Я чето так и не понял, как у вас работает процедура void char_12_16str. Может вы что то другое имели ввиду, не вывод простой строки ASCIIZ(оканчивающуюся нулем), тогда да…

      Я бы написал примерно так:

      void char_12_16str(char*str, char x, char y) // вывод строки
      {
      while (*str) char_12_16(*str++,x++,y);
      }

      • Владимир

        12 лет назад

        Почти такой код я использовал для дисплея Alkatel 311 (библиотека 3310), там все работает. Предложенный Вами код попробовал, все равно мусор.

        • Я с коммуникатора пишу, поэтому ни проверить ни посмотреть толком не могу. Вы бы весь проект привели. Может затык в другом… А я через пару дней доберусь до компа, может и помогу чем, если вы раньше проблему не решите.

  • Владимир

    12 лет назад

    Попробовал сейчас другие функции библиотеки, в результате хоть какой то результат есть только от функций от Panda. Все остальные просто пустой экран.

  • Владимир

    12 лет назад

    Вот основной файл, пытаюсь выводить разными шрифтами одновременно.

    *****************************************************/
    
    #include <mega32.h>
    #include <stdio.h>
    #include <delay.h>
    #include <1100.h>
    //#include <1100.lib>
    
    // 1 Wire Bus functions
    #asm
       .equ __w1_port=0x15 ;PORTC
       .equ __w1_bit=0
    #endasm
    #include <1wire.h>
    
    // DS1820 Temperature Sensor functions
    #include <ds18b20.h>
    
    // maximum number of DS1820 devices
    // connected to the 1 Wire bus
    //#define MAX_DS18b20 8
    // number of DS1820 devices
    // connected to the 1 Wire bus
    //unsigned char ds18b20_devices;
    // DS1820 devices ROM code storage area,
    // 9 bytes are used for each device
    // (see the w1_search function description in the help)
    //unsigned char ds18b20_rom_codes[MAX_DS18b20][9];
    unsigned char devices;
    unsigned char LcdBuffDevices[20];
    unsigned char RomCode[2][9];
    //unsigned char LcdBuff1[20];
    unsigned char Temp1[20];
    float temper_one;
    
    
    //#pragma rl+
    //char *str1="Датчики:";
    //char *str2="Обрыв!   ";
    //char *str3="oC";
    //#pragma rl- 
    
    
    // Declare your global variables here
    
    void main(void)
    {
    // Declare your local variables here
    
    // Input/Output Ports initialization
    // Port A initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTA=0x00;
    DDRA=0x00;
    
    // Port B initialization
    // Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
    // State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
    PORTB=0x00;
    DDRB=0xFF;
    
    // Port C initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTC=0x00;
    DDRC=0x00;
    
    // Port D initialization
    // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
    // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
    PORTD=0x00;
    DDRD=0x00;
    
    // Timer/Counter 0 initialization
    // Clock source: System Clock
    // Clock value: Timer 0 Stopped
    // Mode: Normal top=FFh
    // OC0 output: Disconnected
    TCCR0=0x00;
    TCNT0=0x00;
    OCR0=0x00;
    
    // Timer/Counter 1 initialization
    // Clock source: System Clock
    // Clock value: Timer1 Stopped
    // Mode: Normal top=FFFFh
    // OC1A output: Discon.
    // OC1B output: Discon.
    // Noise Canceler: Off
    // Input Capture on Falling Edge
    // Timer1 Overflow Interrupt: Off
    // Input Capture Interrupt: Off
    // Compare A Match Interrupt: Off
    // Compare B Match Interrupt: Off
    TCCR1A=0x00;
    TCCR1B=0x00;
    TCNT1H=0x00;
    TCNT1L=0x00;
    ICR1H=0x00;
    ICR1L=0x00;
    OCR1AH=0x00;
    OCR1AL=0x00;
    OCR1BH=0x00;
    OCR1BL=0x00;
    
    // Timer/Counter 2 initialization
    // Clock source: System Clock
    // Clock value: Timer2 Stopped
    // Mode: Normal top=FFh
    // OC2 output: Disconnected
    ASSR=0x00;
    TCCR2=0x00;
    TCNT2=0x00;
    OCR2=0x00;
    
    // External Interrupt(s) initialization
    // INT0: Off
    // INT1: Off
    // INT2: Off
    MCUCR=0x00;
    MCUCSR=0x00;
    
    // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x00;
    
    // Analog Comparator initialization
    // Analog Comparator: Off
    // Analog Comparator Input Capture by Timer/Counter 1: Off
    ACSR=0x80;
    SFIOR=0x00;
    
    // Determine the number of DS1820 devices
    // connected to the 1 Wire bus
    //devices=w1_search(0xf0,RomCode);
    devices=w1_search( DS18B20_SEARCH_ROM_CMD, RomCode ); delay_ms(100); //поиск датчиков на линии 1-wire
    
    LCD_init();
    delay_ms(20);
    LCD_clear();
    delay_ms(20);
    
    
    #asm("sei")
    while (1)
          {
          // Place your code here
                
          sprintf( LcdBuffDevices,"DS=%u", devices ); //выводим информацию о кол-ве датчиков
        
          gotoxy( 15,0 ); print_string( LcdBuffDevices);
             
    
          ds18b20_init( &RomCode[0][0], 30, 85, DS18B20_12BIT_RES );delay_ms(10); //инициализация первого датчика
          
          //чтение температуры первого датчика
          //sprintf( LcdBuff1," %.1f\'C", ds18b20_temperature( &RomCode[0][0] ) ); 
          //чтение температуры первого датчика  
          temper_one = ds18b20_temperature( &RomCode[0][0] );
          if( temper_one > 1000 ) { temper_one = 4096-  temper_one; temper_one = -temper_one; }  
          sprintf( Temp1," %.1f\'C   ", temper_one  );
          
          //вывод данных на дисплей
          gotoxy( 50,3 ); print_string(Temp1);
          gotoxy( 55,0 ); print_char(8);
          char_12_16(8,5,2);
          char_12_16s("Temp1",5,4);
          char_24_32(6,30,2);
          gotoxy( 70,0 ); LCD_bold_char(8,1);
          gotoxy( 70,1 ); LCD_char(125,1);
          //delay_ms(100);
    
    
          };
    }
    
  • Владимир

    12 лет назад

    Победил я все же эту библиотеку. Я по старинке пытался выводить напрямую. В это и была моя ошибка. Упустил тот момент, что в ней используется буфер. Спасибо за терпение.

    • Победил я все же эту библиотеку.

      Молодчага! Работа боится, руки делают… 🙂

      Спасибо за терпение.

      Да что ты, какое терпение, обращайся, если что…

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

    • Здравствуйте Владимир.
      Не могли бы Вы скинуть на мой адрес проект термометра на LCD1202 в
      CVAVR.
      Спасибо.

      • Я сейчас в отпуске, далеко от компов и интернета. Поэтому никак не могу. По возвращению, если будет актуально, что нибудь придумаем.

  • Владимир

    12 лет назад

    Я тут заткнулся на выводе крупного шрифта. Конкретно нужно вывести значение переменной шрифтом 24х32. Почти сутки бьюсь и не как.Склоняюсь к тому, что это из-за то, что я изменил
    const unsigned char deg24x32[13][96]  на  flash unsigned char deg24x32[13][96], если оставить const  , не влазит в память.

    • Я так понимаю, что const unsigned char deg24x32[13][96] создает массив констант в оперативной памяти, а flash unsigned char deg24x32[13][96] в программной памяти. Не знаю как в CVAVR, но в AVR-GCC с ними работают по разному.

  • Владимир

    12 лет назад

    Создал «голый» проект с выводом текста, все работает. Видимо дело в настройках самого проекта. Буду пробовать подбирать размер стека.

    • Видимо дело в настройках самого проекта

      С этого надо всегда начинать.

      • Владимир

        12 лет назад

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

  • Владимир

    12 лет назад

    Запарился я уже с этим шрифтом. По одному символу выводит без проблем. Как вывести строку? В библиотеке вывод символа есть а строки нет, пытался сам что то написать, видимо рано мне ещё.
    Пытался вот так:
    void LCD_deg_24x32s(unsigned char*str, unsigned char color)    // ++ вывод строки
    {
    unsigned char x;

    x=posx;
    while(*str!=») LCD_deg_24x32(*str++, color);
    if(color==0) LCD_frame(x);
    }
    Догадываюсь что проблема в функции LCD_frame(x), но как её обойти не знаю. В результате вместо символов в строке отображаются черные прямоугольники.

    • Я не понял всего действа из приведенного куска, но навскидку координата X нигде не инкрементируется (увеличивается), поэтому все рисуется в одном месте

      • Владимир

        12 лет назад

        На форуме KAZUS я уже задавал этот вопрос, но пока тоже тишина. Там и сам проект есть. http://kazus.ru/forums/showpost.php?p=533258&postcount=1202

        • Посмотрел код на Казусе — ужас. Мешанина кода. Так писать нельзя. Я сам не всегда оптимальный код пишу, но такой каши… дас-с-с…

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

          • Владимир

            12 лет назад

            А каша в каком месте?

            • Владимир

              12 лет назад

              За основу была взята библиотека с Вашего сайта http://digitalchip.ru/uploads/proj_files/nokia1100_v2/nokia1100_lib_all_v2.zip. Изменения вносились минимальные, касаются в основном вывода строк.

              • Я вижу, что возможно части из моей, но она сильно переделана

            • — Нет единого стиля именования функций и переменных

              — имена функций ни о чем не говорят, не поймешь сразу что они делают

              — все функции перемешаны, нет единого логического порядка

              и т.д.

            • Все шрифты в одном файле, там же и код. Надо разделять на модули. Шрифты отдельно, код отдельно, определения и интерфейсы отдельно.

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

  • а по подключению дисплеев от samsunga помочь можете ???

  • А через USART пробовали делать?

  • Попробовал переписать библиотеку под Raspberry Pi (Raspbian).
    Все работает, но есть артефакты:
    http://www.youtube.com/watch?v=DPkp4JFa3JI
    Не могу понять, в чем причина.

    • Ну если все переписали правильно… Может дисплей с битой памятью? На AVR пробовали этот дисплей запускать?

      • На atMega8 дисплеи (2 шт.) отрабатывают нормально.
        По сути — у меня переписана работа с пинами и убрано упоминание об «программной памяти»
         

        • Значит надо смотреть на процедуры вывода. Похоже у вас ошибка с логическими операциями в части, где происходит наложение текущей строки на такую же строку в видеобуфере. Проверьте еще раз.

  • Николай

    11 лет назад

    Знатоки, подскажите. Экран 1100 + атмега 8.
     
    lcd_init();
    while (1)
    {
    sprintf (lcd_buf, "%02u:%02u:%02u",h,m,s ); / отрисовываем минуты, секунды, часы. переменные
    gotoxy(0,0);                                                 крутятся в таймере Т2/ 
    print_string (lcd_buf);

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

    • Предполагаю 2 вещи:
      1. Вывод происходит слишком быстро, вставьте задержку после print_string. Вам же не нужно выводить часы очень часто. Пару раз в секунду (или 1 раз в секунду) вполне достаточно.
      2. Помимо нужных данных выводится и мусор. Очищайте буффер перед использованием.

      Как-то так…

  • baralgin1003

    11 лет назад

    Подскажите как выводить шрифт двойного размера, нарисовал 10*16, а он половинится. То есть один символ выодится двумя половинками. 
    шрифт такого вида:

    const unsigned char nlcd_FontX2[][20] PROGMEM ={
     
    { 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x03, 0xE3, 0xE3, 0xFF, 0xFF,
     0x3F, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x3F, 0x3F, 0x3F, 0x3F },  // 0
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xFF, 0xFF,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F },  // 1
     

    вывожу так (чуток изменил функционал исходника):

    void nlcd_PutcWide(unsigned char c)
    {
    if (c>127) c=c-64; // Переносим символы кирилицы в кодировке CP1251 в начало второй
    // половины таблицы ASCII (начиная с кода 0x80)
     
    for ( unsigned char i = 0; i < 20; i++ )
    {
    unsigned char glyph = pgm_read_byte(&(nlcd_FontX2[c-48][i]));
      nlcd_SendByte(DATA_LCD_MODE,glyph); 
        }    
    nlcd_SendByte(DATA_LCD_MODE,0x00); // Зазор между символами по горизонтали в 1 пиксель
     
    }
     
    void nlcd_printWCharS(unsigned char* c)
    {
     
    for(unsigned char i=0;i<strlen(c);i++)
    nlcd_PutcWide(c[i]);
     
    }

  • По поводу скорости работы дисплея.
    Я сделал так:

    void nlcd_Init(void)
    {   
        if (!ncld_pwr_status) {
        // Инициализируем порт на вывод для работы с LCD-контроллером
        DDR_LCD |= (1<<SCLK_LCD_PIN)|(1<<SDA_LCD_PIN)|(1<<CS_LCD_PIN)|(1<<RST_LCD_PIN)|(1<<PWR_LCD_PIN);

        CS_LCD_RESET;
        RST_LCD_RESET;

        delay_ms(5);            // выжидем не менее 5мс для установки генератора(менее 5 мс может неработать)

        RST_LCD_SET;

       delay_ms(10);

    Дальше все как у вас.
    После этого, NLCD_MIN_DELAY можно выставить в 1 мс (0 не выставляется, т.к. delay_ms хочет отличное от 0 число, а убирать везде delay_ms я поленился)
    На моей меге8 и raspberry pi работает.
    Дисплей 1100, китай.

    • Дельное замечание! Спасибо!

      Надо бы собрать макетку — проверить.

      • А еще у вас беда со ссылкой:
        http://digitalchip.ru/opisanie-funktsiy-graficheskoy-biblioteki-dlya-lcd-ekrana-ot-nokia-1100
        Выдает, что у меня IE6 (причем на любых браузерах)
        [IMG]http://f3.s.qip.ru/dD49erTl.jpg[/IMG]

        • Ссылка починилась.
          Вопрос такой: 
          При попытке скомпилировать тестовую программу, использующую
          графический буффер, получаю сообщение об ошибке:

          Linker error: global RAM variables size: 864 bytes is too large

          Чип — AtMega8a, RAM у него согласно даташиту 1Kb.
          Программа — в CodeVision AVR 2.05.3.

          Не могу понять в чем проблема.
          В AVRStudio 4 компилится и работает.
          Но она мне категорически не нравится да и некоторые функции там по другому реализованы.
           
          Не знаете как CodeVision починить?

          • Разобрался благодаря автору другой подобной библиотеки.
            Надо было изменить распределение памяти в настройках компилятора.

            • 🙂

              Рад, что решение нашлось.

              И кстати, раз уж получилось, может выложите библиотеку на CodeVision на сайт? Другим, я думаю, пригодится.

          • Чесслово, не знаю. С CodeVision и IAR у меня почему то не сложилось. Совсем. Подсел плотно на бесплатный AVR-GCC. И теперь пишу только на нем.

        • Ссылка на библиотеки поломана опять..

  • Странно.. Сразу после комментария она чинится.. о_О

  • Андрей

    10 лет назад

    Дайте пожалуйста простейший пример исходника для Arduini IDE/ Хотябы «печатать точку в координатах» . не компелирует.

  • Спасибо за библиотеку. Подключил дисплей 1110i, сначала не хотел работать, т.е. видно, как он стирает дисплей от шума, но после вывода символа или просто посылки байта, ничего не показывал. Оказалось, что после отправки байта, линия клок остаётся в логической единице и видно дисплей ждал завершения посылки бита. добавил в конец процедуры SendByte() SCLK_LCD_RESET; и всё заработало.
    Кстати оформил либу в виде библиотеки для arduino. Скачать можно здесь: https://drive.google.com/file/d/0BxVbH3NtEnFQWG9VU2x1dXpySlE

  • Владимир  к сожалению библиотекой под CVAVR так и не поделился  или я не там смотрю?

  • Сорри за оффтоп вопрос был к Ringo

    • Все доступные мне библиотеки выложены здесь: http://digitalchip.ru/opisanie-funktsiy-graficheskoy-biblioteki-dlya-lcd-ekrana-ot-nokia-1100

      Ringo так и не прислал мне библиотеку для CodeVision.

      • не понимаю что не не так при компиляции cvarv ругается что я пытаюсь засунуть в RAM 2362 байта хотя только подключил библиотеку lcd и ничего больше… пустой цикл while. Скорей всего переменные в библиотеке заносятся в RAM, а что изменить что бы заносились в память программ? Я еще полный чайник в программировании и самому библиотеку переписать не под силу, а дисплеев нокиа 1202  штук 15 лежит.

  • А я ее так и не допилил, чтобы было не стыдно показать общественности 🙂
    У меня там гибрид этой библиотеки и еще двух 🙂

    • кого стыдится? 🙂 давайте общими силами попробуем допилить такой библы не нашел нигде вообще

      • Выложил вот сюда: https://dl.dropboxusercontent.com/u/586096/Nokia%201112%20UI%20Lib.zip свой проект, который я пока дропнул.
        Это должен был быть 2х канальный термометр на DS18B20. В 
        В папке — проект CVAVR и файлик протеуса.  Пока только демонстрация основного экрана UI. 
        На реальном железе тоже работает. 

        • Спасибо! Мало кто откликается. Мой проект это регулятор для ламинатора под ЛУТ и фоторезист. Основной код практически готов осталось только вывод на дисплей сделать, если все получится проект выложу на всеобщее обозрение.

  •  Здравствуйте, с разрешения уважаемого chiperа   могу  выложить его библы перемонтированные для CVAVR  версии 2.05.3 standart в связке с протеусом 7.10 sp0 (проект успешно скомпилился и в протеус все завелось и заработало сразу,вывел текст из ОЗУ на экран ), честно не совсем уверен с корректностью функции nlcd_PrintF вывода строки из флеш памяти (сравнить изменения можно с оригиналом там их немного).
    от себя скажу большое спасибо уважаемому chiperу и его помощникам  за столь качественный и очень хорошо разжёванную библиотеку и статьи.

    • 🙂 Льстите… 🙂
      По существу… Шлите исходники и т.д. мне на мыло, я размещу. Наверняка многим поможет.

  • странно  выше наверху был указан ваш адрес электронки……gmail.com…пытался на него отправить..пишет неверно написан адрес….может есть ещё куда вам кинуть…или я чтот непраильна  делал..
    сёня уже не успею…пора на работу

  • Отправил зип….на адрес

  • Странно но мне кажется что библиотека ujin тратит Оочень много время на инициализацию, или мне кажется? При симуляции в протеусе от нажатия Play до вывода первого символа у меня проходит около семи минут…

    • Кстати да, сейчас посмотрел, у него в конце процедуры инициализации стоит задержка в 1000 мс (зачем???). Поэтому эта задержка + скорость симуляции Протеуса = медленно.

      // Инициализация контроллера
      void nlcd_Init(void)
      {	
      ...
      delay_ms(1000);               		// 1 Sec delay
      }
      • Ну задержка как я понял была задумана для эффекта затемнения экрана перед запуском вывода. Но я ее закоментировал сразу как увидел. Просто нет сейчас возможности проверить в железе. Если есть у кого боард на готове могу хекс скинуть глянули бы.

  • здравствуйте
    в библиотеке на экран которую я скачал отсюда,в функции инициализации дисплея  последняя строка была….    _delay_ms(1000);// 1 Sec delay….она там уже была по умолчанию …логику работы с экраном я абсолютно не менял….для компиляции  в кваре я изменил строчки где квар и винавр по разному ссылаются на программную (флеш)память…(ту строку у себя я тоже закоментил -долго думал в протеусе). так что думаю если с этой библиотекой экранчики работали в железе…то должно быть без разницы

  • здравствуйте….немного перемонтировал библиотеку версии 1 для нокии1100 в данном виде эта библиотека интегрируется в cvavr и доступна как стандартная библиотека….если это интересно, то как обычно с разрешения уважаемого автора chipera могу выложить для теста естественно на свой страх и риск…(сам же в таком виде её использовал в кваре 2.05.3 в связке с протом 7.10 всё работает норм.)
    с уважением…

  • От кого:
    Кому: dmiXXen@XXXXXX.ru
    Вчера, 3:16 03-09-2014…

    • Блин, только сейчас заметил. Письмо почему то улетело в спам. Хотел почистить папку спама, но на глаза попалось и не успел удалить. Слава богу. Сейчас добавлю на сайт.
      Спасибо.

  • День добрый.Сразу обозначусь:только начинаю «возиться» с контролерами ATMEL . Собрал адаптеры и для 1110i ,и для 1202.Подключил дисплеи (по очереди)к ATmega16, залил версию V2.1 и ….. ни один (дисплей) ни чего не показывает.В программировании я не силен еще,но читая комментарии( в голове начинает «сгущаться») понимаю , что я «где то рядом», а где -???? Уважаемый Chiper подскажите.
    Я менял задержки (delay_ms…) 10,100,150,1000; ни чего не меняется.
    С уважением…

    • Хм… Так прямо сразу и не скажешь. Нужно смотреть как вы собрали адаптер, как программировали контроллер и т.д. и т.п.

      Давайте описание вашего процесса сборки и программирования, будем разбираться.

      • Chiper спасибо за отзыв.Адаптеры собрал как на вашем сайте. Программировал в AVR Studio (V4.12).Я понял ,что это просто библиотеки,нужно же что то выводить, поэтому попробовал проект парня http://digiua.com/lcd-nokia-1110/ .Он выводит картинку и проверку АЦП.Адаптер для 1110i(1200)я собрал первым , так как был всего один LD1117 (3.3V), а на адаптер 1202 подавал отдельно 3.3V. Вообщем как я писал— ни чего. Хотя с атмеги16 сигналы идут , проверял и логическим пробником, и ARDUINO-осцилографом(https://code.google.com/p/xoscillo/).А тут вчера получил заказанные LM1117(3.3V) и увидел Ваш ответ.На радостях впаял LM-ку в адартер 1202 и подсоединил к Атмеге16, и «о боже» он нарисовал картинку и написал три строчки (ну как у этого парня). Правда зеркально и не контрастно.Тогда я «ткнул» кондером в 10мкф на ножку подсветки, стало ярче. Ну думаю впаяю его и промою спиртиком. Но случайно спирт попал под подложку экрана.Сушил ,продувал—всё бестолку. Видно «спился» мой 1202-дисплей. И опять —ни чего.(ОХ,ЛУЧШЕ Б МАЛЕНЬКИМ Я СДОХ).С уважением….

  • Помогите вывести рамку на экран: использую текстовую библиотеку, функцией вывожу массив нарисованный в программе, часть картинки выводится нормально, но когда начинаю выводить остальные части массива картинка начинает бегать кусочками по экрану:
    void lcd_fonn(char x, char y)
    {
    unsigned char i;
    //nlcd_GotoXY(0,0);
    for ( i = 0; i < 96; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);} // русует верхнюю полоску
    //nlcd_GotoXY(0,1);
    for ( i = 96; i < 192; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);} // русует вторую полоску
    //nlcd_GotoXY(0,2);
    //for ( i = 192; i < 256; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);} // после этого цикла
    //nlcd_GotoXY(x,4); начинается движение рваной картинки по всему экрану
    //for ( i = 288; i < 384; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);}
    //nlcd_GotoXY(x,4);
    //for ( i = 384; i < 480; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);}
    //nlcd_GotoXY(x,5);
    //for ( i = 480; i < 576; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);}
    //nlcd_GotoXY(x,6);
    //for ( i = 576; i < 672; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);}
    //nlcd_GotoXY(x,7);
    //for ( i = 672; i < 768; i++ ){nlcd_SendByte(DATA_LCD_MODE,lcd_image_mas[i]);}

    }

    • Сам массив в коментарии к видео, сюда почему то вставить не могу http://youtu.be/hJC2AY1yk4Q

      • Проблема решена. Разбил массив да двухмерный и вывел кусками.

        • …..думаю что проблема в принципе может решена кардинально (как вариант)…читайте в комментариях статьи «Описание функций графической библиотеки для LCD-экрана от Nokia 1100»

  • Серга

    9 лет назад

    подкиньте примеры менюшек текстовых!
    выбор менюшки по кнопке или жнкодером
    Буду очень признателен!

  • всем привет
    подключаю десплей 1100 к ардуинке пробую залить какой нибуть код и вот такая ошибка

    avrdude: stk500v2_ReceiveMessage(): timeout
    avrdude: stk500v2_ReceiveMessage(): timeout
    avrdude: stk500v2_ReceiveMessage(): timeout
    avrdude: stk500v2_getsync(): timeout communicating with programmer

    [Stino — Exit with error code 1.]

    а если в стандартной IDE пытаюсь залить то вот такая

    Hello_World.ino: In function ‘void setup()’:
    Hello_World.ino:6:6: error: redefinition of ‘void setup()’
    sketch_jun13b.ino:1:6: error: ‘void setup()’ previously defined here
    Hello_World.ino: In function ‘void loop()’:
    Hello_World.ino:16:6: error: redefinition of ‘void loop()’
    sketch_jun13b.ino:6:6: error: ‘void loop()’ previously defined here
    Ошибка компиляции.
    што делать?
    зарание спасибо

  • izhadapter

    7 лет назад

    не увидел нигде версии текстовой 1.1 с поддержкой 1202
    вообще библиотека универсалная а название ёё неё nokia1100_lcd_
    создают значительные нестыковки в мозгу.

  • Никифор

    7 лет назад

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

    может и на 1100 также ?

  • Marina Zemina

    6 лет назад

    Здравствуйте! Таким образом занятыми окажутся от 6-ти до 11-ти контактов от обоих устройств. Если вам не требуется считывать с дисплея, что подходит под большинство сценариев использования, для команд понадобится 2 линии.

  • Библиотека хорошо работает, все выводит и строки и рисунки.
    А как быть если есть к примеру переменная с плавающей точкой. Как ее вывести?

    #include  
    
    PCF8814 Lcd(13,11,10,6); // SCLK, SDA, CS, RESET.
    
    String s;  char Text[] = "Русский ТЕКСТ";  float volts=18.3;
    
    void setup() { 
      Serial.begin(9600);
      Lcd.Init();
      delay(100);
      Lcd.Contrast(0x0F);//  0х00 - 0х1F 
      Lcd.GotoXY(0);
      Lcd.Print("ДОБРОЕ УТРО++");
      Lcd.GotoXY(1,2);
      Lcd.PrintWide("СТРАНА");
      Lcd.GotoXY(1,4);
      Lcd.Print(Text); // Выводим строку из программной памяти
    
    }
    
    void loop() {
      
      s = "U1 "+String(volts);
      Serial.println(s);   // в монитор порта выводит
    
    //val = String(va/10, DEC); val += "."; val += String(va%10, DEC);
    
      Lcd.GotoXY(0,6);
      Lcd.Print("12,9  "); Lcd.Print("4,7  "); 
      //Lcd.Print("18,9"); 
      Lcd.Print(s);    // ошибка компилятора 
      delay(1000);
    
    }
    • Есть несколько вариантов. Выводить библиотека может только текстовые строки. Что бы выводить числа, их нужно перевести в текст.
      Что бы перевести вещественные числа в текст в среде Ардуино есть несколько способов:
      1. Использовать библиотеку floatToString
      2. Использовать sprintf() с набором параметров форматирования
      3. Использовать функцию dtostrf() с набором параметров
      4. Написать свою функцию перевода типа такой:

      // Converts a floating-point/double number to a string. 
      void ftoa(float n, char* res, int afterpoint) { 
          // Extract integer part 
          int ipart = (int)n; 
          // Extract floating part 
          float fpart = n - (float)ipart; 
          // convert integer part to string 
          int i = intToStr(ipart, res, 0); 
          // check for display option after point 
          if (afterpoint != 0) { 
              res[i] = '.'; // add dot 
              // Get the value of fraction part upto given no. 
              // of points after dot. The third parameter  
              // is needed to handle cases like 233.007 
              fpart = fpart * pow(10, afterpoint); 
              intToStr((int)fpart, res + i + 1, afterpoint); 
          } 
      }
      

Добавить комментарий

Отправляя комментарий, вы автоматически принимаете правила комментирования на сайте.

Правила комментирования на сайте:

  1. Не следует писать исключительно заглавными буквами. Это дурной тон.
  2. Запрещены комментарии не относящиеся к тематике сайта и самой статье.
  3. Запрещены реплики оскорбляющие других участников проекта. Давайте будем взаимовежливы.
  4. Запрещены нецензурные слова, идиоматические выражения, призывы к межнациональной и межконфессиональной розни.
  5. Запрещено обсуждение наркотических веществ и способов их применения.
  6. Запрещены комментарии с призывами к нарушению действующего законодательства РФ (Уголовного и Административного кодекса).
  7. Запрещены ссылки на сторонние ресурсы без согласования с владельцем сайта.
  8. Запрещается использовать в качестве имени комментатора слоганы/названия сайтов, рекламные фразы, ключевые и т.п. слова.

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

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