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 выглядит пока так:
@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 файла:
- font6×8.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