хм я иной алгоритм надумал,как получу ЖКИ - опробую мне надо крупные шрифты, от 16 точек
Если нужно выводить шрифт с шириной кратной 8-ми тачкам (8,16,24,32), то буфер не нужен... можно выводить прям в дисплей... Но если будут шрифты с шириной не кратной 8-ми, то придется через буфер.....
Рад, что этот дисплей приобрел такую популярность. Есть даже статья на хабре http://habrahabr.ru/post/213459/. Попытался по ней написать нормальную библиотеку для работы по SPI. Но столкнулся с проблемой. Если подать "0" (-) на SPB (Для разрешения приема данных) вся цепь замыкается. У меня питается от программатора, так что гаснет все. Программатор в том числе. У кого-нибудь еще такое было? И еще. На дисплее по ссылке GND и VCC, по сравнению с мои дисплеем, на разных местах. Я об этом узнал уже после того, как подключил и цепь замкнулась. Даже и не подумал, что пины могут отличаться по назначению. Видимо, не судьба с SPI мне поработать... Спасибо за примеры. Буду стараться написать еще более компактный код
У меня такая-же беда. Купил дисплеи в Китае специально под Serial режим... Удалось победить?
Все, разобрался. На плате уже установлена перемычка...
хм я иной алгоритм надумал,как получу ЖКИ - опробую мне надо крупные шрифты, от 16 точек
Если нужно выводить шрифт с шириной кратной 8-ми тачкам (8,16,24,32), то буфер не нужен... можно выводить прям в дисплей... Но если будут шрифты с шириной не кратной 8-ми, то придется через буфер.....
сел делать, ан фиг вам, товарищи
во-первых, идиотская адресация. Победил: сделал по Х 0-7 блоков, и по Y 0-7 - строк дело в том, что выгрузить просто 8*8 в любое место не получится простыми способами. По горизонтали запись ведётся * + 8 бит. Т.е., можно вывести только в левую часть блока. Или два символа сразу. А вывести по-простому в правую -никак Это пол беды, в памяти небольшой буфер + анализ соседнего символа и сразу два выводить. Сносно но меня в тупик поставило вот что: есть в памяти программ массив с данными шрифтов. Как обратиться к началу нужного символа? как адресоваться туда?
есть в памяти программ массив с данными шрифтов. Как обратиться к началу нужного символа? как адресоваться туда?
Создается указатель, указывающий на начало массива, потом к нему нужно прибавить (порядковый номер нужного символа в массиве, умноженный на значение размерности символов в массиве), вот вам и начало нужного символа...
есть в памяти программ массив с данными шрифтов. Как обратиться к началу нужного символа? как адресоваться туда?
Создается указатель, указывающий на начало массива, потом к нему нужно прибавить (порядковый номер нужного символа в массиве, умноженный на значение размерности символов в массиве), вот вам и начало нужного символа...
вот: шрифты сам рисовал, в свободных сделал пару десятков ходовых символов: батарея заряжена, половина, разряжена, всякие пиктограмки: вход\выход в меню, стрелочки,.... на одной из фотографий пиктограмка вилки мол, питание от сети 220в можно всё сделать, была бы фантазия!
эффект Bold сделан программно из обычного шрифта: смещаю на 1 позицию всю строку
Карма: 1
Рейтинг сообщений: 21
Зарегистрирован: Пн май 16, 2011 10:54:32 Сообщений: 299 Откуда: Красноярск
Рейтинг сообщения:2
Здравствуйте все . Ну вот, я снова вернулся в эту тему. Мне нужно было время, чтобы немного в себе разобраться, переосмыслить многие вещи, подтянуть свои знания в СИ и разобраться с STM8 и 32. Предыстория: СпойлерИзучая новое семейство STM32 я понял, что такая мощность мне ни к чему, да и питаются они только лишь от 3.3 вольта, что влечет за собой применение устройств согласования уровней при подключении многих модулей, а это дополнительные расходы, что в быту бывает критично. Хотелось что-нибудь с пользовательским интерфейсом. Хоть в STM32 и есть LTDC (Модуль управления RGB дисплеями без контроллера) с DMA2D (встроенный графический ускоритель с возможностью самостоятельно рисовать различные фигуры на экране) + на моей отладочной плате еще был экран 240*320, но слишком он уж сложен в освоении да и для домашних поделок это перебор. + не для каждого проекта захочется покупать контроллер за 500 руб. И тут я начал смотреть в сторону STM8. Контроллеры с виду очень понравились, а как только начал с ними работать - так на всегда для себя решил отказаться от AVR. Хоть STM8 чуть-чуть и уступают в производительности, но зато отлаживать программы на них - одно удовольствие, но да ладно. Как вы уже поняли, я начал разбираться с нашим LCD заново. Т.к. в интернете я не нашел ни одного упоминания подключения нашего LCD по SPI к STM8, то я решил написать библиотеку сам. И, забыв про все грабли, начал писать. В конце этого сообщения есть файл проекта с моей библиотекой и примером. Библиотека сейчас активно дорабатывается и в будущем будет прикреплена к какой-нибудь RTOS. Связь STM8 и LCD по SPI: СпойлерТ.к. у меня нет логического анализатора и я никогда ранее не работал с этим дисплеем по SPI, то реализовать интерфейс я решил "дрыганьем ножек" с большой задержкой и подключенными светодиодами к пинам, чтобы проследить, что все биты доходят нормально (После успешного соединения перевел на аппаратный SPI. В библиотеке есть обе реализации). Как я писал ниже - мне досталась старая версия дисплея, и чтобы перевести его из параллельного в SPI - мне пришлось перепаять резистор (перемычку, как оказалось). Иначе происходило замыкание при правильном подключении. Далее я начал читать эту статью, из которой я подчеркнул подключение дисплея и принцип передачи. Но возникли определенные проблемы: 1. В статье написано:
Цитата:
В SPI режиме передача одной команды или 1 байта данных происходит при передачи 24 бит Протокол передачи данных таков: Устанавливаем высокий уровень CS Передаем 4 единицы подряд Передаем 1 бит RW – чтения или запись Передаем 1 бит RS – Команда или данные Передаем 0 Передаем 4 бита старшей половины байта данных Передаем 4 нуля Передаем 4 бита младшей половины байта данных Передаем 4 нуля подряд Устанавливаем низкий уровень CS
Как оказалось, нужно передать сначала 5 единиц подряд, а не 4. 2.
Цитата:
Передаем 4 бита старшей половины байта данных
Непонятно было, передавать со старшего к младшему или от младшего к старшему. Оказалось, что нужно передавать именно со старшего к младшему: 7 бит, 6 бит, 5 бит, 4-й, четыре нуля, 3-й, 2-й, 1-й, 0-й, снова 4 нуля. На этом проблемы с подключением закончились. Библиотечная реализация соединения (низкий уровень). СпойлерЗа инициализацию SPI отвечает функция SPI_Init();. Причем их в библиотеке 2. Та, которая закомментирована - программная (медленная), 2-я аппаратная с делителем частоты f\8 (при частоте встроенного генератора в 16 мгц), использует 2 линии (выход и тактирование, вход отключен для экономии выводов (Это, несомненно, + STM8)) + CS так же "ногодрыг" (изменяется в ручную). При такой аппаратной конфигурации экран полностью обновляется в режиме картинки примерно за пол секунды. За отправку байтов по SPI в LCD отвечает функция SPI_Out. Их тоже 2. Закомментированная так же программная, отправляет с 7-го бита по 0-й, как и аппаратная. За отправку байта данных или команды отвечает функция LCD_OUT. Она принимает 2 параметра: 1. Байт данных. 2. Комманда или данные. Есть в defin-ах.
Код:
#define Command 0 //Отправка комманды или данных. #define Data 1
Пример использования:
Код:
LCD_OUT(0x30, Command); //8 бит, стандартный набор комманд.
Использование стандартного шрифта. СпойлерДля начала LCD нужно инициализировать в текстовом режиме. Для этого служит библиотека LCD_TextStandart_Init();. Функция не требует входных параметров и вызывается перед использованием дисплея. Последовательность была взята из статьи выше. Для отправки строки используется функция LCD_OutString_std. Функция выводит входную строку до символа с кодом 0x00. Пример использования.
Код:
int main( void ) { Led_init(); SPI_Init(); LCD_TextStandart_Init(); LCD_OutString_std("Loooool)))"+0x00); while (1) {
} }
Вот как выглядит этот код в жизни (программный SPI). Сразу скажу, над этой функцией долго не работал, т.к. в своей практике использовать не буду. Использование собственных символов 8x8. СпойлерВ моем МК есть аж 2 кб ОЗУ, так что я решил сделать в памяти МК буфер для всего экрана, а после просто обновлять его. По-началу хотел делать без буфера, но адресация меня убила и я решил, что так будет куда проще (Да и в будущем все равно без буфера не обойтись). Для начала нужно инициализировать дисплей в режиме SPI. Делается это функцией без параметров LCD_Graf_Init();. Далее появится мусор на экране. Его можно очистить функцией LCD_Graf_Clear();. Вывод символов (которые лежат скачанные в отдельном файле) производится так, сначала функцией LCD_Graf_Out_char (символ, положение по оси x, положение по оси y) символ закачивается в буфер в нужном месте, далее функцией OUT_Graf_BUFFER на экран выводится весь буфер на экран. Если нужно вывести строку, то достаточно лишь вызвать функцию OUT_Graf_String ("строка"+0x00, координата 1-го символа по оси x, координата по оси y), после так же вывести буфер на экран. Если строка не поместилась в строку, то она автоматически продолжается с начала новой строки. Если строка не влезла в последнюю строку, то она продолжается с начала. Применяется кодировка размером 8x8, с русскими символами. Пример вывода символа и строки.
Можно и не дописывать 0x00 в конце, но я все таки делаю это. Работа с графикой: (Рисование линий). СпойлерЯ решил, что в будущем использую этот дисплей в связке с ОС реального времени, для чего мне нужен будет интерфейс пользователя. А для этого нужно уметь рисовать его. Решил начать с линий. Т.к. мне нужны будут лишь горизонтальные и вертикальные линии произвольной длинны, то я решил написать свой алгоритм (на что убил 2 дня). В библиотеке есть функция OUT_Graf_Line, она принимает 4 параметра. 1. Horiz (горизонтальная) или Vert (вертикальная) линия. Далее так. Если линия горизонтальная, то. 2. Отступ слева в пикселях (0...128). 3. Длинна пикселей вправо (включая 1-й пиксель). 4. Положение по оси Y (константа), так же от 0 до 63. Если линия вертикальная, то: 2. Отступ пикселей сверху (0...63). 3. Длинна вниз (0..64). 4. Отступ слева по оси X (0..128). Вот пример кода, рисующего прямоугольник с отступом в 1 пиксель от каждой грани экрана и надпись внутри него + символ.
Выглядит это так: Работа с графикой: (Рисование прямоугольников). СпойлерДля работы с прямоугольниками есть функция OUT_Graf_Prm, она имеет 4 параметра: координаты левого верхнего угла (х, у) и координаты правого нижнего угла (х, у). Значения для Х [0..128], Y [0..64]. Пример рисовки такого же прямоугольника, как на рисунке в примерах рисования линий.
Все, что функции пишут в буфер - происходит наложением. Так что если буква занимает ни все отведенное ей пространство 8x8, то там спокойно можно провести линию. Вот собственно и библиотека. Код написан на C, под IAR для контроллера stm8s105c4, но код не имеет ассемблерных вставок, так что перенос будет легкий
Глюки библиотеки: Спойлер1. При использовании стандартных символов, передача возможна лишь с помощью программной инициализации SPI. Скорее всего я просто не выдержал задержки при работе с контроллером символов. Т.к. я не использую стандартные символы вообще - мне не критично.
_________________ Все можно сделать, было бы желание!
Карма: 1
Рейтинг сообщений: 21
Зарегистрирован: Пн май 16, 2011 10:54:32 Сообщений: 299 Откуда: Красноярск
Рейтинг сообщения:2
Немного поработал над библиотекой и добавил несколько новых функций: Спойлер1. Теперь можно очистить буфер (ОЗУ) LCD. За это отвечает функция void OUT_Graf_BUFFER (void);, не требующая параметров. 2. Библиотека вынесена в отдельный файл (LCD12864.h и LCD12864.c). В 1-м файле (.h) вынесены заголовки всех функций с их небольшим описанием + необходимые #define, а во 2-м сами функции (С кучей комментариев). Для подключения к проекту нужно подключить оба файла к проекту. У меня они подключены так.
Код:
#include "inc\LCD12864.h" //Библиотека работы с LCD. #include "inc\LCD12864.c"
3. Работы с SPI так же в отдельных файлах SPI.h и SPI.c. Так же в .h описания и заголовки - во 2-м сами функции. Так же осталась аппаратная и программная реализация. По умолчанию раскомментирована аппаратная (железная). Их так же необходимо подключить к проекту (Раньше файлов библиотек экрана! Иначе не будет компилироваться.) 4. Добавлена функция копирования изображения любого размера (не больше размера экрана) из програмной памяти в ОЗУ, с возможностью выбора координат копирования и смещения рисунка по осям X и Y по пикселям (Это далось сложнее всего). Это делается с помощью функции void OUT_Graf_PasteJmeg (char x1, char y1, const char mes_name[], const char mes_set[]). Поясню как с ней работать. Параметр № 1. Смещение по оси Х. 2. Смещение по оси Y. 3. Имя массива картинки. 4. Имя массива информации о картинке. Пример работы с библиотекой. Допустим нам нужно нарисовать "рыбку" размером 8 на 16 пикселей, для этого: 1. Подготовка картинки: Спойлер1. Открываем программу Bitmap2Code, ссылка на которую есть в 1-м посте темы. 2. В графе image нажимаем на знак папки и добавляем свою картинку. Кстати, картинка обязательна по оси X должна быть кратна 8!. Так что если она занимает, к примеру, 5 символов, то нужно оставить до 8 пустое место (т.к. изображение накладывается, а не замещает, ничего страшного не произойдет). 3. В строке Name пишем на английском имя нашего массива. 4. В правом окне переворачиваем изображение на 90 градусов (Это какой-то прикол программы, иначе получается 2 рядом стоящих сплющенных изображения). 5. В пункте bit\point выбираем 1pbb. Все 3 галочки (Перевороты X, Y и RLE) должны быть сняты. 6. Далее нажимаем в левом окне на generate и получаем код. В верхнем окне получится что-то типа:
// Bitmap information for Kr const char KrffInfo [] = { 7, // Pictur высота - 1 15, // Picture ширина - 1 };
Советую вынести это в отдельный файл. Я, например, создал файл Resurs.h, и там храню изображения и информацию о них. Только не забудьте в начале проекта подключить его. 2. Настроить функцию. СпойлерДопустим нам захотелось, чтобы наша рыбка плавала по всему экрану, для этого делаем 2 цикла (в 1-м рыбка перемещается по оси у, а во 2-м по х). Таким образом рыбка будет плыть слева направо, сверху вниз, от и до строки. Вот пример моего кода.
Код:
int main(void) { Led_init(); SPI_Init(); LCD_Graf_Init(); while (1) { for (char DvY = 0; DvY < (64-8); DvY=DvY+8) //По оси У. Каждый раз спускаемся на 8 пикселей. { for (char DVx = 0; DVx<(128-16); DVx++) //По оси Х. Т.к. картинка 16 пикселей, то делаем отступ, иначе уплывет в никуда. { OUT_Graf_PasteJmeg(DVx, DvY, Kffr, KrffInfo); //Смещение по х, по y, имя массива картинки, имя массива параметров. OUT_Graf_BUFFER (); //Показываем буфер. Lcd_Clear(); //После каждого наложения чистим буфер. }; }; }; }
Вот так выглядит мой пример в жизни: Спойлер А вот картинка рыбки, если кто захочет свериться. Вот проект примера работы библиотеки:
Вложение:
Комментарий к файлу: Проект. 1.1.rar [281.26 KiB]
Скачиваний: 563
А вот и сама библиотека
Вложение:
Комментарий к файлу: Либа inc.rar [12.28 KiB]
Скачиваний: 593
Буду вводить уже им версии. Т.к. слишком уж большой функционал планируется. Так вот, это версия 1.1
А вот и видио работы кода. Спойлер
_________________ Все можно сделать, было бы желание!
Карма: 1
Рейтинг сообщений: 21
Зарегистрирован: Пн май 16, 2011 10:54:32 Сообщений: 299 Откуда: Красноярск
Рейтинг сообщения:2
Новая версия: 1.2 Новое: Добавлена возможность рисования закрашенных прямоугольников. За это отвечает функция void OUT_Graf_PrmZK (char X1, char Y1, char X2, char Y2);. Работа с ней ведется точно так же, как и с не закрашенным прямоугольником. Обновления: теперь свой текст (8x8) может быть 4-х видов.
Код:
//Режимы вывода символов. #define FonOFF_InversOFF 0 //Рисует на пустом месте белым по синему, фон не тронут. #define FonOFF_InversON 1 //Рисует пустым по закрашенному, фон не тронут. #define FonON_InversOFF 2 //Буква использует весь фон. Рисует по пустому. #define FonON_InversON 3 //Весь фон, рисует по закрашенному пустотой.
Данное изменение коснулось функции LCD_Graf_Out_char и OUT_Graf_String. Теперь помимо всех предыдущих входных параметров - нужно еще дописать формат вывода. Для демонстрации был написан небольшой примерчик. Здесь нижняя часть экрана закрашена прямоугольником и на обеих частях по 4 строчки текста, каждая из которых демонстрирует режим.
Карма: 1
Рейтинг сообщений: 21
Зарегистрирован: Пн май 16, 2011 10:54:32 Сообщений: 299 Откуда: Красноярск
Рейтинг сообщения:2
Цитата:
А я все не уймусь...
Небольшой рассказ, поясняющий изложенное в посте. СпойлерПосле написания последней выложенной функции я решил подключить сенсорный экран (Touchscreen (тачскрин)), для этого нужно было произвести настройку ADC, а далее - дело за малым. Решив, что сейчас у меня нет времени разбираться с архитектурой - я решил подключить std peripheral library. Хоть я и понимал, что она очень сырая и в ней много глюков - но хоть какой-то каркас кода лучше, чем ничего. И тут начались проблемы. 1. К IAR-у библиотека наотрез отказалась подключаться. Решал эту проблему около 2-х дней, но на 3-й день все же получилось чего-то добиться, но при этом понадобилось бы с НУЛЯ переписывать всю СВОЮ библиотеку, что меня взбесило и я решил попробовать другую среду. 2. Попробовав официальную IDE ST Visual Programmer в комплекте с COSMIC-ом, я понял, что Жизнь - боль. Обе среды мне не нравились с самого начала (Мой идеал (в нем работать просто одно божественное удовольствие) - keil5, но он не поддерживает STM8). Решив, что платформа пока еще развивается, а мне дорога каждая минута - я решил достать свою платку с STM32F429ZI и переписать библиотеку под него. Хоть этот контроллер и слишком огромен для такого экрана (МК спокойно тянет 32-х битные LCD экраны с разрешением 480*800 с кучей различных фич), но перенести программу на МК по-меньше после не составит труда. Итак, библиотека под STM32. Скажу сразу, пока что это лишь сырой порт, который, убив 2 дня жизни, мне удалось сделать. Функционал такой же, как и в версии 1.2. Но вот в использовании есть небольшие изменения. Спойлер1. Настройка SPI и GPIO происходит с помощью StdPeriph (Да, это громоздко, но пока что так. Неизвестно еще, может я на NXP перейду. А функционал нужно расширять). 2. По умолчанию передача идет через SPI4 (Их там аж 7!!!), для того, чтобы включить программный SPI - нужно в функции LCD_OUT строку SPI_Out_LCD12864_Ap поменять на SPI_Out_12864_Soft.
Код:
void LCD_OUT (uint8_t Data_LCD, uint8_t Np_LCD) { CS_ON(); //Передача начата. if (Np_LCD == Data) {SPI_Out_LCD12864_Ap(0xFA);} //Передача данных или комманды. else {SPI_Out_LCD12864_Ap(0xF8);} SPI_Out_LCD12864_Ap(Data_LCD & 0xF0); //Старшая половина и 4 "0". SPI_Out_LCD12864_Ap(Data_LCD << 4); //Младшая и 4 "0". CS_OFF(); //Передача окончина. }
А вместо SPI_LCD12864_Init_AP_SPI4 использовать для инициализации SPI_LCD12864_Init_Soft. Скорость выставлена в обоих реализациях SPI методом подбора так, чтобы при кварце в 8 Mhz (без умножителя), изображение приходило без артефактов (Смотрел от большей скорости к меньшей). От себя: был приятно удивлен, когда включил свой пример "рыбки" при той же скорости кварца, а код работал быстрее. Только потом вспомнил, что у STM8 и STM32 производительность 0.9 против 1.32 (Может чуть напутал в цифрах, лень лезть читать). Приятным плюсом так же оказалась совместимость уровней 3.3 и 5V (Но дисплей питается от 5!). Так что подключение прямое. Кстати о подключении:
Думаю, если что, изменить настройки нижнего уровня не составит труда. Вот файл проекта для Keil5. Буду выкладывать целыми проектами, т.к. только на согласование .c и .h файлов у меня ушел день.
Ну вот и фото (На нем можно увидеть светодиоды справа, так, выставляя гигантские задержки я отлаживал SPI). Теперь о скорости вывода. Она ОЧЕНЬ высокая. Если смотреть на мой пример, то видно, что при перемещении, между 2-мя изменениями еще видны "не остывшие" пиксели. Делать скорость еще выше я не вижу смысла, т.к. экран не успевает измениться между новыми порциями данных. Скоростью SPI - доволен. Фото Спойлер P.S. Пока ST не напишет нормальную IDE для STM8 - я буду работать над библиотекой под STM32, а учитывая тенденцию на снижение цен 32-х битных мк, возвращяться к 8 мне уже не придется.
_________________ Все можно сделать, было бы желание!
Карма: 1
Рейтинг сообщений: 21
Зарегистрирован: Пн май 16, 2011 10:54:32 Сообщений: 299 Откуда: Красноярск
Рейтинг сообщения:2
Смог соединить наш экран с тачскрином (ранее не работал с ним). Так вышло, что по ширине он на 1-2 пикселя меньше, а в высоту на 3 мм больше с каждой стороны. Так что пришлось писать библиотеку с учетом этого. Из-за SPL конечно опрос происходит ОЧЕНЬ медленно (Всего 2-3 обновления экрана в секунду), но пока что хватит. Вот фото: Библиотеку пока не выкладываю, ее ждет огромная оптимизация.
_________________ Все можно сделать, было бы желание!
Пока ST не напишет нормальную IDE для STM8 - я буду работать над библиотекой под STM32, а учитывая тенденцию на снижение цен 32-х битных мк, возвращяться к 8 мне уже не придется.
ST никогда не напишет... она вообще ни пишет ИДЕ... А так... ИАР вполне хватает... И по поводу восьмёрок... S003 для простых поделок очень даже ничего...
_________________ "Я не даю готовых решений, я заставляю думать!"(С)
Неделю назад тоже получил из китая пару таких дисплеев. Написал свою библиотеку под AVR. Пока только под параллельный 8-битный режим, но добавить 4-битный или последовательный вроде как несложно - протоколы там простые.
Основное моё требование к библиотеке было - совместимость со своей же KS0108-библиотекой. Это, в основном, использование пропорциональных (!) шрифтов с "вертикальными" байтами. Ограничение проистекает из необходимости добавить поддержку дисплея в свой проект спектроанализатора, где подобные шрифты уже используются с дисплеями на базе KS0108 и дисплеем LS020.
Ввиду использования ATmega16 полного экранного буфера (1кБайт) сделать не получалось, так что буфер немного упрощённый - 128 байт (8 строк длинной 128 пикселов), в который легко вписывается нужный шрифт. Буфер вычитывается из экранной памяти (GDRAM) при переходе на очередную "строку" из восьми.
Собственно, вот картинки с текущим результатом:
А исходники под avr-gcc, если кому интересно, можно глянуть на гитхабе.
Ввиду использования ATmega16 полного экранного буфера (1кБайт) сделать не получалось, так что буфер немного упрощённый - 128 байт (8 строк длинной 128 пикселов), в который легко вписывается нужный шрифт. Буфер вычитывается из экранной памяти (GDRAM) при переходе на очередную "строку" из восьми.
Тоже вариант, но к сожалению так полноценную ИДЕ (с окошками рамочками и прочими приколами) не сварганить... Хотя может и вариант, но значительно увеличится нагрузка на контроллер...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения