Сообщение от dimdidim
|
UP.. Да, передавать массивами значительно быстрее, чем попиксельно. Так можно добиться приличной скорости обновления экрана и без DMA
|
Ну как получилось хотябы раза 3-4 в секунду?
Заливка одним цветом из массива это конечно хорошо, но когда начнешь формировать какие-то элементы, текст - перерисовка полного кадра ради замены пары цифр - накладное дело, поскольку не хватает оперативки. Считай, вся сотая серия СТМов не имеет объема, достаточного для полного кадра. Это уже удел четырехсотой серии. Выходит, что максимальные скорости работы МК приходится выжимать только ради перерисовки дисплея. И даже при этом, сколько бы не извращался, предел скорости на SPI получится что-то около 100 мс на полный кадр, ну плюс-минус. При одноразовой перерисовке нормуль, а вот постоянное обновление будет дерганным.
Ускориться, особенно в режиме прерываний, поможет перевод SPI в 16-битный режим на время передачи данных изображения. Но менять битность SPI можно только при отключенном SPI. Для этого напишем вот такую функцию (это не на ХАЛ, это быстрее):
Код:
|
void Start_16bit_communication(void){
SPI1-›CR1 &= ~SPI_CR1_SPE;
SPI1-›CR1 |= SPI_CR1_DFF;
SPI1-›CR1 |= SPI_CR1_SPE;
} |
Теперь перед началом передачи изображения вызовем ее
Start_16bit_communication(); Прибавка в скорости получается за счет вдвое меньшего числа прерываний. Конечно, на деле несколько меньше, чем вдвое прибавка.
Настанет время передать 8-битные команды, возвращаем в прежний режим:
Код:
|
void Return_to_8bit_communication(void){
SPI1-›CR1 &= ~SPI_CR1_SPE;
SPI1-›CR1 &= ~SPI_CR1_DFF;
SPI1-›CR1 |= SPI_CR1_SPE;
} |
Все это хорошо, однако размер оперативки, формирование изображения...
И вот тут на помощь приходят команды дисплея - CASET, PASET. Хотя писательской мороки получается больше, зато в пределах выделенной области перерисовка пойдет куда быстрее. Например, обновить две-три небольшие цифры размером в 16*8 быстрее в ограниченной области, тут как бы даже объяснять не надо.
Итак...
Прежде, чем начать более серьезно после первых опытов работать с дисплеем, неплохо бы вообще почитать его даташит, поглазеть на набор команд и режимы.
В даташите к дисплею (не к контроллеру, а именно к дисплею) приведена стандартная процедура инициализации. Она дофига какая длинная. Из нее смело можно выкинуть почти всё, (выкинутое отправим для эстетов, напотом), оставить в инициализации нужно буквально несколько команд:
- Команда софтового сброса Software Reset - вещь хорошая и полезная, позволит правильно возобновить работу с дисплеем, если питание не прерывалось, а только сбросился управляющий МК. Совместно с "железным" выводом сброса /RST помогает правильно запустить дисплей после "железной" подачи питания. Перед подачей следующих команд надо выдержать паузу 5 мс.
- Команда Pixel Format Set - крайне важная команда при инициализации. Дисплей стартует по умолчанию с 18-битным цветом, представленном в трех байтах. Поэтому, если хотим сэкономить на размерах, выставляем этой командой 16-битный цвет.
- Команда Memory Access Control - тоже очень нужная вещь, она настраивает ориентацию изображения, зеркалирование, и важную вещь - порядок вывода цветов - RGB или BGR, то есть, соответствие последовательности физических цветовых пикселей в триаде той последовательности, которая передается интерфейсно. В моем дисплее по дефолту синий и красные цвета наоборот местами поменяны.
- Команды Display ON и Sleep OUT - без них никуда - первая активирует внутренние выходы на пиксели, вторая - запускает развертку пикселей. Команды влияют только на работу пикселей и развертки, сам дисплей способен принимать команды и данные в выключенном или спящем режиме.
После этих команд надо выдерживать небольшие паузы по 100 мс.
Вот, это основной набор для инициализации. Остальное, типа калибровки цветов и настройки гаммы - пофик, пусть эстеты морочатся.
Сразу после подачи питания и выключенном управлении пикселями дисплей будет пропускать свет от подсветки. После запуска развертки содержимое внутренней видеопамяти - произвольное, чаще всего серо-полосчатое. Поэтому, после подачи питания подсветку не включаем, проводим очистку видеопамяти загрузкой в него черного цвета или сразу нужной нам картинки, после этого можно зажечь подсветку. Итого, получается для дисплея нужен еще один вывод МК - управление подсветкой. Хотя, это опять же для эстетов - если не хочется артефактов всяких.
Прежде, чем переходить к рисованию всякой фигни на дисплее, надо заготовить функции работы с дисплеем. Причем, команды не обязательно пересылать через видеобуфер или DMA. Команды короткие, есть однобайтные без параметров, есть с одним параметром, есть с двумя-четырьмя, причем, приходится передергивать сигнал D/CX. Правда, в определенном режиме его можно включить в посылку SPI, но посылки должны быть 9-битными тогда.
"Джентельменский набор" функций работы с дисплеем - помимо инициализации и записи/чтения видеопамяти - еще и установка размеров области записи/чтения. Эта функция должна быть всегда под рукой.
Ну вот, после таких подготовительных операций, когда всё отлажено и работоспособно, можно переходить непосредственно к формированию изображения.
А вот тут пригодится еще одна функция, упаковывающая R, G и B компоненты в два байта в соответствии с заданным режимом дисплея. 5-6-5. По 5 бит на красный и синий и 6 бит на зеленый цвета. Тоже очень просто - каждый компонент переносится в двухбайтную переменную, сдвигаясь на заданное число позиций и добавляясь по ИЛИ.
Заодним, понадобятся заранее задефайненные цвета в формате непосредственного вывода. То есть,
Код:
|
#define RED_Tx 0xF800
#define GREEN_Tx 0x07E0
#define BLUE_Tx 0x001F
#define YELLOW_Tx 0xFFE0
#define LIGHTBLUE_Tx 0x07FF
#define WHITE_Tx 0xFFFF
#define BLACK_Tx 0x0000
... ну и так далее.. |
Пригодится при однородных заливках, чтобы не вычислять из RGB компонент.
Ну а дальше... Дальше вопрос формирования изображения...
Причем, простейшую геометрию можно формировать прямо "на лету" - рамочки, заливочки, поля. Двухмерный массив, однако..
Сообщение от dimdidim
|
в stm32f1xx_hal_spi.h все функции передачи данных только 8 бит.
|
Хм... Так а чего там такого, неужто без ХАЛа с двухбайтной переменной не справиться? Регистр приёма/передачи автоматически изменяет разрядность при изменении разрядности SPI.
uint16_t variable - и готово, работай. Остальное настраивается/работает так же, как и в 8-битном режиме.