STM Урок 69. HAL. LTDC. DMA2D. Часть 2

 

 

 

 

Урок 69

 

Часть 2

 

HAL. LTDC. DMA2D

 

 

В предыдущей части нашего занятия мы сгенерировали и настроили проект, добавиили необходимые переменные, а также произвели их начальную инициализацию.

 

Немного исправим функцию TFT_FillScreen, которая заливает полностью экран одним цветом. Ну немного, это мягко сказано, в принципе мы можем скопировать с прежнего кода только некоторые значения в слое

 

//----------------------------------------

void TFT_FillScreen(uint32_t color)

{

  hdma2d.Init.Mode = DMA2D_R2M;

  hdma2d.Init.OutputOffset = 0;

  if(HAL_DMA2D_Init(&hdma2d) == HAL_OK)

  {

    if (HAL_DMA2D_Start(&hdma2d, color, hltdc.LayerCfg[0].FBStartAdress,

    hltdc.LayerCfg[0].ImageWidth, hltdc.LayerCfg[0].ImageHeight) == HAL_OK)

    {

      HAL_DMA2D_PollForTransfer(&hdma2d, 10);

    }

  }

}

//----------------------------------------

 

Вообщем здесь мы меняем настройки видеоускорителя, выбрав режим копирования из регистра в память, и копируем значение color, которое находится именно в регистре, а в каком, нам не важно, используя функцию HAL_DMA2D_Start, в память с адреса, находящемся в третьем входном параметре. Четвёртым и пятым параметром функции являются ширина и высота заливаемой области, которые в нашем случае равны ширине и высоте нашего экрана, так как мы заливаем весь экран. Затем мы ждём окончания передачи данных с помощью функции HAL_DMA2D_PollForTransfer, выставив таймаут в 10 милисекунд. Я думаю этого достаточно для нашего мощного ускорителя.

Добавим тест, окрашивающий случайным цветом весь экран дисплея, в бесконечный цикл. Код можно позаимствовать в уроке 66

 

/* USER CODE BEGIN 3 */

  //окраска всего экрана случайным цветом

  for(i=0;i<50;i++)

  {

    TFT_FillScreen(HAL_RNG_GetRandomNumber(&hrng)|0xFF000000);

    HAL_Delay(200);

  }

  TFT_FillScreen(0);

  HAL_Delay(1000);

 

Соберём код, прошьём контроллер и увидим, что наш экран также окрашивается, как и в уроке 66 не смотря на то, что окраска происходит уже с применением ускорителя DMA2D.

Теперь, применив подобные исправления, изменим код в функции TFT_FillRectangle, которая выводит закрашенные прямоугольники с заданными координатами

 

//----------------------------------------

void TFT_FillRectangle(uint16_t x1, uint16_t y1,

uint16_t x2, uint16_t y2, uint32_t color)

{

  if(x1>x2) swap(x1,x2);

  if(y1>y2) swap(y1,y2);

  uint32_t addr = 0;

  addr = (hltdc.LayerCfg[0].FBStartAdress) + 4*(y1*hltdc.LayerCfg[0].ImageWidth + x1);

  hdma2d.Init.Mode = DMA2D_R2M;

  //смещение = ширина экрана минус ширина прямоугольника

  hdma2d.Init.OutputOffset = hltdc.LayerCfg[0].ImageWidth-(x2-x1);

  if(HAL_DMA2D_Init(&hdma2d) == HAL_OK)

  {

    if (HAL_DMA2D_Start(&hdma2d, color, addr, x2-x1, y2-y1) == HAL_OK)

    {

      HAL_DMA2D_PollForTransfer(&hdma2d, 10);

    }

  }

}

//----------------------------------------

 

Теперь добавим в бесконечный цикл функции main() тест, выводящий закрашенные сулчайным цветом прямоугольники случайного размера в случайное место

 

HAL_Delay(1000);

//выводим в случайном месте прямоугольники, окрашенные случайным цветом

for(i=0;i<1000;i++)

{

  TFT_FillRectangle(HAL_RNG_GetRandomNumber(&hrng)%480,

  HAL_RNG_GetRandomNumber(&hrng)%272,

  HAL_RNG_GetRandomNumber(&hrng)%480,

  HAL_RNG_GetRandomNumber(&hrng)%272,

  HAL_RNG_GetRandomNumber(&hrng)|0xFF000000);

  HAL_Delay(10);

}

TFT_FillScreen(0);

HAL_Delay(1000);

 

Соберём код, прошьём контроллер и посмотрим результат

 

image02

 

Прямоугольники также выводятся, но уже с применение видеускорителя DMA2D.

Вообщем один режим проработали, теперь следующий.

 

 

Вернёмся в ltdc.c и исправим уже код функции TFT_DrawBitmap, которая выводит на экран изображение формата BMP.

Здесь мы исправляем не всё.

Сначала исправим код в цикле for. Он будет только одного уровня, внутренний будет удалён

 

for(index=0; index < height; index++)

{

  hdma2d.Init.Mode = DMA2D_M2M_PFC;

  hdma2d.Init.ColorMode = DMA2D_ARGB8888;

  hdma2d.Init.OutputOffset = 0;

  hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;

  hdma2d.LayerCfg[1].InputAlpha = 0xFF;

  hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB888;

  hdma2d.LayerCfg[1].InputOffset = 0;

  if(HAL_DMA2D_Init(&hdma2d) == HAL_OK)

  {

    if(HAL_DMA2D_ConfigLayer(&hdma2d, 1) == HAL_OK)

    {

      if (HAL_DMA2D_Start(&hdma2d, (uint32_t) pbmp, address, width, 1) == HAL_OK)

      {

        HAL_DMA2D_PollForTransfer(&hdma2d, 10);

      }

    }

  }

  address+= (X_SIZE*4);

  pbmp -= width*(bit_pixel/8);

}

 

Здесь мы уже настраиваем видеоускоритель на режим копирования из памяти в память с преобразованием пикселя из формата RGB888 в формат ARGB8888.

Затем мы применяем ту же функцию HAL_DMA2D_Start, только в данном случае входные параметры немного изменятся. То есть тип входных параметров зависит от режимов работы видеоускорителя. Мы передаём указатель на видеоускоритель, указатель на адрес источника данных, адрес приёмника, ширину и единичку, обозначающую высоту. У нас высота 1 пиксель, так как выводим мы одну линию. Только теперь данная линия выводится при помощи видеоускорителя, и наш макрос по конвертированию формата пикселя мы уже не используем, возлагая это на DMA2D.

Затем после полного выхода из условия else мы возвращаем настройки по умолчанию для нашего ускорителя такие, как мы настраивали в Cube MX.

 

  }

  //Установим настройки DMA2D в DMA2D_M2M_BLEND

  hdma2d.Init.Mode = DMA2D_M2M_BLEND;

  hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;

  hdma2d.Init.OutputOffset = 0;

  hdma2d.LayerCfg[1].InputOffset = 0;

  hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;

  hdma2d.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;

  hdma2d.LayerCfg[1].InputAlpha = 0;

  hdma2d.LayerCfg[0].InputOffset = 0;

  hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_ARGB8888;

  hdma2d.LayerCfg[0].AlphaMode = DMA2D_REPLACE_ALPHA;

  hdma2d.LayerCfg[0].InputAlpha = 0;

  if(HAL_DMA2D_Init(&hdma2d) == HAL_OK)

  {

    HAL_DMA2D_ConfigLayer(&hdma2d, 0);

    HAL_DMA2D_ConfigLayer(&hdma2d, 1);

  }

  //вернём формат пикселя по умолчанию

  bit_pixel = 0;

}

 

Раскомментируем наш код с тестом вывода картинок в бесконечном цикле, соберём код, прошьём контроллер и проверим вывод картинок

 

image03 image04 image05 image06 image07 image08 image09 image10 image11 image12

 

Все рисунки также выводятся не смотря на использование видеоускорителя. Из этого следует, что мы сделали всё правильно, то есть формат пикселя теперь преобразуется с помощью DMA2D.

 

В следующей части урока мы напишем некоторые функции и тест по плавному выводу изображений на экран дисплея и посмотрим все наши тесты, тем самым завершим наше занятие по программированию видеоускорителя DMA2D.

 

Предыдущая часть Программирование МК STM32 Следующая часть

 

 

Отладочную плату можно приобрести здесь 32F746G-DISCOVERY

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM HAL. LTDC. DMA2D

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

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

*