STM32F4: GNU AS: Подключение дисплея на PCD8544 (Часть 7)

от автора


Поскольку мигающим светодиодом интерфейс пользователя построить сложно, решил подключить к STM32F407 простенький SPI дисплей из Китая. Интерфейс дисплея PCD8544, подключение по SPI, на aliexpress и ebay обычно ищется по строке LCD nokia 5110, питание дисплея как раз от 2.7 до 3,3 вольт.
По информации полученной из даташита частота SPI дисплея не должна превышать 4 Мгц, однако все имеющиеся у меня экземпляры надежно работали при такте SPI в 21 Мгц…

Описание проекта, исходные тексты программы, настроенный файл автоматической компиляции и сборки проекта под «катом»:

в проект из шестой части публикации добавил работу с счетчиком тактов микроконтроллера DWT (честно взято с www.stm32asm.ru и переформатировано в модуль под раздельную компиляцию). Теперь в каталоге периферии микроконтроллера три модуля:

В корень проекта добавил папку devices — в нее планирую размещать модули подключаемых к микроконтроллеру устройств:

Из устройств самым необходимым сейчас являются FullHD монитор + PC клавиатура + Мышь простой LCD дисплей — чтобы можно было наконец получать информацию не с горящих светодиодов, а читая с экрана. Поэтому в папке devices появилась папка LCD со следующим содержимым:

Файл lcd_func.asm это модуль графических функций которые не зависят от «железа», в настоящий момент содержит в себе следующие функции:

@ *************************************************************************** @ *               МОДУЛЬ ДОПОЛНИТЕЛЬНЫХ ФУНКЦИЙ МОДУЛЯ LCD                  * @ *************************************************************************** @ * Процедуры:								    * @ *     LCD_PUTSTR:   Вывод строки по координатам:                          * @ *                   R0:Y, R1:X, R2:COLOR R4:ADR_TEXT                      * @ *                   Текст должен заканчиваться нулевым символом           * @ *                   Управляющий код: 0x01, .short Y, .short X, .word col  * @ *                                                                         * @ *     LCD_PUTHEX:   Вывод шестнадцатеричного числа:                       * @ *                   R0:Y, R1:X, R2:COLOR R4:HEXVal, R5:DigitCol           * @ *                                                                         * @ *     LCD_PUTDEC:   Вывод десятичного числа:				    * @ *                   R0:Y, R1:X, R2:COLOR R4:DECVal, R5:DigitCol           * @ *                                                                         * @ *     LCD_LINE:     Вывод линии:                                          * @ *                   R0:Y1, R1:X1, R2:COLOR R3:Y2, R4:X2                   * @ *                                                                         * @ *     LCD_RECT:     Вывод прямоугольника:                                 * @ *                   R0:Y1, R1:X1, R2:COLOR R3:Y2, R4:X2                   * @ *                                                                         * @ *  ПРИМЕЧАНИЕ !                                                           * @ *  - Все процедуры не портят регистры!                                    * @ *                                                                         * @ *  - допустимые координаты и шаг печати native процедурами определяются   * @ *    в файле lcd_param.inc который должен лежать рядом с файлом модуля    * @ *                                                                         * @ *  - Драйвер дисплея должен содержать функции определенные как .global:   * @ *    LCD_CHAR: (R0:Y, R1:X, R2:Color, R3:Char) - native вывод символа     * @ *    LCD_PIXEL: (R0:Y, R1:X, R2:Color)         - native вывод пиксела     * @ *                                                                         * @ *************************************************************************** 

Поскольку модуль планируется использовать для различных типов дисплея, то процедуры старался сразу написать в расчете на разнообразное применение, например, под кодирование цвета отвел 32 бита (регистр R2) — для монохромного дисплея конечно многовато (достаточно было одного бита), но вот для цветных дисплеев с 16-ти битной палитрой в самый раз.
Для рисования линий применил алгоритм Брезенхейма — могу сказать что ассемблер ARM в этом себя показал просто великолепно!!! возможность условного исполнения команд присваивания и арифметических действий сделала код рисования линии не намного большим процедуры вывода символа!
Вывод десятичного числа написан с использованием блока деления на 10 при помощи арифметики и сдвигов — тоже получилось очень компактно.
Файл настроек для модуля lcd_func.asm под драйвер дисплея pcd8544 выглядит пока так:

lcd_param.inc

@GNU AS @ *************************************************************************** @ *    Файл настроек для модуля дополнительных функций LCD (lcd_func.asm)   * @ *************************************************************************** @ *    Файл  настроек  сообщает  параметры  драйвера  дисплея  для  функци- * @ * онирования  библиотек дополнительных функций LCD,  это такие параметры, * @ * как: разрешение экрана по горизонтали и вертикали в графическом режиме, * @ * наличие native процедуры печати символов,  и возможность  их  печати  с * @ * точностью до пиксела, шаг вывода текста по X и Y для внешней  процедуры * @ * печати строк, и т.д.                                                    * @ *                                                                         * @ * файл настроек необходимо положить в папку с модулем lcd_func.asm  кото- * @ * рый их загрузит и будет использовать в своих функциях                   * @ *************************************************************************** @ @ Устройство: LCD SPI PCD8544 @  @ графические параметры дисплея .equ LCD_PARAM_pixel_present, 1 @ в драйвере есть процедура вывода точек LCD_PIXEL  .equ LCD_PARAM_size_px, 84	@ количество точек на экране по горизонтали .equ LCD_PARAM_size_py, 48      @ количество точек на экране по вертикали   @ текстовые параметры дисплея .equ LCD_PARAM_char_present, 1    @ в драйвере есть процедура печати букв LCD_CHAR  .equ LCD_PARAM_char_stepx,    7      @  - шаг текста по оси Х  .equ LCD_PARAM_char_stepy,    8      @  - шаг текста по оси Y 

еще не все параметры использую, отложил это до того момента как запущу еще какой нить дисплей (скорее всего это будет цветной SPI дисплей с aliexpress) — вот тогда и буду вводить дополнительные блоки условной компиляции в зависимости от типа дисплея.

В папке PCD8544 размещен драйвер дисплея, это 3 файла:

  • font6x8.inc — шрифт 6х8, немного страшненький, но зато рисовал сам, маленьких букв нет (не получаются они у меня), состоит из знаков, цифр, заглавных букв латинского и русского алфавита. За счет отсутствия маленьких букв — существует в виде двух блоков символов LCD_LAT_CHARS (64 символа) и LDC_RUS_CHARS (31 символ), всего 570 байт
  • lcd_param.inc файл настроек для lcd_func.asm, при использовании драйвера этот файл должен быть скопирован в одну с ним папку (что я и сделал — смотрите содержимое папки LCD приведенное выше)
  • lcd_pcd8544.asm драйвер дисплея. Содержит в себе процедуру инициализации дисплея (LCD_INIT), процедуру очистки буфера (LCD_CLEAR), процедуру обновления экрана содержимым буфера (LCD_REFRESH), процедура рисования пиксела (LCD_PIXEL), процедура вывода символа (LCD_CHAR). В последней процедуре решил немного по «выпендриваться» и сделал вывод символов с точностью до пиксела (причем не через попиксельный вывод каждой точки)

Еще раз повторю: никаких дополнительных функций (вывод числа, вывод строки, вывод линии) в драйвер намеренно не вмещал — это функции от железа не зависящие.

Как всегда самое сложное — это написать демонстрацию возможностей получившихся модулей… Но это я наконец-то сделал:

у меня получилось 3 слайда:
— первый, (он же в начале статьи) — вывод текста с точностью до пиксела, вывод рамки

— второй — вывод шестнадцатеричного числа (до 32ух бит, число цифр задается в программе), вывод десятичного числа (32 бита, число цифр задается в программе)

— третий — рисование линий и точек, внизу слайда приведено количество тактов микроконтроллера затраченное на такое рисование (вместе с очисткой буфера), подсчет тактов производился при помощи модуля DWT:

Да, и еще, чур на дисплей не пинять, он у меня какой то контуженый 🙂 был другой, но отказался заводиться не только от программы написанной на ассемблере, но и от программы написанной на си с частотой SPI в 2 Мгц (за что сразу был выброшен в мусорку дабы не портил нервы)

Снял небольшое видео работы программы:

Музыка в фоне от телевизора, звуком я пока не занимался.

Ссылка на архив проекта

p.s. кстати, никто не занимается написанием текстовых редакторов? очень хочется среду разработки с подсветкой кода, контекстным меню, и прочими рюшками… Пока делаю это в FAR, но хочется чего то более удобного… мои контакты прежние: gorbukov @ тот_кто_знает_ всё. ru

ссылка на оригинал статьи https://habrahabr.ru/post/276121/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *