Обновление библиотеки вывода для дисплеев 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 комментариев

Присоединиться к обсуждению

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

Мы ценим аргументированное и конструктивное общение. Пожалуйста, соблюдайте эти простые правила:

  • Уважение к другим. Общайтесь вежливо. Оскорбления, нецензурная лексика, угрозы и разжигание розни недопустимы.
  • Тематика. Пишите по теме статьи. Спам, реклама и ссылки на сторонние ресурсы без согласования будут удалены.
  • Законность. Запрещены призывы к нарушению законов РФ, обсуждение наркотических веществ и любые формы экстремизма.
  • Оформление. Не используйте Caps Lock (ЗАГЛАВНЫЕ БУКВЫ) для написания всего текста комментария.
  • Профиль. В качестве имени (никнейма) запрещено использовать ключевые слова, рекламу и адреса сайтов.

Все комментарии проходят проверку. При нарушении правил или рассылке спама аккаунт блокируется без права восстановления.

  • ArmiT

    14 лет назад

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

    • Chiper

      14 лет назад

      Заведется без всяких изменений.
      Единственное, что надо настроить, это разрешение экрана:

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

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

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

    • Chiper

      14 лет назад

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

      • Владимир

        14 лет назад

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

        • Chiper

          14 лет назад

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

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

          • Владимир

            14 лет назад

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

  • Владимир

    14 лет назад

    Пытаюсь перевести часть кода под 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); // вместо строки мусор!
    • Chiper

      14 лет назад

      Ужас!!!

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

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

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

        14 лет назад

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

        • Chiper

          14 лет назад

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

  • Владимир

    14 лет назад

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

  • Владимир

    14 лет назад

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

    //*****************************************************
    
    #include 
    #include 
    #include 
    #include 
    //#include 
    
    // 1 Wire Bus functions
    #asm
       .equ __w1_port=0x15 ;PORTC
       .equ __w1_bit=0
    #endasm
    #include 
    
    // DS1820 Temperature Sensor functions
    #include 
    
    // 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);
    
          };
    }
  • Владимир

    14 лет назад

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

    • Chiper

      14 лет назад

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

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

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

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

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

    • sawa

      12 лет назад

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

      • Chiper

        12 лет назад

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

  • Владимир

    14 лет назад

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

    • Chiper

      14 лет назад

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

  • Владимир

    14 лет назад

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

      • Владимир

        14 лет назад

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

  • Владимир

    14 лет назад

    Запарился я уже с этим шрифтом. По одному символу выводит без проблем. Как вывести строку? В библиотеке вывод символа есть а строки нет, пытался сам что то написать, видимо рано мне ещё.
    Пытался вот так:

    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), но как её обойти не знаю. В результате вместо символов в строке отображаются черные прямоугольники.

    • Chiper

      14 лет назад

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

        • Chiper

          14 лет назад

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

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

              • Chiper

                14 лет назад

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

            • Chiper

              14 лет назад

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

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

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

              и т.д.

            • Chiper

              14 лет назад

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

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

    • Chiper

      13 лет назад

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

      • Ringo

        13 лет назад

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

        • Chiper

          13 лет назад

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

  • Николай

    13 лет назад

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

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

    • Chiper

      13 лет назад

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

      Как-то так…

  • baralgin1003

    13 лет назад

    Подскажите как выводить шрифт двойного размера, нарисовал 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]);
     
    }
  • Ringo

    13 лет назад

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

    
    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, китай.

        • Ringo

          13 лет назад

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

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

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

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

          • Ringo

            13 лет назад

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

            • Chiper

              13 лет назад

              🙂

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

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

          • Chiper

            13 лет назад

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

  • Андрей

    13 лет назад

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

  • igorok107

    13 лет назад

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

  • syavagold

    13 лет назад

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

      • syavagold

        13 лет назад

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

  • Ringo

    13 лет назад

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

    • syavagold

      13 лет назад

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

      • Ringo

        13 лет назад

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

        • syavagold

          13 лет назад

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

  • ujin

    13 лет назад

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

    • Chiper

      13 лет назад

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

  • ujin

    13 лет назад

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

  • syavagold

    13 лет назад

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

    • Chiper

      13 лет назад

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

      // Инициализация контроллера
      void nlcd_Init(void)
      {	
      ...
      delay_ms(1000);               		// 1 Sec delay
      }
      • syavagold

        13 лет назад

        Ну задержка как я понял была задумана для эффекта затемнения экрана перед запуском вывода. Но я ее закоментировал сразу как увидел. Просто нет сейчас возможности проверить в железе. Если есть у кого боард на готове могу хекс скинуть глянули бы.

  • ujin

    13 лет назад

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

  • ujin

    12 лет назад

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

    • Chiper

      12 лет назад

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

  • Nikolaich

    12 лет назад

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

    • Chiper

      12 лет назад

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

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

      • Nikolaich

        12 лет назад

        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-дисплей. И опять —ни чего.(ОХ,ЛУЧШЕ Б МАЛЕНЬКИМ Я СДОХ).С уважением….

  • syavagold

    12 лет назад

    Помогите вывести рамку на экран: использую текстовую библиотеку, функцией вывожу массив нарисованный в программе, часть картинки выводится нормально, но когда начинаю выводить остальные части массива картинка начинает бегать кусочками по экрану:
    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]);}

    }

        • ujin

          11 лет назад

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

  • Серга

    11 лет назад

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

  • pasha_rey

    10 лет назад

    всем привет
    подключаю десплей 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

    10 лет назад

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

  • Никифор

    10 лет назад

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

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

  • Marina Zemina

    8 лет назад

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

  • Оля

    7 лет назад

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

    #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);
    
    }
    • Chiper

      7 лет назад

      Есть несколько вариантов. Выводить библиотека может только текстовые строки. Что бы выводить числа, их нужно перевести в текст.
      Что бы перевести вещественные числа в текст в среде Ардуино есть несколько способов:
      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); 
          } 
      }