lcd_ltdc — дисплей RGB 800×480
Выводит на дисплей с параллельным интерфейсом RGB картинку с SD-карты и гоняет по ней квадрат. Контроллер LTDC сам читает кадр из SDRAM и выдаёт его на дисплей, рисует DMA2D — процессор в этом почти не участвует.
Подключение
Заголовок раздела «Подключение»Дисплей 800×480 с интерфейсом RGB (24 бита данных, CLK, HSYNC, VSYNC, DE) — через переходник на разъёмы J1 и J2. Подсветка и питание дисплея — от переходника.
| Сигнал | Вывод | Контакт | Сигнал | Вывод | Контакт | Сигнал | Вывод | Контакт | ||
|---|---|---|---|---|---|---|---|---|---|---|
| R0 | PG13 | J1-22 | G0 | PE5 | J1-28 | B0 | PE4 | J1-27 | ||
| R1 | PA2 | J2-32 | G1 | PE6 | J1-29 | B1 | PC10 | J1-14 | ||
| R2 | PA1 | J2-33 | G2 | PA6 | J2-27 | B2 | PA3 | J2-30 | ||
| R3 | PB0 | J2-23 | G3 | PC9 | J1-7 | B3 | PA8 | J1-10 | ||
| R4 | PA5 | J2-28 | G4 | PB10 | J2-18 | B4 | PA10 | J1-12 | ||
| R5 | PA9 | J1-9 | G5 | PC1 | J2-31 | B5 | PB5 | J1-24 | ||
| R6 | PB1 | J2-22 | G6 | PC7 | J1-5 | B6 | PA15 | J1-11 | ||
| R7 | PC4 | J2-25 | G7 | PD3 | J1-18 | B7 | PD2 | J1-15 |
CLK — PG7 (J2-7), HSYNC — PC6 (J1-6), VSYNC — PA4 (J2-29), DE — PC5 (J2-24).
Эти 28 выводов заняты дисплеем целиком: ШИМ Lua-модуля pio на PA1–PA3, PA5, PA6, PA8,
PB0, PB1, PC6–PC9 с ним не совместим. Свободными остаются, например, I2C1 (PB8, PB7),
FDCAN2 (PB12, PB13) и USART1.
Включить
Заголовок раздела «Включить»cmake --preset Release -DH723_RECIPES="lcd_ltdc"Картинка — /SD/lcd.bmp: BMP 24 бита без сжатия, лучше 800×480 (меньшая встанет по центру).
Без файла на экране цветные полосы.
Вывод на плате
Заголовок раздела «Вывод на плате»lcd_ltdc: startedlcd_ltdc: 800x480 RGB565, pixel clock 25000 kHz, refresh 43 Hzlcd_ltdc: /SD/lcd.bmp 800x480 loaded in 175 mslcd_ltdc: 43 fps, draw 506 us/frame43 кадра в секунду — по одному на каждый кадр развёртки; на рисование кадра уходит 0,5 мс.
С работающим дисплеем SD-карта пишет 10,1 МБ/с и читает 10,7 МБ/с (sd_file), SSH, SFTP и Lua
работают как без дисплея.
Как это работает
Заголовок раздела «Как это работает»- Такт пикселя. LTDC тактируется от выхода R PLL3: 250 МГц / 10 = 25 МГц
(
PeriphCommonClock_Configвmain.c). Полный кадр с порогами — 1057 × 549 тактов, отсюда 43 Гц. - Тайминги развёртки —
LCD_HSYNC,LCD_HBP,LCD_HFPи вертикальные вlcd_ltdc.h, из документации панели. В регистры LTDC пишутся накопленные суммы: импульс, + задний порог,- видимая часть, + передний порог, каждая минус 1.
- Регистры, а не HAL. Модули HAL для LTDC и DMA2D в проекте не включены (их нет в
.ioc), а регистров немного — рецепт не зависит от настроек CubeMX. - Кадровые буферы — в SDRAM, два по 768 КБ (RGB565, 2 байта на пиксель). На экране один,
рисуется другой;
lcdSwapменяет адрес слоя с перезагрузкой по кадровому гасящему импульсу (LTDC_SRCR_VBR) и ждёт его — поэтому картинка не рвётся. - RGB565 вместо ARGB8888 — вдвое меньше памяти и нагрузки на шину SDRAM. Линии R0–R2, G0–G1, B0–B2 LTDC при этом всё равно выдаёт, дополняя цвет до 24 бит.
- DMA2D рисует сам: заливка прямоугольника (режим «регистр → память»), копия картинки («память → память») и перевод BMP из RGB888 в RGB565 («память → память с преобразованием»).
- Перерисовывается только изменившееся. Шину SDRAM делят LTDC (~33 МБ/с на чтение кадра), DMA2D, процессор, Lua и RAM-диск. Копия всего фона в каждом кадре добавила бы ~65 МБ/с и 17 мс работы DMA2D. Поэтому фон пишется в оба буфера один раз, а в каждом кадре закрывается фоном только место, где квадрат был два кадра назад (буферы чередуются).
- Своя периферия с DMA рядом с дисплеем. Пока LTDC читает кадр, доступ к SDRAM идёт с
очередью. Буферы DMA для периферии, которой важно успевать (SD-карта, быстрый UART, SPI),
лучше держать во внутренней памяти (
pvPortMalloc, AXI SRAM) — так сделан и драйвер SD-карты. - Кэш. SDRAM кэшируется. Память под буферы инвалидируется после выделения: иначе «грязные»
строки кэша от прежних владельцев могли бы вытесниться поверх того, что пишет DMA2D. Данные
BMP, прочитанные процессором, перед DMA2D выгружаются из кэша (
SCB_CleanDCache_by_Addr). Буферы выровнены по 32 байта — размер строки кэша. - BMP хранит строки снизу вверх и выравнивает их до 4 байт, поэтому DMA2D переводит картинку по строке. Файл читается через FatFs блоками по 32 КБ: драйвер SD передаёт их одной командой, мелкие чтения через stdio в разы медленнее.
Переделать под себя
Заголовок раздела «Переделать под себя»- Другая панель — размер и тайминги в
lcd_ltdc.h; частоту пикселя меняет делительPLL3R(в.ioc, от него же тактируется АЦП). Полярности сигналов — регистрLTDC->GCR. - Текст, кнопки, графики и сенсорный ввод — рецепт lvgl_demo: LVGL
рисует прямо в кадровые буферы этого драйвера (
lcdFrameBuffer,lcdShow). - Рисование процессором по пикселям — в
backBuffer, а передlcdSwapвыгрузить изменённое из кэша (SCB_CleanDCache_by_Addr), иначе LTDC покажет старые данные. - Сенсорная панель дисплея обычно подключается по I2C — см. рецепт i2c_bme280.
Исходники рецепта: recipes/lcd_ltdc
