Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Ср ноя 25, 2015 15:41:07

Сори 32 бита микрософт ... и так еле скомпилял у меня RadStudio 10 а он во всю под 64 точен ...

увы лет 10 хочу начать кодить под люникс но все четно , есть у меня белые пятна :)

под виндой не ниже ХР работать должно

Изображение

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Ср ноя 25, 2015 18:33:28

А я вот тоже всё мечтаю свой редактор растровых шрифтов сделать, а то те, что существуют - все хоть чем-то да не устраивают.

Но всё некогда заняться этим. Пока на что хватило времени - это лишь на редактор цифр в редакторе eeprom своего проекта часов на светодиодных матрицах.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Чт ноя 26, 2015 14:16:19

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

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сб апр 16, 2016 14:35:03

WiseLord писал(а):Ну.. не знаю. По даташиту ширина строба (Tpw) при чтении 320нс. Об остальном заботится процедура чтения флага занятости.

Ну а dummy read - да, нужен. У меня тоже использовалось (опечатка в комментарии).


Код:
static uint8_t st7920ReadData()
{
   uint8_t data;

   st7920WaitWhile(ST7920_STATUS_BUSY);
   ST7920_CTRL_PORT |= ST7920_RS;

   data = st7920Strob();

   return data;
}

Проясните пожалуйста как Вы производите чтение не подняв RW на единицу?
Точно ли возможно чтение при Extended Function set?

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сб апр 16, 2016 16:46:23

А с чего Вы взяли, что RW не в единице?

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сб апр 16, 2016 21:31:19

Ну типа RW потенциально может быть не на единице. Мене просто удивило, что Вы принудительно RW в единицу не загоняете.
Подскажите, пожалуйста что не так в алгориртме ниже.
Код:
    uint8_t ABC[16],
            a;
    Set_Adress(0,0);
    RS=1:
    RW=1;
    Strob();
   
    for(a=0; a<16; a++)
    {
        Strob();
        ABC[a] = PORTC;
    }
       
    RW=0;
    Set_Adress(20,0);
       
    for(a=0; a<16; a++)
    {
        PORTC = ABC[a];
        Strob();
    }


Пытаюсь скопировать пиксели с нулевого адреса на 20-ый. Вот что получается:
Изображение
Пробовал выставлять задержку 100мкСек тупо после каждой команды. Результат идентичный.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Сб апр 16, 2016 21:51:06

Наверное разгадка вот в этом:
Код:
            if (data & (128>>k))
               fb[j * 8 + k] |= (1<<i);
            else
               fb[j * 8 + k] &= ~(1<<i);

Если Вас не затруднит, проясните сакральный смысл этого чудо-алгоритма.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Вс апр 17, 2016 01:50:23

Burgunsky писал(а):Мене просто удивило, что Вы принудительно RW в единицу не загоняете
Раз. Два. Три.
Тут чётко видно, что RW в единице при чтении статуса, поэтому не пойму, о чём Вы говорите.
Burgunsky писал(а):Если Вас не затруднит, проясните сакральный смысл этого чудо-алгоритма
Это другое, просто поворот на 90 градусов. У KS0108, изначально использовавшемся мною, данные, посылаемые в дисплей, отображаются на нём в виде вертикальных столбиков, а у ST7920 - горизонтально. Поэтому такой кусок кода фактически поворачивает на 90 градусов данные. То есть, сначала данные (строка, например) пишутся в буфер fb размером 128 байт (128 вертикальных столбиков), после чего, для посылки в ST7920, этот буфер пересчитывается в горизонтальные байты.

Непосредственно к протоколу работы с ST7920, как таковой, этот код отношения не имеет.
Burgunsky писал(а):Пробовал выставлять задержку 100мкСек тупо после каждой команды. Результат идентичный
Достаточно и 50мкс, на самом деле.
Burgunsky писал(а):Подскажите, пожалуйста что не так в алгориртме ниже.
Навскидку, я не вижу переключения порта C с выхода на вход при попытке чтения. Поэтому непонятно, что именно вычитывается в буфер ABC, но точно не данные, которые выдаёт дисплей. Скорее, какое-то их наложение на то, что выдаёт сам МК на выход. И вопрос, кто кого "передавит" - выходные транзисторы МК или дисплея.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Пн апр 18, 2016 17:17:40

WiseLord писал(а):Навскидку, я не вижу переключения порта C с выхода на вход при попытке чтения.

Большое Вам спасибо. То, что Вам "на вскидку", мне 2 дня мучений. А причина настолько банальна... Даже не знаю как бороться с такой невнимательностью.
WiseLord писал(а):Раз. Два. Три.

Всё. Увидел. Почти весь аппаратный стек использовали.))
Не могли бы пояснить почему Вы пишете ST7920_CTRL_PORT |= ST7920_PSB;, вместо ST7920_CTRL_PORT = 1; , т.е. почему не используется обычный оператор присваивания ?

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Пн апр 18, 2016 17:56:48

ST7920_CTRL_PORT |= ST7920_PSB устанавливает один бит порта, не затрагивая остальные, а ST7920_CTRL_PORT = 1 устанавливает весь порт в 0x01, а другие биты этого порта у меня вообще-то тоже используется.

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

Если контроллер позволяет (имеет от 2кБ ОЗУ), гораздо интереснее с дисплеем работать через кадровый буфер. Данные (пикселы) пишутся не в дисплей, а в буфер в ОЗУ размером 1КБайт (128*64/8). А уже в дисплей данные попадают посредством таймера ~20кГц. Таймер вызывает раз в 50мкс прерывание, в котором из буфера берётся очередноё байт данных и кладётся в дисплей. Ну, или вызывается команда адресации, если пора переходить на другую строку. То есть, фактически, данные обновляются в фоне, полностью информация на дисплее обновляется где-то 18 раз в секунду. При этом это происходит как бы в фоне, без прерывания основной программы.

Вот моя реализация такого алгоритма. Она проще и компактнее обычного кода с задержками и при этом в разы быстрее.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Вт апр 19, 2016 16:04:49

WiseLord писал(а):ST7920_CTRL_PORT |= ST7920_PSB устанавливает один бит порта, не затрагивая остальные

Ясно. Я обычно в таких случаях битовые поля использую. Не знаю что там по производительности по сравнению с алгоритмом выше...
Если контроллер позволяет (имеет от 2кБ ОЗУ)

Ни разу не работал с такими крутыми. Это не фантастика? Да и вообще пока не представляю задачи по такой быстрой смене кадров. Мне сейчас надо показывать пару статичных картинок с расшифровкой последовательного сигнала, поступающего на вход контроллера.
Таймер вызывает раз в 50мкс прерывание,

Можно попробовать использовать алгоритм, в котором прерывание будет вызываться флагом BUSY повешенным на вход INT. Может дисплей быстрее умеет работать.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Вт апр 19, 2016 17:23:52

Burgunsky писал(а):Я обычно в таких случаях битовые поля использую

Интересно. Применительно к обычным переменным - не проблема:
Код:
typedef struct {
  bit0:1; bit1:1; bit2:1; bit3:1; bit4:1; bit5:1; bit6:1; bit7:1;
} myVar;
myVar var;
var.bit1 = 0;
var.bit2 = 1;

А вот как Вы применяете битовые поля к портам, а не переменным? Особенно, если для какой-то функционала используются разные биты разных портов?
Burgunsky писал(а):Ни разу не работал с такими крутыми. Это не фантастика?
Те же ATmega328, ATmega32 достаточно популярны.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Вт апр 19, 2016 19:58:53

Да нет. Я имел в ввиду предопределенные поля. Вот из хедера для PIC16F883:
Код:
typedef union {
    struct {
        unsigned RA0                    :1;
        unsigned RA1                    :1;
        unsigned RA2                    :1;
        unsigned RA3                    :1;
        unsigned RA4                    :1;
        unsigned RA5                    :1;
        unsigned RA6                    :1;
        unsigned RA7                    :1;
    };
} PORTAbits_t;
extern volatile PORTAbits_t PORTAbits @ 0x005;

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Пт июн 24, 2016 18:41:11

Что-то не въеду, как с этим дисплеем работать в Serial Mode. В даташите на 7920 про Serial Mode всего три с половиной странички, одна про передачу одного байта 24-битной посылкой, вторая - пример для 8051, третья - таблицы для времянки на передачу одного бита и половинка - сами времянки, и все. Негусто.

Как из этих байтов компоновать команды? Нужны ли паузы в передаче байтов? Нужно ли манипулировать сигналом CS ? Об этом в даташите ни слова.

То есть, конечно, догадываюсь, что надо соблюдать задержки, заявленные для 8-битной параллельной связи, но как там оно в деталях? Кто-то ведь разобрался?

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Ср июн 29, 2016 11:14:39

afz писал(а):Что-то не въеду, как с этим дисплеем работать в Serial Mode.
Я тоже по даташиту не въехал, потом как то где то подсмотрел и чтото получилось... со временем накидал свою библиотечку...

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

Либка получилась достаточно компактная, помоему около 1-2 кило, даже на мега8 можно легко развернуться...
Если будет не понятно как пользоваться, могу накидать примерчик...
Вложения
font8x8.h
(48.48 KiB) Скачиваний: 700

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Ср июн 29, 2016 18:12:51

Либка получилась достаточно компактная, помоему около 1-2 кило, даже на мега8 можно легко развернуться...
А почему вручную, дрыгая ножками? Я так прикинул, по идее должно получиться использовать аппаратный SPI. Там же заявлено 72 мкс между соседними байтами, и, как кто-то утверждал здесь раньше, можно "разогнать" его до 32-33 мкс, при большем разгоне появляются артефакты. Учитывая посылку одного байта 24 битами, чтобы обеспечить их передачу за 72 мкс нужна частота SCLK 333.3 кГц, увеличив ее до 666.7 кГц можно разогнать дисплейчик до 36 мкс. Я так думаю, что разгон "до упора" не есть хорошо, поэтому можно взять Мегу с кварцем, допустим, 7372.8 кГц, запустить ее аппаратный SPI с делителем 16, при этом получим 460.8 кГц SCK (SCLK), разгон при этом будет 52 мкс, т.е. порядка 1.4, при этом SPI, получив очередной байт, будет самостоятельно его обрабатывать в течение 128 тактов; спокойно можно делать в прерываниях, без всяких ожиданий.

Я не ошибаюсь?

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Ср июн 29, 2016 21:47:46

afz писал(а):А почему вручную, дрыгая ножками?
Наверное можно использовать и SPI, но меня устраивает и так... слишком уж много внимания и условий для решения по вашему варианту... тем более что на повышенных частотах некоторые дисплеи могут и не заработать...
Так же программный вариант избавляет от привязки к определенным выводам контроллера...

Кроме того, обновление экрана происходит в основном цикле (не мешая прерываниям) в следующих ситуациях - изменение положения курсора, обновление данных, изменение контекста и т.д.... т.е. довольно редко...
все остальное время контроллер полностью свободен...

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Чт июн 30, 2016 05:09:50

Кроме того, обновление экрана происходит в основном цикле (не мешая прерываниям) в следующих ситуациях - изменение положения курсора, обновление данных, изменение контекста и т.д.... т.е. довольно редко...
Тоже, конечно, вариант. Но я хочу попробовать обойтись без экранного буфера. Если подобрать изображения так, чтобы части, подлежащие изменениям, начинались по горизонтали с положения, кратного 16 точкам, то, вроде-бы, все должно получиться.
слишком уж много внимания и условий для решения по вашему варианту...
Каких условий? Всего-то надо подобрать частоту SCK, то есть при заданной частоте кварца выбрать коэффициент деления, чтобы SCK оказалась в пределах 333-666 кГц. Ну да, еще ножки привязаны. Аж целых две. Нет, даже две с половиной. :)

Хотя... Нам же не нужно показывать на этом экране полноценное видео. Поэтому и за сверхскоростью гнаться необязательно, 10 кадров в секунду, точнее, отрисовать кадр за 0.1 секунды, ИМХО, вполне достаточно. Поэтому, если Вы боитесь разгона, можно задать и 166-333 кГц. Если же разгона бояться не сильно, то диапазон еще шире - 166-500 кГц, ИМХО, вполне допустимо.

В общем так. За код спасибо, я из него достану не описанные в ДШ детали. Собственно, в таких делах кусок работающего кода с успехом заменяет многостраничные описания. К сожалению, орлы из Sitronix приложили код не на те действия, которые бы хотелось уточнить, ну а Ваш код - самое то.

Сочинять буду, скорее всего, на асме, если все заработает - выложу отчет.

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Чт июн 30, 2016 05:53:54

Я с этим дисплеем в SPI режиме не работал, но вот посмотрел на код сейчас и хочу спросить. Если в двух словах, то:
- для передачи команды 0bABCDEFGH передаём по SPI 0b11111000 0bABCD0000 0bEFGH0000
- для передачи данных 0bABCDEFGH передаём по SPI 0b1111010 0bABCD0000 0bEFGH0000

Правильно ли я понял суть?

И ещё, есть ли смысл по окончании передачи байта опускать CS, а по началу следующего - снова поднимать? Что будет, если держать его в 1 постоянно?

P.S. и вдогонку, по пинам:

PSB (единица в параллельном мрежиме) = PSB (ноль в последовательном)
RS (данные/команда в параллельном режиме) = CS (chip select в последовательном)
E (строб в параллельном режиме) = SCLK (тактирование в последовательном)
RW (запись/чтение в параллельнмо режиме = SID (вход данных в последовательном)

Так ли это? И что делать с D0-D7, занулить или можно оставить как есть?

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920

Чт июн 30, 2016 10:28:52

afz писал(а):хочу попробовать обойтись без экранного буфера.
Тоже вариант, по идее должно получится...
Тогда при печати отдельных символов скорость работы с дисплеем существенно увеличится...
Но при обновлении таким способом всего экрана скорость сильно упадет... т.к. для каждого байта данных нужно будет передавать команды позиционирования на дисплее...

WiseLord писал(а):- для передачи команды 0bABCDEFGH передаём по SPI 0b11111000 0bABCD0000 0bEFGH0000
- для передачи данных 0bABCDEFGH передаём по SPI 0b1111010 0bABCD0000 0bEFGH0000
Правильно ли я понял суть?
Ну да... вроде так...

WiseLord писал(а):И ещё, есть ли смысл по окончании передачи байта опускать CS, а по началу следующего - снова поднимать? Что будет, если держать его в 1 постоянно?
Пробовать надо... даже не помню, где и что по этому поводу говорилось... возможно что не нужно каждый раз дергать...

WiseLord писал(а):PSB (единица в параллельном мрежиме) = PSB (ноль в последовательном)
RS (данные/команда в параллельном режиме) = CS (chip select в последовательном)
E (строб в параллельном режиме) = SCLK (тактирование в последовательном)
RW (запись/чтение в параллельнмо режиме = SID (вход данных в последовательном)
Да так...

WiseLord писал(а):И что делать с D0-D7, занулить или можно оставить как есть?
Оставить как есть...

Изображение
Вложения
glcd-pinout.jpg
(81.98 KiB) Скачиваний: 2571
Ответить