Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
-
Novice user
- Мудрый кот
- Сообщения: 1704
- Зарегистрирован: Вт янв 05, 2016 10:14:25
- Откуда: поселок Мелеуз
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
а какова максимальная скорость вывода графики ST7920 на весь экран в режиме SPI?
в смысле сколько "кадров" в секунду...
в смысле сколько "кадров" в секунду...
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Думается, те же ~20 кадров в секунду будут, что и при параллельном интерфейсе. Тут не протокол ограничивает скорость. Нужно (из опыта) выжидать около 50мкс после операции записи (в даташите будет даже больше, надо смотреть). А за это время данные любым протоколом загнать не проблема.
-
Novice user
- Мудрый кот
- Сообщения: 1704
- Зарегистрирован: Вт янв 05, 2016 10:14:25
- Откуда: поселок Мелеуз
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Более 4 кадров в сек не получается,программный спай,как перехожу на аппаатный дисплей вообще молчит,буду рыть гугл...
-
taratik
- Встал на лапы
- Сообщения: 83
- Зарегистрирован: Пт авг 03, 2007 11:46:17
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Оказалось кстати на него не так уж и сложно рисовать. Здесь есть подробная инструкция http://tehnopage.ru/vyvod-kartinki-na-displey-128x64
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Тоже сделал либу для данного дисплея с использованием экранного буфера в ОЗУ - 1 кб.
С выводом текста, вертикальных и горизонтальных линий, а так же выводом картинок.
Вывод в дисплей - по параллельному интрефейсу, отправка в таймере каждые 50 мкс.
И столкнулся буквально сегодня с тормозным дисплеем.
Так дисплей отказался рисовать картинку нормально при паузе в 50 мкс между отправками.... Нормально завелся аж при 68 мкс....
Хотя предыдущий работал без артефактов на 37 мкс паузах.... Вот такие пироги
С выводом текста, вертикальных и горизонтальных линий, а так же выводом картинок.
Вывод в дисплей - по параллельному интрефейсу, отправка в таймере каждые 50 мкс.
И столкнулся буквально сегодня с тормозным дисплеем.
Так дисплей отказался рисовать картинку нормально при паузе в 50 мкс между отправками.... Нормально завелся аж при 68 мкс....
Хотя предыдущий работал без артефактов на 37 мкс паузах.... Вот такие пироги
- afz
- Опытный кот
- Сообщения: 744
- Зарегистрирован: Сб дек 22, 2012 08:17:42
- Откуда: Караганда, Казахстан
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
А ее можно где-нибудь увидеть?goldenandy писал(а):Тоже сделал либу для данного дисплея с использованием экранного буфера в ОЗУ - 1 кб.
Ну, так не зря в ДШ заявлено 72 мкс - при такой паузе изготовитель гарантирует работоспособность. А все, что меньше - типичный оверклок, может и заработать, но не обязано.goldenandy писал(а):И столкнулся буквально сегодня с тормозным дисплеем.
Так дисплей отказался рисовать картинку нормально при паузе в 50 мкс между отправками.... Нормально завелся аж при 68 мкс....
Хотя предыдущий работал без артефактов на 37 мкс паузах.... Вот такие пироги
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Озадачился я с этим экранчиком, уж прям не знаю как быть.
Захотелось мне поделку, да с экраном помордастее. Остановившись на обычном ЖК, выбрал китайский как относительно недорогой за 6уе ST7920 12864 93х70мм(видимые 72х40мм).
Не без недостатков, уж очень большой, но по фоткам видно можно обпилить лишнее.
Решил всётаки заказать(по очередной распродаже, раньше всё равно денег не было, на прошлых другим барахлом закупился).
Ну и чтоб время не терять вспомнил о протеусе.
Под дня потратил чтоб заставить работать библиотеку. Как оказалось LCD12864A.dll md5: 86BE444AA4B60E359C29CD9F066E5979 с Proteus 8 не работает вообще, после этоже и нагуглилось.
Были подозрения что есть и другие версии, но начал перебирать архивы и контрольные суммы, и библиотека всётаки одна и работает только в 7 версии.
Тут я попытался купить этот экран в росии, но обломался, их нет. Тыкаясь по гуглу, магазины с подобным так и не нашлись. Разок натыкался, но на синий, оно мне не надо.
Забросив это на пару недель, поставил Proteus 7.10 (что оказалось не так то просто, комп к этому был не готов).
Имея 3 примера с разных сайтов, они начали работать как надо, выдавая картинку на экран в симуляторе.
Накидал схемку на ардуино U8glib_Arduino-1.19.1, там где к экрану 3 проводка, и облом, экран не кажет.
Подумал на кривой код, но я же готовый пример впихнул. Присмотрелся, а в примерах соединение параллельное.
Получается что этот симулятор мало того что только в старой версии проги работает, так ещё и только в паралельном режиме.
Как это паралелить я уже не знаю, выдрать какие ноги цеплять из исходника, мне както не очень удавалось. Даже не знаю может ли U8glib так работать, на гуглокоде ничего толком не понять, и вообще этот ресурс давно закрыт.
Попытки нагуглить готовое под ардуину тоже не нашлись.
Может коты подскажут как разрулить.
Проще всего подождать экран и живьём.
Но хотелось бы уже с чегото начать, хотябы рисовать значки.
Если можно тем же способом подключить паралельно для симулятора, а потом просто чуть подправить код освободив ноги, то вариант сгодился бы, да не знаю как.
Можно было и параллельный режим оставить, наверняка он быстрее, а я всё равно хочу несколько МК поставить, а этим только экран таскать.
В итоге всё упирается в то, что экран показывает мусор и библиотека вылетает
Захотелось мне поделку, да с экраном помордастее. Остановившись на обычном ЖК, выбрал китайский как относительно недорогой за 6уе ST7920 12864 93х70мм(видимые 72х40мм).
Не без недостатков, уж очень большой, но по фоткам видно можно обпилить лишнее.
Решил всётаки заказать(по очередной распродаже, раньше всё равно денег не было, на прошлых другим барахлом закупился).
Ну и чтоб время не терять вспомнил о протеусе.
Под дня потратил чтоб заставить работать библиотеку. Как оказалось LCD12864A.dll md5: 86BE444AA4B60E359C29CD9F066E5979 с Proteus 8 не работает вообще, после этоже и нагуглилось.
Были подозрения что есть и другие версии, но начал перебирать архивы и контрольные суммы, и библиотека всётаки одна и работает только в 7 версии.
Тут я попытался купить этот экран в росии, но обломался, их нет. Тыкаясь по гуглу, магазины с подобным так и не нашлись. Разок натыкался, но на синий, оно мне не надо.
Забросив это на пару недель, поставил Proteus 7.10 (что оказалось не так то просто, комп к этому был не готов).
Имея 3 примера с разных сайтов, они начали работать как надо, выдавая картинку на экран в симуляторе.
Накидал схемку на ардуино U8glib_Arduino-1.19.1, там где к экрану 3 проводка, и облом, экран не кажет.
Подумал на кривой код, но я же готовый пример впихнул. Присмотрелся, а в примерах соединение параллельное.
Получается что этот симулятор мало того что только в старой версии проги работает, так ещё и только в паралельном режиме.
Как это паралелить я уже не знаю, выдрать какие ноги цеплять из исходника, мне както не очень удавалось. Даже не знаю может ли U8glib так работать, на гуглокоде ничего толком не понять, и вообще этот ресурс давно закрыт.
Попытки нагуглить готовое под ардуину тоже не нашлись.
Может коты подскажут как разрулить.
Проще всего подождать экран и живьём.
Но хотелось бы уже с чегото начать, хотябы рисовать значки.
Если можно тем же способом подключить паралельно для симулятора, а потом просто чуть подправить код освободив ноги, то вариант сгодился бы, да не знаю как.
Можно было и параллельный режим оставить, наверняка он быстрее, а я всё равно хочу несколько МК поставить, а этим только экран таскать.
В итоге всё упирается в то, что экран показывает мусор и библиотека вылетает
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Ребята, а никто не пытался либу Вадиматорчика в кокосе запустить?
Добавлено after 4 hours 51 minute 51 second:
Интересует возможность использования HAL, так как большая часть проекта написано на HAL.
Добавлено after 4 hours 51 minute 51 second:
Интересует возможность использования HAL, так как большая часть проекта написано на HAL.
-
MikhailBMW
- Родился
- Сообщения: 4
- Зарегистрирован: Ср авг 05, 2020 23:40:20
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Народ, игрался я с этим индикатором, решил поделиться опытом новичка (пробую на зуб и STM32 и графические экраны, от нокии 3310, от семена А52 и этот вот), может кому пригодиться
1: к вопросу о количестве кадров: на STM32f103 самопальной библиотеке (не без кусков кода уважаемого Вадиматоричика) с программным SPI получилось 25 FPS с учетом того, что часть времени тратится на сбор информации с АЦП (мои хотелки).
2; на скорость работы контроллера экрана можно влиять - в даташите временные интервалы задержек сигналов не просто указаны, а указаны с поправкой на частоту работы самого ST7920 - а именно 540кГц. при этом есть график зависимости тактовой частоты контроллера от задающего резистора. при 5В питания должен быть впаян 33кОм. вся штука в том, что мой экран с Али пришел с резистором 27кОм, но когда я ткнул в эти цепи осциллографом, то увидел что там всего 408кГц. наши братья из Китая опять что-то нахитрили. В итоге я впаял резюк на 20кОм и частота выросла до 460кГц. по затратам времени на отрисовку всего экрана (а мерял я программно счетчиком тактов ядра МК STM32) без мусора на экране смог построить картинку не за 2,3 миллиона тактов как сначала а уже за 1,8 миллиона (частота МК 56МГц). дальше подымать частоту ST7920 не пробовал, хотя по даташиту максимальная частота контроллера экрана 600кГц. при текущей скорости обновления уже мылятся пиксели.
еще одна засада с этим экраном: хотя он и работает с сигналами STM32 - 3,3В, при этом от питания в 3,3В работать отказался, пока я 5В не подал, думал что с Али прислали труп. (при этом тогда еще про замену резистора и не помышлял). хотя по даташиту на ST7920 питание от 2,7В. такой вот небольшой опыт.
1: к вопросу о количестве кадров: на STM32f103 самопальной библиотеке (не без кусков кода уважаемого Вадиматоричика) с программным SPI получилось 25 FPS с учетом того, что часть времени тратится на сбор информации с АЦП (мои хотелки).
2; на скорость работы контроллера экрана можно влиять - в даташите временные интервалы задержек сигналов не просто указаны, а указаны с поправкой на частоту работы самого ST7920 - а именно 540кГц. при этом есть график зависимости тактовой частоты контроллера от задающего резистора. при 5В питания должен быть впаян 33кОм. вся штука в том, что мой экран с Али пришел с резистором 27кОм, но когда я ткнул в эти цепи осциллографом, то увидел что там всего 408кГц. наши братья из Китая опять что-то нахитрили. В итоге я впаял резюк на 20кОм и частота выросла до 460кГц. по затратам времени на отрисовку всего экрана (а мерял я программно счетчиком тактов ядра МК STM32) без мусора на экране смог построить картинку не за 2,3 миллиона тактов как сначала а уже за 1,8 миллиона (частота МК 56МГц). дальше подымать частоту ST7920 не пробовал, хотя по даташиту максимальная частота контроллера экрана 600кГц. при текущей скорости обновления уже мылятся пиксели.
еще одна засада с этим экраном: хотя он и работает с сигналами STM32 - 3,3В, при этом от питания в 3,3В работать отказался, пока я 5В не подал, думал что с Али прислали труп. (при этом тогда еще про замену резистора и не помышлял). хотя по даташиту на ST7920 питание от 2,7В. такой вот небольшой опыт.
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
[uquote="afz",url="/forum/viewtopic.php?p=3696334#p3696334"]
Обещанного три года ждут
Посему - некропостинг - лучше поздно, чем никогда.
st7920.h
st7920.c
И некоторые размышлизмы по подключению - вот тут...
А ее можно где-нибудь увидеть?[/uquote]goldenandy писал(а):Тоже сделал либу для данного дисплея с использованием экранного буфера в ОЗУ - 1 кб.
Обещанного три года ждут
Посему - некропостинг - лучше поздно, чем никогда.
st7920.h
Спойлер
Код: Выделить всё
#ifndef _DISPLAYDRIVER_7920_BLOCK_
#define _DISPLAYDRIVER_7920_BLOCK_
/*****************************************************************************************
Драйвер для взаимодействия с дисплеем на контроллере ST7920
Особенность данного контроллера - пауза между посылками команд и слов данных.
Согласно документации - пауза 72 мкс.
По факту на некоторых дисплеях можно добиться работоспособности вплоть до 35мкс.
Для минимизации потребления процессорного времени алгоритм отправки данных
в дисплей реализован через периодический вызов процедуры внутренней синхронизации
с периодичностью 72мкс. От основной программы требуется только периодический вызов
процедуры синхронизации, например, из прерывания таймера. Остальные действия по отправке
данных на экран будут прозрачны для основной программы.
*****************************************************************************************/
/*****************************************************************************************
ВНИМАНИЕ! В данном драйвере отсутствуют процедуры физического общения с дисплеем!
Эти процедуры должны быть описаны отдельно.
Это 2 процедуры - одна отвечает за управлением пином RST дисплея,
вторая - за отправку одного или двух байт данных/команды в дисплей.
Как будет реализована такая отправка - ногодрыгом, через аппаратный SPI на ожиданиях/прерываниях/DMA
и т.д. - драйвер не знает.
Для работы с дисплеем предоставлены 2 процедуры - очистки дисплея и включения/выключения пикселя.
Вся остальная работа выполняется в процедуре обслуживания, которую необходимо вызывать из
основноай программы с периодичностью 72мкс.
*****************************************************************************************/
#include <stdint.h>
//_______________________________________
/******** Процедуры физического взаимодействия МК с дисплеем ********/
/******** Процедуры должны быть реализованы в основной программе ********/
extern void ST7920_setResetLevel(uint8_t resetLevel);
// установка уровня Reset. При инициализации железа начальный уровень - высокий.
extern void ST7920_sendData(uint8_t dataBuf[], uint8_t count, uint8_t dataFlag);
// Установка флага данные/команда (dataFlag), отправка count байт данных из буфера dataBuf в дисплей
// _______________________
// Параллельное подключение дисплея
// (Вывод PSB через 4к7 подключен к питанию)
// --------------------------------------
// 1. На линии RS выставляется признак данных/команды - флаг dataFlag (1-данные, 0-команда)
// 2. Линия R/W прижата к общему прводу, мы данные из дисплея не читаем
// 3. Через время не менее 10 нс* строб E переводится в 1.
// 4. На выводах D0-D7 выставляются данные.
// 5. Через не менее чем через 140 нс после поднятия строб E переводится в 0.
// При этом данные на D0-D7 должны присутствовать на шине не менее чем за 40нс до опускания строба.
// 6. После опусания строба данные на шине и сигнал R/S должны присутствовать без изменений еще 20 нс
// _______________________
// Последовательное подключение дисплея
// (Вывод PSB подключен к общему проводу)
// --------------------------------------
// Линия RS выступает как сигнал CS - Chip select, idle-уровень - низкий, активный - высокий.
// Линия E остается сигналом строба (CLK), активный уровень низкий, idle - высокий
// Линия R/W - данные (DATA).
// Данные считвываются с линии DATA в момент перехода CLK из низкого уровня в высокий.
// AVR.SPI:
// SPCR.CPOL=1 (SCK is high when idle, Leading edge is falling),
// SPCR.CPHA=1 (Sample on trailing edge)
// Первый такт CLK должен начинаться не ранее чем через 60 нс* после активации CS.
// Сигнал CS снимается не ранее, чем через 60 нс после заднего фронта CLK
// Байт данных передается в дисплей за 24 такта CLK (передача 3х байт)
// Период сигнала CLK - не менее 600 нс ( 1.66(6) МГц), длительность низкого и высокого уровней - не менее 300 нс
// Данные на линии DATA должны быть выставлены минимум за 40 нс до перехода CLK из низкого в высокий уровень
// и должны там удерживаться еще не менее 40нс
// 1. Выставить высокий уровень CS.
// 2. Последовательно передать 3 байта:
// 2.1. Первый байт: 1 1 1 1 1 RW DC 0
// DC - признак данных или команды, 1-данные, 0-команда
// RW - 0-запись данных (мы данные из дисплея не читаем)
// Итого: 0xF8 - для команды, 0xFA - для данных
// 2.2. Второй байт: D7 D6 D5 D4 0 0 0 0
// 2.3. Третий байт: D3 D2 D1 D0 0 0 0 0
// 3. Выставить низкий уровень CS.
// _______________________
// * 1 такт AVR при 8 МГц = 125 нс, при 16 МГц = 62,5 нс
// ** SPI clock - проверялось на 1, 1.125, 1.25, 1.5, 1.75 МГц. На 2МГц завелось с мусором, на 2.25 МГц не завелось.
//_______________________________________
/******** Процедуры управления дисплеем ********/
void ST7920_init(void);
// Установка флага необходимости сброса и инициализации дисплея.
// Сампроццесс сброса и инициализации пройдет в процессе периодических вызовов процедуры внутренней синхронизации
void ST7920_reInit(uint8_t clearRAM);
// Установка флага необходимости переинициализации контроллера дисплея без подачи сигнала сброса.
// Очиста видеопамяти - опционально
void ST7920_sync(void);
// Процедура внутренней синхронизации, должна вызываться с периодичностью 72 мкс.
uint8_t ST7920_getIdleFlag(void);
// процедура проверки статуса обновления, возвращает 1, если все данные на дисплее обновлены.
//_______________________________________
/******** Процедуры вывода графики ********/
void ST7920_clearDisplay(void);
// очистка видеопамяти
void ST7920_putPixel(uint8_t x, uint8_t y, uint8_t color);
// вывод пикселя в видеопамять. color ==1 - пиксель будет зажжен, ==0 - погашен
#endif //_DISPLAYDRIVER_7920_BLOCK_
Спойлер
Код: Выделить всё
#include "st7920.h"
#include <string.h>
typedef enum {
dpOff = 0,
dpReset1,
dpReset2,
dpInit1,
dpInit2,
dpInit3,
dpScanChanges,
dpSetRow,
dpSendCol,
dpSendData
} displayPhaseType;
// режимы дисплея
static volatile displayPhaseType displayPhase = dpOff;
// организация видеопамяти - 32 строки по 16 слов.
// Итого 256*32 - как принято в архитектуре ST7920
// При этом левый блок 128*32 - верняя часть реального дисплея, правый - нижняя часть.
// так сделано для оптимизации вывода, ибо он должен происходить максимально быстро.
static volatile uint16_t videoram[32][256/16];
// массив флагов с признаками необходимости обновления обновления
static volatile uint8_t updateFlags[32];
// просто константы
static const uint8_t masks[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
// флаг наличия обновлений
static volatile uint8_t needUpdate = 0;
#define AS_DATA 1
#define AS_COMMAND 0
void ST7920_init(void){
displayPhase = dpReset1;
}
void ST7920_reInit(uint8_t clearRAM){
if (clearRAM) memset((void*)videoram, 0x00, sizeof(videoram));
memset((void*)updateFlags, 0xFF, sizeof(updateFlags));
displayPhase = dpInit1;
}
void ST7920_sync(void){
static uint16_t delay = 0;
static uint8_t data[2];
static uint8_t row = 0;
static uint8_t col = 0;
if (delay) {
delay--;
return;
}
switch (displayPhase) {
case dpOff:
return;
//break;
case dpScanChanges:
if ( !needUpdate ) return;
if ( row == 0 ) needUpdate = 1;
while (row<32) {
if (updateFlags[row]) {
// нужно обновлять данные в дисплей....
col = 0;
displayPhase = dpSetRow;
updateFlags[row] = 0;
break;
}
row++;
} // while row < 32
if (displayPhase == dpScanChanges) {
if (row == 32) {
row = 0;
if (needUpdate==1) needUpdate = 0;
}
break;
} // if (displayPhase == dpScanChanges)
// break; - тут брейк не нужен, мы нашли неотправленные данные и едем их отправлять
case dpSetRow:
case dpSendCol:
if (displayPhase == dpSetRow) data[0] = 0x80 | row;
else data[0] = 0x80; // col == 0
ST7920_sendData(data, 1, AS_COMMAND);
displayPhase++;
break;
case dpSendData:
data[0] = ((uint16_t)videoram[row][col])>>8;
data[1] = videoram[row][col] & 0xFF;
ST7920_sendData(data, 2, AS_DATA);
col++;
if (col==16) displayPhase = dpScanChanges; // если дошагали до конца строки - возвращаемся к сканированию.
break;
case dpReset1:
memset((void*)videoram, 0x00, sizeof(videoram));
memset((void*)updateFlags, 0xFF, sizeof(updateFlags));
needUpdate = 2;
ST7920_setResetLevel(0);
delay = 1000; // 72 ms - 1000 * 72 us = 72 ms
displayPhase++;
break;
case dpReset2:
ST7920_setResetLevel(1);
delay = 50; // 3.6 ms - 50 * 72 us = 3.6 ms
displayPhase++;
break;
case dpInit1:
case dpInit2:
case dpInit3:
switch ((uint8_t)displayPhase) {
case dpInit1:
data[0] = 0x30; // Standard mode
break;
case dpInit2:
data[0] = 0x01; // Clear text display
break;
case dpInit3:
data[0] = 0x36; // Enter extended mode
break;
}
ST7920_sendData(data, 1, AS_COMMAND);
delay = 100; //100 * 72 us = ~7.2 ms
displayPhase++;
row = 0;
col = 0;
break;
} // switch (displayPhase)
}
void ST7920_clearDisplay(void){
// очистка видеопамяти
memset((void*)videoram, 0x00, sizeof(videoram));
memset((void*)updateFlags, 0xFF, sizeof(updateFlags));
needUpdate = 2;
}
void ST7920_putPixel(uint8_t x, uint8_t y, uint8_t color){
uint16_t xMask;
uint8_t xIndex;
if (x > 127 || y > 63) return;
y &= 0x3F;
xIndex = x/16;
x = 15-(x & 0x0F);
if (y>31) xIndex += 8;
y &= 0x1F;
xMask = masks[x & 0x07];
if (x>7) xMask <<= 8;
uint16_t vRam = videoram[y][xIndex];
if (color) videoram[y][xIndex] |= xMask;
else videoram[y][xIndex] &= ~xMask;
if (vRam == videoram[y][xIndex]) return;
updateFlags[y] = 1;
needUpdate = 2;
}
uint8_t ST7920_getIdleFlag(void){
return needUpdate==0 || displayPhase==dpOff;
}
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Подскажите, пожалуйста, а как можно вывести символ или строку шрифтом 8х8 (например, из font8x8.h Вадиматоричик`а) без использования буфера? Что-то никак не допру, как это сделать...
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Pretender, выодить построчно, по одному байту. Каждый раз задавая адрес.
- lizard66
- Первый раз сказал Мяу!
- Сообщения: 35
- Зарегистрирован: Чт май 14, 2015 16:58:00
- Откуда: Kharkiv
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
[uquote="Pretender",url="/forum/viewtopic.php?p=4016041#p4016041"]Подскажите, пожалуйста, а как можно вывести символ или строку шрифтом 8х8 (например, из font8x8.h Вадиматоричик`а) без использования буфера? Что-то никак не допру, как это сделать...[/uquote]
Без буфера слишком хлопотно. Индикатор заполняется фрагментами строк по 16 бит, это шире символа 8х8, придется зачитывать фрагмент строки из индикатора и «сливать» с изображением, которое уже присутствует. ST7920 позволяет зачитать буфер только в параллельном режиме.
Без буфера слишком хлопотно. Индикатор заполняется фрагментами строк по 16 бит, это шире символа 8х8, придется зачитывать фрагмент строки из индикатора и «сливать» с изображением, которое уже присутствует. ST7920 позволяет зачитать буфер только в параллельном режиме.
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
lizard66, в последовательном тоже можно читать вроде бы. Во всяком случае, бит чтения-записи там есть.
Каждый байт команды/данных в последовательном режиме отправляется тремя байтами. И первый байт как раз и содержит биты-указатели, команда или данные идут и чтение или запись производится : 1 1 1 1 1 RW DC 0
Но читать, а потом писать - это геморно. При том, что еще и дисплей тормозной, одну команду или байт данных пережевывает минимум 70 (а то и все 80-90) микросекунд. Если по последовательному протоколу слать, то тактовую выше 1.666 МГц вроде нельзя подавать.
Я тестировал - 1.75 МГц он еще проглотил, а на 2 МГц уже пошли артефакты.
Если в применении к АВРкам, то тут грустно. Аппаратный СПИ при тактовой 8 МГц - это или 1, или 2 МГц. Нам подходит только 1 МГц.
Либо ставить на АВР кварц 12 МГц. Тогда СПИ можно на 1.5 МГц раскочегарить.
В результате эти циклы чтения-записи будут отбирать на ожидания вагон времени. И для основной программы останется ресурсов всего ничего.
Pretender,
Уж лучше (если это мега 8, у которой всего 1 кб ОЗУ) - выделить себе буфер на 8 строк пикселей, принтануть шрифт в этот буфер и потом выплюнуть буфер в дисплей.
Вот тут - http://avrprog.blogspot.com/2013/12/lcd ... 920-8.html есть описание представления памяти и команды.
Ну и плюс я для себя собрал в одном месте нюансы по подключению. Ибо не покидают меня эти дисплеи. Вроде распихал в всякие изделия, ан нет, еще один лежит.
Каждый байт команды/данных в последовательном режиме отправляется тремя байтами. И первый байт как раз и содержит биты-указатели, команда или данные идут и чтение или запись производится : 1 1 1 1 1 RW DC 0
Но читать, а потом писать - это геморно. При том, что еще и дисплей тормозной, одну команду или байт данных пережевывает минимум 70 (а то и все 80-90) микросекунд. Если по последовательному протоколу слать, то тактовую выше 1.666 МГц вроде нельзя подавать.
Я тестировал - 1.75 МГц он еще проглотил, а на 2 МГц уже пошли артефакты.
Если в применении к АВРкам, то тут грустно. Аппаратный СПИ при тактовой 8 МГц - это или 1, или 2 МГц. Нам подходит только 1 МГц.
Либо ставить на АВР кварц 12 МГц. Тогда СПИ можно на 1.5 МГц раскочегарить.
В результате эти циклы чтения-записи будут отбирать на ожидания вагон времени. И для основной программы останется ресурсов всего ничего.
Pretender,
Уж лучше (если это мега 8, у которой всего 1 кб ОЗУ) - выделить себе буфер на 8 строк пикселей, принтануть шрифт в этот буфер и потом выплюнуть буфер в дисплей.
Вот тут - http://avrprog.blogspot.com/2013/12/lcd ... 920-8.html есть описание представления памяти и команды.
Ну и плюс я для себя собрал в одном месте нюансы по подключению. Ибо не покидают меня эти дисплеи. Вроде распихал в всякие изделия, ан нет, еще один лежит.
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
GoldenAndy, у меня тренировочный PIC16F877A c 368 байт ОЗУ и доступна она не вся, а 96 байт только
Т.е. в принципе, если работать с таким дисплеем, нужно подбирать под него подходящий МК с достаточным для буфера объемом ОЗУ...
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Pretender, ну смотрите.
Память дисплея представлена в виде массива 32 строки по 256 пикселей, сгруппированых по 16 пикселей.
Есть 2 команды, установить вертикальный адрес, установить горизонтальный адрес.
И если вертикальный адрес произвольно устанавливается на любую строку (0..31), то на горизонтальный адрес устанавливается только кратный 16. Ибо на установку горизонтального адреса отведено 4 бита на всю строку из 256 пикселей.
При этом если горизонтальный адрес от 0 до 7 - данные попадают в верхнюю часть дисплея, если от 8 до 15 - то на 32 пикселя ниже (см. описание представления памяти дисплея).
Т.е. если выводить последовательно строку на дисплей и дальше забыть, что вы ее вывели - можете выводить сразу по два символа. Если нужно вывести один символ - то вы можете его вывести, но в позицию по горизонтали, кратную 16 пикселям.
Как по мне - если дисплей чисто для текста, то сделать буфер 16 байт - для строки символов. Печатать в него, а потом выводить буфер на дисплей построчно. Или, если есть возможность, взять МК чуть потолще. Ибо 368 байт ОЗУ - это грустно на данное время.
(Хотя и сам в основном делаю устройства на тех контроллерах, которые уже куплены, а не те, что идеально подходят под задачу)
Память дисплея представлена в виде массива 32 строки по 256 пикселей, сгруппированых по 16 пикселей.
Есть 2 команды, установить вертикальный адрес, установить горизонтальный адрес.
И если вертикальный адрес произвольно устанавливается на любую строку (0..31), то на горизонтальный адрес устанавливается только кратный 16. Ибо на установку горизонтального адреса отведено 4 бита на всю строку из 256 пикселей.
При этом если горизонтальный адрес от 0 до 7 - данные попадают в верхнюю часть дисплея, если от 8 до 15 - то на 32 пикселя ниже (см. описание представления памяти дисплея).
Т.е. если выводить последовательно строку на дисплей и дальше забыть, что вы ее вывели - можете выводить сразу по два символа. Если нужно вывести один символ - то вы можете его вывести, но в позицию по горизонтали, кратную 16 пикселям.
Как по мне - если дисплей чисто для текста, то сделать буфер 16 байт - для строки символов. Печатать в него, а потом выводить буфер на дисплей построчно. Или, если есть возможность, взять МК чуть потолще. Ибо 368 байт ОЗУ - это грустно на данное время.
(Хотя и сам в основном делаю устройства на тех контроллерах, которые уже куплены, а не те, что идеально подходят под задачу)
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Что-то не пойму. Вот функция вывода картинки на дисплей из массива, записанного в память программ (работает нормально у меня)
Получается, горизонтальный адрес кратен 8. Как-то с адресацией не совсем понятно. Попробую воспользоваться вашим советом...
Возможность есть заменить на другой. Просто к этой плате разработки был пример от китайцев как работать с этим дисплеем в текстовом режиме. А весь интерес работать с ним именно в графическом режиме, получается. В процессе разбора стало понятно, почему с данным МК китайцы привели пример только в текстовом режиме 
Спойлер
Код: Выделить всё
void GLCD_display(unsigned char code *addr)
{
int i,j;
//*******display top half screen
for(i=0;i<32;i++) //
{
TransferData((0x80 + i),0); //SET VERTICAL ADDRESS
TransferData(0x80,0); //SET HORIZONTAL ADDRESS
for(j=0;j<16;j++)
{
TransferData(*addr,1);
addr++;
}
}
//*******display bottom half screen
for(i=0;i<32;i++) //
{
TransferData((0x80 + i),0); //SET VERTICAL ADDRESS
TransferData(0x88,0); //SET HORIZONTAL ADDRESS
for(j=0;j<16;j++)
{
TransferData(*addr,1);
addr++;
}
}
}
СогласенИли, если есть возможность, взять МК чуть потолще. Ибо 368 байт ОЗУ - это грустно на данное время.
- GoldenAndy
- Поставщик валерьянки для Кота
- Сообщения: 1925
- Зарегистрирован: Чт июл 28, 2016 07:58:37
- Откуда: Kyiv, UA
- Контактная информация:
Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
нет, горзонтальный адрес кратен 16 пикселям. Просто засылка данных побайтово идет. Что параллельная шна 8 бит, что последовательная работает с байтом.
Смотрите.
Установка горзонтального адреса - команда 1000АААА - тут АААА - 4 бта выбора горз. адреса, от 0 до 15 (0..F). И эти 0..15 охватывают все 256 пикселей. Т.е. 1 единичка гориз. адреса отвечает за 16 пикселей. Первые 128 пикселей (адрес 0..7 - верхняя часть дисплея), вторые (8..15) -нижняя.
Ваш тестовый код.
Сначала идет установка вертикального адреса (выбор строки - от 0 до 31).
Потом TransferData(0x80,0); //SET HORIZONTAL ADDRESS
0х80 == 10000000 - стартуем с нулевого блока пикселей.
И засылаем туда 16 байт данных - 128 бит. Как раз верхняя строчка. Если засылать без смены адреса дальше - то следующая информация появится в не в нулевой, а в трицать второй строке. Это нам пока не надо, ибо под такой вывод надо хитро готовить картинку.
Переходим к первой строке и таке далее, 32 строки по 128 бит.
Второй цикл.
Все тоже самое, но горизонтальный адрес устанавливается
TransferData(0x88,0); //SET HORIZONTAL ADDRESS
0х88 == 10001000 - стартуем с восьмого блока пикселей.
1 блок - 16 пикселей. 8*16 = 128. Т.е. мы будем слать данные в нулевую строку, но со 128-й позиции. А это, согласно модели дисплея - нижний блок дисплея. И так - 32 раза.
----
Вдогонку. Я предпочитаю с дисплеями, у которых пиксель занимает меньше байта, работать через промежуточный буфер. Ибо, зажечь пиксель, не имея информации о соседях - тяжело. Практыческы нэвазможно ©
И так сложилось, что первые поделия были на АТМеге32, где памяти 2 кб, а потом на СТМках... (там удобнее реализовывать физическое взаимодействие по ДМА).
Так что все же лучше остановиться на буфере. Тогда там можно рисовать линии, фигуры и т.д.
Смотрите.
Установка горзонтального адреса - команда 1000АААА - тут АААА - 4 бта выбора горз. адреса, от 0 до 15 (0..F). И эти 0..15 охватывают все 256 пикселей. Т.е. 1 единичка гориз. адреса отвечает за 16 пикселей. Первые 128 пикселей (адрес 0..7 - верхняя часть дисплея), вторые (8..15) -нижняя.
Спойлер

Сначала идет установка вертикального адреса (выбор строки - от 0 до 31).
Потом TransferData(0x80,0); //SET HORIZONTAL ADDRESS
0х80 == 10000000 - стартуем с нулевого блока пикселей.
И засылаем туда 16 байт данных - 128 бит. Как раз верхняя строчка. Если засылать без смены адреса дальше - то следующая информация появится в не в нулевой, а в трицать второй строке. Это нам пока не надо, ибо под такой вывод надо хитро готовить картинку.
Переходим к первой строке и таке далее, 32 строки по 128 бит.
Второй цикл.
Все тоже самое, но горизонтальный адрес устанавливается
TransferData(0x88,0); //SET HORIZONTAL ADDRESS
0х88 == 10001000 - стартуем с восьмого блока пикселей.
1 блок - 16 пикселей. 8*16 = 128. Т.е. мы будем слать данные в нулевую строку, но со 128-й позиции. А это, согласно модели дисплея - нижний блок дисплея. И так - 32 раза.
----
Вдогонку. Я предпочитаю с дисплеями, у которых пиксель занимает меньше байта, работать через промежуточный буфер. Ибо, зажечь пиксель, не имея информации о соседях - тяжело. Практыческы нэвазможно ©
И так сложилось, что первые поделия были на АТМеге32, где памяти 2 кб, а потом на СТМках... (там удобнее реализовывать физическое взаимодействие по ДМА).
Так что все же лучше остановиться на буфере. Тогда там можно рисовать линии, фигуры и т.д.
Спойлер

Re: Графический дисплей LCD 12864 (128x64 пикселя) на ST7920
Вот, теперь понятно стало... Я вот, кстати, ваши записи изучал, было бы это там сразу - не было бы подобных вопросов... Спасибо!
Так вот тоже еще проблема - если вывести этот небольшой буфер, а как погасить остальную область экрана?Ибо, зажечь пиксель, не имея информации о соседях - тяжело.


