хм я иной алгоритм надумал,как получу ЖКИ - опробую мне надо крупные шрифты, от 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]
Скачиваний: 588
А вот и сама библиотека
Вложение:
Комментарий к файлу: Либа inc.rar [12.28 KiB]
Скачиваний: 618
Буду вводить уже им версии. Т.к. слишком уж большой функционал планируется. Так вот, это версия 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) при переходе на очередную "строку" из восьми.
Тоже вариант, но к сожалению так полноценную ИДЕ (с окошками рамочками и прочими приколами) не сварганить... Хотя может и вариант, но значительно увеличится нагрузка на контроллер...
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения