Можно ли сделать несколько проектов для дисплеев контроллера
Максимальное количество конфигурируемых соединений для устройств HMI можно найти в Information System TIA Portal, для большинства панелей Comfort и WinCC Advanced RT оно равно 8, для панелей серии Basic – 4.
Если же планируется подключение к большему количеству контроллеров, то надо ориентироваться на использование WinCC Advanced RT с подключением через OPC сервер или на WinCC Professional RT.
Но надо иметь в виду, что в этом случае дополнительно потребуется лицензия SOFTNET-IE S7, необходимая для подключения более 8 контроллеров S7 по сети Ethernet
Ограничение количества подключаемых к PLC HMI устройств
Есть ограничение на количество одновременно подключенных к контроллерам S7-1200 и S7-300 устройств HMI. Для S7-1200 рекомендуется подключать не более 2 устройств:
Для S7-300 ограничение точно не описано, но в зависимости от типа контроллера, количества тегов, сложности программы в контроллере, проблемы с передачей данных с контроллера могут начаться при 3 и более подключенных к S7-300 контроллеру панелей или компьютеров с HMI/SCADA. Для более мощных S7-400 и S7-1500 ограничения существенно выше, но все равно надо иметь в виду, что при большом количестве запрашиваемых тегов (производительность в секунду), проблемы с передачей информации с контроллера на устройства HMI также могут возникнуть.
Варианты подключения дополнительных устройств HMI:
Sm@rtServer
Преимущество такого варианта: клиенты не надо программировать. Недостаток варианта: на всех клиентах и сервере открыт один и тот же экран, одновременно можно управлять только с одной панели.
Варианты подключения дополнительных устройств HMI:
использование OPC UA
Преимущество этого варианта: на клиентах и сервере
возможны разные экраны и управлять одновременно могут
несколько операторов.
Недостаток решения: клиенты надо программировать.
При подготовке публикации использовались материалы и изображения SIEMENS AG
Обычно для вывода информации сигнального дисплея на HD44780 более чем достаточно. Но иногда нужно нарисовать картинку, график или хочется сделать красиво, с модными менюшками. Тут на помощь приходят графические дисплеи. Одним из самых простых и доступных является дисплей на контроллере KS0107 или аналоге. Например, WG12864A от Winstar. Сам дисплей вполне свободно достается, имеет довольно большой размер (диагональ около 80мм) и разрешение 128х64 пикселя. Монохромный. Цена вопроса 400-500р.
Итак, если взять тот, что у меня WG12864A-TGH-VNW то у него следующая распиновка:
К контроллеру (ATMega16 на Pinboard) я подключил все следующим образом.
Данные полностью легли на PORTA, а управление на PORTB. В качестве резистора подстройки контраста я взял многооборотный переменник, что так кстати стоит рядом для подобных случаев. Питание подсветки взял с колодки от дисплеяя. Благо там все уже готово, даже управление от транзистора есть :) Правда я ее просто включил.
Двое из ларца, одинаковых с лица. Адресация
Контроллер CS0107 он может организовать матрицу только 64х64. А у нас в дисплее вдвое большая 128х64. Значит стоят два контроллера. Один отвечает за правую половину экрана, другой за левую.
Он представляет собой этакую микросхему памяти, где все введенные данные отображаются на дисплее. Каждый бит это точка. Кстати, для отладки удобно юзать, выгружая туда разные данные, а потом разглядывая этот дамп). Карта дисплея выглядит так:
Байты укладываются в два контроллера страницами по 64 байта. Всего 8 страниц на контроллер.
Протокол обмена
Тут все просто, без каких либо изысков. Выставляем на линиях RW, DI что мы хотим сделать, линиями CS1 и CS2 выставляем к кому обращаемся. На шину данных выдаем нужное число и поднимаем-опускаем линию строба. Опа! Впрочем, есть одна тонкость. Для чтения данных строб нужно дернуть дважды, т.к. предварительно данные должны попасть в регистр-защелку. Для чтения же флага состояния такой изврат не нужен. Вот примеры временных диаграм для разных режимов.
И запись. Причем запись, в отличии от чтения, можно делать сразу в оба контроллера. Конечно одновременно писать данные в контроллер смысла имеет мало, разве что захочишь двойную картику получить :) А вот команды обычно пишут срзау в оба.
Временные диаграммы, т.е. сдвиг фронтов между собой по времени может быть разным у разных контроллеров. Где то быстрей, где то медленней. Но в целом 1мкс обычно хватает. В реале обычно меньше. Лучше поглядеть в даташите на конкретный контроллер (не дисплей, в ДШ на дисплей обычно редко есть описание самого контроллера). Там обычно есть таблица вида:
Система команд.
Она тут простейшая.
Инициализация дисплея элементарная, в отличии от HD44780, где надо переключать режимы, включать-выключать разные курсоры и отображения.
Надо после сброса задать начальные координаты (адрес точки и страница), значение скролинга (обычно 0) и включить отображение. При включении на дисплее может быть мусор. Поэтому отображение обычно включают после очистки видеопамяти.
У меня ициализация, по командам, выглядит так:
Ну и потом еще заливка сразу в оба контроллера.
Код
Итак, приступим к коду. Чтобы было наглядней я все операции с ногами расписал в виде макросов. Заодно будет гораздо проще все перенести на другую архитектуру. Просто написав другие макросы, не правя сам код :)
Весь код можно поглядеть в нашей кодосвалке:
lcd_wg128.h
lcd_wg128.c
Покажу тут лишь характерные моменты работы с дисплеем.
Записью команд и данных занимаются следующие функции:
Чтение слова состояния делать не стал. Т.к. дисплей работает весьма шустро, что на круг ожидания можно не уходить, а просто подождать несколько тактов. Собственно этих трех функций уже достаточно для работы :) Остальное все свистоперделки и удобства.
Вроде заливки экрана:
Или установки пикселя. Причем можно загонять его в трех режимах. Просто установить, стереть или инвертировать. Координаты задаются глобальные, а вычисление адреса идет в функции:
// Процедура установки пикселя. Т.к. пиксель часть байта, то надо сначала вычислить // Контроллер, потом страницу и нужный байт. Считать этот байт. Изменить в нем только один, // нужный, бит и вернуть его на место. // На входе координаты и режим обработки пикселя (вкл, выкл, переключение) void PIXEL(u08 x,u08 y,u08 mode) < u08 CSS, row, col, byte; u08 res,read; if(y>63) // Проверяем в каком контроллере искомый пиксель < CSS = 1<<CS2; // Если У больше 63 значит во втором. Выставляем 2й col = y-64; // И отнимаем смещение, чтобы не мешалось. >else < CSS = 1<<CS1; // Иначе контроллер у нас первый. col = y; // А смещения нет. >row = x>>3; // Делим Х на 8, чтобы получить номер страницы. byte = 1<<x%8; // А остаток от деления даст нам искомый бит, который мы задвигаем // и получаем нужную нам битмаску для модификации байта. SET_ADDR(row,col,CSS); // выставляем адрес read = LCD_RD_DATA(CSS); // Читаем данные (адрес при этом ++ аппаратно). switch(mode) // В зависимости от режима < case 0: // Clear < res = read &
byte; // Накладываем сбрасывающую (NOT) маску break; > case 1: // Invert < res = read ^ byte; // Накладываем инвертирующую (ХОR) маску break; >default: // Set < res = read | byte; // Накладываем устанавливающую (OR) маску break; >> SET_ADDR(row,col,CSS); // Повторно выставляем адрес. Т.к. чтение его исказило. LCD_WR_DATA(res,CSS); // Вгоняем туда результат нашей модификации. >
Но работа с пикселями медленная штука. Это же каждый надо считать, изменить, закинуть обратно. Куча мороки. На обновление всего экрана в попиксельном режиме уйдет прорва времени. Я подсчитывал, при полной загрузке проца только на это, на заливку попиксельно всего экрана уходит чуть ли не треть секунды.
Куда эффективней работать с дисплеем блоками. Т.е. берем и последовательно записываем сразу куски страниц, на глубину в несколько байт. Например, таким образом удобно рисовать текст. Правда при попиксельном выводе, когда текст попадает между страницами получается неудобно, приходится делать вдвое больше работы. Но все равно намного быстрей чем попиксельно. На порядок!
// Запись сразу блока. Удобно для вывода строк или картинок, постранично. // На входе страница Х и колонка У. А также длина блока и адрес откуда брать данные. u08 BLOCK(u08 x,u08 y, u08 len, u16 addr) < u08 CSS,i,col; if(y>63) // Сначала вычисляем нужные нам сегмент (чип) < CSS = 1<<CS2; col = y-64; >else < CSS = 1<<CS1; col = y; >SET_ADDR(x,col,CSS); // Ставим адрес // А дальше в цикле гоним байты. Не забывая увеличивать адрес, чтобы была выборка из // памяти. Счетчик, чтобы не сбиться со счета. И номер колонки, чтобы не вылезти за границы // И вообще понимать где мы находимся. for(i=0;i!=len;i++,addr++,col++) < if(64==col) // Попутно проверяем за границы выхода из сегмента < if(CSS == (1<<CS2)) // Если случилось, и у нас второй сегмент, т.е. конец < // страницы (уже второй в этой строке) return 128; // выходим с кодом ошибки (код больше разрешения экрана) >col=0; // Иначе же обнуляем счетчик колонок. И переключаем банку CSS = 1<<CS2; // Выбрав второй сегмент экрана SET_ADDR(x,col,CSS); // И выставив новый текущий адрес > LCD_WR_DATA(pgm_read_byte(addr),CSS); // Пишем туда данные прям из флеша (таблица символов). > return y+len; // Возвращаем координату увеличиную на размер блока. >
Блочный вывод легко превращается в текстовый вывод. Надо лишь совместить таблицу символов с печаталкой блоков. И гнать данные из флеша напрямую.
// Процедура вывода строки. На входе строка, и координаты. Х в страницах, а У в точках. void LCD_putc(u08 x,u08 y,u08 *string) < u08 sym; while (*string!='\0') // Пока первый байт строки не 0 (конец ASCIIZ строки) < if(127<y) // Проверяем за границу выхода за экран. Если вылезаем < // Вот тут, кстати, можно поиграть с числом, чтобы не рубило последний символ. y=0; // То обнуляем координату точки. x++; // Выставляем следующую строку if(x>7) break; // Если экран и вниз кончился - выход. >sym = *string-0x20; // Вычисляем из ASCII кода смещение в таблице символов. // Для русского языка и цифр надо условия добавить. Т.к. // таблица там не полная, не 255 байт. y = BLOCK(x,y+1,5,(u16)symboltable+sym*5); // Закатываем этот блок. string++; // Не забывая увеличивать указатель, > >
Для еще большего ускорения можно немного оптимизировать функции ввода вывода. Убрав из хвостов возврат сигналов в первоначальное положение. У меня они больше для красоты. Да чтобы на экране анализатора было лучше видно :)
Ну и чтение-модификацию-запись делать тоже большими блоками. Загоняя, скажем, страницу в буфер, правя его там и быстро выгружая обратно.
Ну и, традиционно, архив с примером. Сделано все на ATmega16 под WinAVR GCC на Pinboard
Спасибо. Вы потрясающие! Всего за месяц мы собрали нужную сумму в 500000 на хоккейную коробку для детского дома Аистенок. Из которых 125000+ было от вас, читателей EasyElectronics. Были даже переводы на 25000+ и просто поток платежей на 251 рубль. Это невероятно круто. Сейчас идет заключение договора и подготовка к строительству!
А я встрял на три года, как минимум, ежемесячной пахоты над статьями :)))))))))))) Спасибо вам за такой мощный пинок.
115 thoughts on “Работа с графическим дисплеем WG12864 на базе контроллера KS0107”
TFT так просто не обработаешь, под него нужен мощный контроллер, а лучше ПЛИС и видеопамять. Так что не все так просто.
Можно да, но его надо гдето в памяти держать. Тут получается килобайт только фреймбуфер.
Мощный то и не нужен, lpc2478 или lh79520 отлично справятся, только если хранить картинки нужно, то лучше прикрутить внешний nand мега на 4
Ди, нескромный вопросик, а с чем у тебя связана работа? :)
Я уже три года как безработный О_о
А последняя работа была какая?
Ди. Раз ты тут. Скажи своей жене чтобы она занялась моим заказом :) 701 вроде.
Последний раз я был наладчиком лабораторного оборудования. До этого наладчиком станков ЧПУ, а до этого я был студентом :)
Сегодня мы вернёмся к Atmega8, так как что-то у меня случилось с моей Atmega328. Но для наших задач нам вполне подойдёт и восьмая серия.
Сегодня мы попробуем подключить к нашему контроллеру дисплей уже графический цветной разрешением 320 на 240 точек, управляемый по восьмибитному параллельному интерфейсу, Дисплей выполнен с помощью модуля и управляется контроллером ILI9341.
Вообще, у данного контроллера дисплея существует несколько режимов подключения к управляющему микроконтроллеру, в том числе есть и SPI, но мне попался дисплей именно с прараллельным способом подключения, о чём я нисколько не жалею. С таким интерфейсом также немало дисплеев, но что обидно, очень мало информации по реализации кода для дисплеев именно с таким интерфейсом. Поэтому наша задача – данный информационный пробел устранить на корню.
Вот перечень режимов подключения
Включить тот или иной режим удаётся благодаря упралению уровнем на ножках IM3:IM0.
Судя по технической документации, контроллер ILI9341 может управлять 262000 разновидностями цветов.
Вот схема подключения дисплея к контроллеру
А вот так схема выглядит на практике
Мы видим также простенький стабилизатор, висящий на проводках, состоящий из микросхемы и конденсатора. Данный стабилизатор служит для подачи питания 3,3 вольта на модуль дисплея, так как такое напряжение для него также требуется. Некоторую информацию, возвращённую из контроллера дисплея мы будем отслеживать с помощью символьного дисплея 20х4, подключенного по интерфейсу i2c, который также мы видим на картинке.
А вот так выглядит модуль дисплея снизу
Мы видим ещё на борту данного модуля картоприёмник для карты Micro SD, которая подключается по интерфейсу SPI.
Также мы видим, что все контакты у дисплея подписаны, поэтому с подключением, я думаю сложностей не возникнет.
Первые снизу справа четыре ножки служат для того, чтобы общаться с картой памяти, поэтому они у нас свободные. Используем мы следующие ножки дисплея:
Управление контроллером дисплея происходит посредством команд или другими словами отправкой в определённый регистр определённых величин. В технической документации очень подробно расписаны все регистры, причём есть и краткий перечень команд регистров, а есть и подробный для каждой команды. Техническая документация на контроллер ILI9341 прикреплена внизу данной страницы. Сначала мы отправляем адрес регистра, а затем шлём параметры команды. Причём количество параметров в различных командах также различается, что накладывает некоторые трудности для создания универсальной функции отправки команды. Но ничего, что-нибудь придумаем.
У нас создан проект TFT9341. Проект вполне стандартный, подключены к нему наши библиотек, написанные на прошлых занятиях – это twi и lcdtwi.
Также мы создадим и подключим к проекту ещё 2 файла для библиотеки уже непосредственно нашего нового дисплея – это файлы ili9341.h и ili9341.c.
Вот так выглядит главный заголовочный файл main.h
В файле ili9341.h подключим
Ну и, как вы все знаете, чтобы любой дисплей подключить и его заставить что-то показывать, необходимо пройти определённую процедуру инициализации. По большому счёту это относится не только к дисплеям.
В файле ili9341.c подключим заголовочный файл и напишем каркас для функции инициализации дисплея
void TFT9341_ini ( void )
Не забываем на данную функцию добавить прототип в хедер-файле, а также напишем некоторые макроподстановки, которые нам потребуются в процессе работы с дисплеем
void TFT9341_ini ( void );
Я думаю, назначение каждого макроса объяснять нет смысла, так как всё ясно из наименований. Но если вдруг кому-то что-то непонятно, то посмотрите видеоурок, кликнув по картинке внизу страницы, там объяснение более подробное.
В следующей части нашего занятия мы попытаемся написать ещё некоторые важные функции для работы с контроллером дисплея, а также считать его идентификатор, что позволит нам убедиться, что мы работаем именно с таким контроллером.
Отличия не глобальны, а в остальном обе приведенные конструкции при условии исправных частей имеют гарантированную 100% повторяемость.
Конечно же я веду речь о доступном железе, которое производится в Китае именно для самодельных конструкций. С одной стороны это хорошо - в основном все китайские контроллеры рассчитаны на максимальный охват доступных матриц. Но следует обязательно отметить и тот факт, что не все 100% существующих матриц можно таким образом воплотить в проект. Имеется в виду, что есть и ряд матриц, которые нельзя назвать универсальными, взаимозаменяемыми и т.д. Встречаются и совсем нестандартные одиночки, но радует то, что их не так уж и много. Речь идет о матрицах с редко встречающимися интерфейсами, "поднять" которые бывает довольно затруднительно, а иногда и невозможно. К таким же трудно приживляемым можно смело отнести и матрицы с сугубо индивидуальными временнЫми характеристиками, которые были заложены в планшетах или нетбуках (где в первой жизни стояли эти матрицы). Не каждый контроллер способен выдать эти характеристики поскольку в подавляющем большинстве прошивки рассчитаны все таки на некие "усредненные" и унифицированные параметры. Контроллеры, которые ГИПОТЕТИЧЕСКИ могли БЫ корректно заработать с подобными матрицами - это те, что с "телевизором" на борту (будут ниже под спойлером). Т.е. те, в настройках которых есть пункт map LVDS, в котором есть хоть какая то возможность выбора из 16 заложенных параметров предустановок.
* на первый взгляд данный спойлер напоминает старый анекдот про студента-биолога, который выучил только тему про блох. Я примерно так же назойливо перевожу все сказанное к интерфейсу LVDS. Но это только на первый взгляд, потому что под предыдущим спойлером я ясно дал понять, что подавляющее большинство китайского железа для самоделок рассчитано на подключение матриц именно с этим интерфейсом. Именно LVDS можно подключить к подобному железу напрямую, а все остальные виды интерфейсов - только через переходники и адаптеры, которые если и существуют в природе, опять же ориентированы на преобразование каких угодно интерфейсов в LVDS. Применение других матриц с интерфейсом отличным от LVDS (а это RSDS, eDP, V-by-One, EPI, MIPI) обязательно приведет к дополнительным изысканиям и финансовым затратам. Отсюда такой акцент.
Еще раз повторюсь - речь идет об УНИВЕРСАЛЬНЫХ контроллерах именно для самоделок.
В Китае их производится огромное количество и все модели я не смогу охватить. Но среди всего разнообразия можно выделить несколько видов, с которыми успех более вероятен, чем с какими то редкими и экзотическими (но при этом все равно универсальными) контроллерами. В первую очередь я подразумеваю доступность массивов прошивок и наличие мало-мальски внятных мануалов.
На всякий случай поделю их на две группы:
КОНТРОЛЛЕРЫ ДЛЯ ПОСТРОЕНИЯ МОНИТОРОВ
Это означает, что контроллеры ведут себя именно как любой компьютерный монитор - "засыпают" при отсутствии сигнала на входе. Время засыпания - от 2 до 5 СЕКУНД.
- контроллер на чипе RTD2660H (или RTD2662) (программное обеспечение обозначено как PCB800099):
WH0802A – двухстрочный символьный дисплей на 8 знакомест со встроенным управляющим контроллером KS0066.
Разбираем назначение выводов дисплея.
По умолчанию подсветка у дисплея WH0802A-YGH-CT отключена. Чтобы ее включить, нужно проделать парочку нехитрых манипуляций, а именно – установить две перемычки и впаять токоограничительный резистор (смотри на фотке RK, JF и RA соответственно).
Вообще у контроллера дисплея есть так называемый флаг занятости – BF. Если флаг в 1 – контроллер занят, если в 0 – свободен. Вместо второй программной задержки можно читать флаг занятости и проверять, когда контроллер дисплея освободится. Но поскольку мы хотим быстро получить первые результаты, с флагом занятости будем разбираться потом.
//функция записи команды
void LcdWriteCom( unsigned char data)
ClearBit(PORT_SIG, RS); // устанавливаем RS в 0
PORT_DATA = data; // выводим данные на шину
SetBit(PORT_SIG, EN); // устанавливаем Е в 1
_delay_us (2);
ClearBit(PORT_SIG, EN); // устанавливаем Е в 0
_delay_us(40); void LcdWriteData( unsigned char data)
SetBit(PORT_SIG, RS); //устанавливаем RS в 1
PORT_DATA = data; //выводим данные на шину
SetBit(PORT_SIG, EN); //устанавливаем Е в 1
_delay_us (2);
int main( void )
while (1);
return 0;
>
Здесь нет сложных мест, все должно быть понятно. Идем дальше.
Любой ЖК-дисплей перед использованием нужно инициализировать. Процесс инициализации обычно описан в datasheet`е на контроллер дисплея. Но даже если там и нет информации, последовательность, скорее всего, будет такая.1. Подаем питание
2. Ждем >40 мс
3. Подаем команду Function set
DL – бит установки разрядности шины
0 – 4 разрядная шина, 1 – 8 разрядная шина
N – бит установки количества строк дисплея
0 – однострочный режим, 1 – двухстрочный режим
F – бит установки шрифта
0 – формат 5*8, 1 – формат 5*11
* - не важно что будет в этих битах
4. Подаем команду Display ON/OFF
D – бит включения/выключения дисплея
0 – дисплей выключен, 1 – дисплей включен
C – бит включения/выключения курсора
0 – курсор выключен, 1 – курсор включен
B – бит включения мерцания
0 – мерцающий курсор включен, 1 – мерцающий курсор выключен
5. Подаем команду Clear Display
6. Ждем > 1,5 ms
7. Подаем команду Entry Mode Set
I/D – порядок увеличения/уменьшения адреса DDRAM(ОЗУ данных дисплея)
0 – курсор движется влево, адрес уменьшается на 1, 1 – курсор движется вправо, адрес увеличивается на 1
SH – порядок сдвига всего дисплея
0 – сдвига нет, 1 – сдвиг происходит согласно сигналу I/D – если он 0 – дисплей сдвигается вправо, 1 – дисплей сдвигается влево
Читайте также: