Отображение символов на ЖК-дисплее с помощью микроконтроллера EFM8
Узнайте, как создавать персонажи с помощью редактора изображений и отображать их на ЖК-дисплее, управляемом микроконтроллером EFM8.
Введение
В предыдущей статье исследовалась функция SPI микроконтроллера EFM8 для отображения горизонтальной линии прокрутки на ЖК-дисплее размером 128 на 128 пикселей. В этой статье мы будем использовать тот же самый низкоуровневый интерфейс для обновления ЖК-дисплея со всеми прописными буквами алфавита; еще лучше, вы научитесь методам эффективного проектирования и отображения любого символа или символа, который может быть адекватно представлен 10 вертикальными пикселями и 8 горизонтальными пикселями.
Предыдущие статьи в этой серии
- Серия EFM8 от Silicon Laboratories: мощная новая встроенная платформа разработки
- Управление ЖК-дисплеем через SPI: введение в разработку проекта с помощью микроконтроллера EFM8
Требуемое оборудование / программное обеспечение
- Плата оценки SLFK2000A EFM8
- Интегрированная среда разработки Simplicity Studio
- Scilab
Обзор проекта
Цель состоит в том, чтобы проектировать и отображать все заглавные буквы на 128-на-128-пиксельном ЖК-дисплее. Текст печатается на ЖК-экране в типичном стиле текстового процессора: курсор отслеживает позицию, в которой будет отображаться следующий символ, и вы просто «набираете» нового символа, вызывая функцию InsertCharacter ().
Шрифт представляет собой набор символов с фиксированной шириной (и фиксированной высотой), созданный с помощью методов, описанных в следующем разделе. Размер фиксированного символа составляет 10 вертикальных пикселей на 8 горизонтальных пикселей (хотя символ фактически ограничен 9 на 7 пикселей, потому что пустые строки и пустой столбец включены для обеспечения разделения между соседними символами). Этот размер был выбран по нескольким причинам. ЖК-дисплей имеет ширину 128 пикселей, поэтому 8 горизонтальных пикселей гарантируют, что четкое количество символов будет соответствовать экрану. Мы используем 10 вертикальных пикселей вместо 8, потому что получающиеся более тонкие буквы несколько более приятны для глаз. Эти размеры также делают буквы, которые достаточно велики, чтобы быть легко разборчивыми, но достаточно маленькими, чтобы на ЖК-дисплее отображалось значительное количество символов за один раз. Однако, пожалуй, самая важная причина заключается в следующем: код для копирования данных пикселя из массива символов в буфер данных ЖК-дисплея намного проще с шириной в 8 пикселей, поскольку биты, представляющие состояния пикселей, выровнены с границами байтов. Это означает, что мы можем корректно обновлять данные ЖК-дисплея, используя чистые операции байта, вместо неудобных (и менее эффективных) бит-операций, в которых бит из одного байта должен быть скопирован в часть одного байта и часть другого байта.
Проектирование персонажей
Перевод визуальных символов в данные, совместимые с ЖК-дисплеем, является серьезным неинтуитивным процессом: кто мог бы нарисовать букву G, присвоив серию шестнадцатеричных значений байтовому массиву "// www.getpaint.net/index.html" target = "_ blank" > Paint. NET, мощное, но бесплатное приложение для редактирования изображений и фотографий.

Получите пустой холст и измените его размер до 10 пикселей в высоту на 8 пикселей в ширину и увеличьте масштаб до конца. Используйте инструмент «Карандаш», чтобы заполнить отдельные пиксели, пока буква не будет выглядеть правильно, а затем сохраните изображение в виде черно-белого файла.bmp.
Теперь настало время для Scilab, которую вы можете скачать здесь. Scilab - бесплатное программное обеспечение для численного расчета, аналогичное MATLAB. Как и в случае с MATLAB, Scilab полезен гораздо больше, чем хруст чисел. В этом проекте мы будем использовать его для анализа изображений символов и преобразования их в C-код, который мы можем скопировать и вставить в исходные файлы EFM8. В дополнение к самому Scilab вам нужно будет установить Image Design Design Toolbox; это легко осуществить с помощью диспетчера модулей ATOMS Scilab:

Самый простой способ использования Scilab - набирать отдельные команды в окне консоли. Все становится захватывающим, однако, когда вы начинаете комбинировать и организовывать эти команды с помощью текстового редактора SciNotes, который позволяет включать инструкции Scilab в когерентный файл исходного кода, который выполняется, как приложение, написанное на языке программирования высокого уровня. Вот некоторые из кода сценария SciNotes (LCD_image_handler.sce), используемого для этого проекта:
Код
ImageFilename = uigetfile(("*.bmp")); if(length(ImageFilename) == 0) break end CurrentImage = ReadImage(ImageFilename); CurrentImage = SegmentByThreshold(CurrentImage, 100); CurrentImage = flipdim(CurrentImage, 2); PixelData = uint8(zeros(10, 1)); for row = 1:10 for column = 1:8 if (CurrentImage(row, column) == %T) PixelData(row) = bitset(PixelData(row), column, 1); else PixelData(row) = bitset(PixelData(row), column, 0); end end end
Скачать код
LCD_image_handler.sce выполняется следующим образом: сначала открывается диалоговое окно файла; выберите файл.bmp, который вы хотите обработать.

Изображение преобразуется в черно-белое (в случае, если любые значения пикселей не равны 0 или 255), и каждый бит в 10-байтовом массиве устанавливается или очищается в зависимости от того, является ли соответствующий пиксель черным или белым. 10-байтовый массив представляет размер одного символа (т. Е. 10 вертикальных пикселей на 8 горизонтальных пикселей): один байт обеспечивает 8 значений горизонтального пикселя, и, следовательно, 10-байтовый массив содержит 10 строк, каждый из которых имеет 8 горизонтальных пикселей. Наконец, имя массива (которое берется из имени файла) и данные пикселя выводятся в консоль Scilab с помощью подпрограмм printf (). Этот процесс повторяется, пока вы не нажмете «отменить» в диалоговом окне файла.

Эти переменные определения могут быть скопированы и вставлены непосредственно в исходные файлы в нашем проекте EFM8. Сценарий также генерирует код, который используется для объявления этих переменных в заголовочном файле проекта, поэтому итоговый вывод выглядит следующим образом:

Как вы можете видеть, этот процесс эффективен и полностью гибкий. С помощью этого сценария SciNotes вы можете быстро создавать пиксельные данные, совместимые с ЖК-дисплеем, для любого символа, который вы можете нарисовать в виде изображения из 10 строк на 8 столбцов.
Порт ввода-вывода
Конфигурация ввода-вывода портов идентична той, что мы использовали в предыдущем проекте SPI.

Сигналы SPI отображаются на соответствующие штырьки портов, за исключением сигнала выбора микросхемы, который мы приводим вручную через P0.1.
Периферийные устройства и прерывания
Настройка периферийных устройств и прерываний аналогична той, которую мы использовали ранее: SPI настроен для связи с ЖК-модулем, прерывания Timer2 регулируют частоту кадров, а Timer4 используется для коротких задержек. Единственное отличие состоит в том, что Timer2 настроен на частоту прерывания 5 Гц вместо 60 Гц. В этом проекте новое письмо печатается на ЖК-экране при каждом переполнении таймера2, а более медленная частота обновления упрощает наблюдение за символами до их перезаписывания.
Прошивка
В предыдущем проекте мы использовали режим однострочного обновления ЖК-дисплея: после выбора чипа с высокой логикой, EFM8 отправляет байт выбора режима, затем адрес линии, затем 128 бит данных пикселя. Передача завершается двумя фиктивными байтами, а выбор чипа возвращается к логическому минимуму. Этот режим подходит для нестандартных приложений, но новая прошивка отличается. Значения пикселей для всего ЖК-дисплея хранятся в одном двумерном массиве, и все эти биты данных передаются на ЖК-дисплей всякий раз, когда прерывание Timer2 сообщает прошивке обновлять дисплей. Другими словами, мы отправляем на ЖК-дисплей гораздо больше данных. (Примечание. В этой конкретной реализации микроконтроллер управляет только первыми 60 линиями ЖК-дисплея, а не всеми 128, поскольку для приложения доступно только 1024 байта ОЗУ, для массива, достаточно большого для всего ЖК-дисплея, потребуется 2048 байт Это ограничение легко устраняется в пользовательском дизайне, выбирая один из совместимых с кодом устройств EFM8 с 4352 байт ОЗУ.)
Со всеми этими дополнительными данными, идущими на ЖК-дисплей, имеет смысл использовать режим многострочного обновления; как следует из названия, этот режим позволяет нам обновлять значения пикселей для нескольких строк во время одной передачи SPI. Это означает, что нам нужен новый конечный автомат в процедуре прерывания SPI:

Другим важным дополнением к прошивке является функция, в которой данные пикселов из массивов, сгенерированных Scilab, вставляются в двумерный массив, который содержит данные пикселя для всего ЖК-дисплея:
Код
void InsertCharacter(unsigned char *LCD_Character) //the input to this function is a pointer to a pixel data array { unsigned char n; unsigned char row_pixel; unsigned char column_byte; //rows are handled on a pixel-by-pixel basis row_pixel = LCDCursor(ROW); //columns are handled on a byte-by-byte basis, because one character width is 8 bits column_byte = LCDCursor(COL); /*each byte from the pixel data array is copied to LCDDisplayData, starting with the current cursor position*/ for(n = 0; n < CHAR_HEIGHT; n+) { LCDDisplayData(row_pixel)(column_byte) = *LCD_Character; LCD_Character+; //point to the next byte in the array row_pixel+; //the next byte corresponds to pixel data for the next line } LCDCursor(COL)+; //move the cursor one character width to the right /*if the cursor has reached the end of the line, return the cursor to the far left and move it down by one character height*/ if(LCDCursor(COL) == NUM_LINE_DATA_BYTES) { LCDCursor(COL) = 0; LCDCursor(ROW) = LCDCursor(ROW) + CHAR_HEIGHT; if(LCDCursor(ROW) == NUM_LINES) //if the cursor has reached the end of the display area, LCDCursor(ROW) = 0; //return the cursor to the top line } while(UPDATE_LCD == FALSE); //wait here until Timer2 initiates an LCD update UPDATE_LCD = FALSE; UpdateAllLCDLines(); }
Скачать код
Если вы проверите приведенный выше код и прочитаете комментарии, вы сможете получить представление о том, как это работает. Обратите внимание, что эта подпрограмма обновляет массив данных пикселей на ЖК-дисплее и управляет позицией курсора.
Общая функциональность этого проекта состоит в том, чтобы повторно печатать все заглавные буквы, от А до Я, а затем от А до Я и так далее. Основной поток программы следующий:
- Микроконтроллер очищает ЖК-дисплей.
- Timer2 включен.
- Программа вводит бесконечный цикл и использует функцию InsertCharacter () для печати A, затем B, затем C и т. Д. На Z, а затем обратно в A снова.
- Функция InsertCharacter () (см. Вышеприведенную выдержку кода) обновляет массив данных пикселей на ЖК-дисплее, управляет курсором, ждет, пока Timer2 не установит флаг для обновления ЖК-дисплея, а затем инициирует обновление через функцию UpdateAllLCDLines ().
- Timer2 ISR устанавливает флаг обновления только в том случае, если переменная состояния SPI указывает, что интерфейс SPI неактивен. Это гарантирует, что функция InsertCharacter () не будет пытаться инициировать новую передачу SPI до завершения предыдущей передачи.
видео
Следующая статья в серии: Общение с микроконтроллером EFM8 через USB
Попробуйте этот проект сами! Получить спецификацию.