STM Урок 64. HAL. LTDC. Часть 3



 

Урок 64

HAL. LTDC

 

Часть 3

 

В прошлой части нашего занятия мы настроили проект и написали тест заливки экрана случайными цветами.

Теперь напишем несколько функций в библиотеку для вывода различных примитивов.

Начнём с той же заливки, только заливать мы будем ограниченную прямоугольную область. Создадим функцию в ltdc.c и создадим для неё прототип

 

//————————————————-
void TFT_FillRectangle(uint16_t x1, uint16_t y1,
        uint16_t x2, uint16_t y2, uint16_t color)
{
}

 

Также мы будем пользоваться некоторым кодом из урока по дисплею 240×380.

В хедер-файл ltdc.h добавим макрос для обмена значениями между двумя переменными.

 

#include <stdlib.h>
//———————————————
#define swap(a,b) {int16_t t=a;a=b;b=t;}
//———————————————

 

Добавим в функцию две переменных для циклов

 

void TFT_FillRectangle(uint16_t x1, uint16_t y1,
        uint16_t x2, uint16_t y2, uint16_t color)
{
  uint32_t xpos, ypos;

 

Так как при выводе, например в случайное место, координаты могут быть выведены и наоборот, сначала например правая координата, а затем левая, то в таком случае обменяем координаты значениями

 

void TFT_FillRectangle(uint16_t x1, uint16_t y1,
        uint16_t x2, uint16_t y2, uint16_t color)
{

 uint32_t xpos, ypos;
 if(x1>x2) swap(x1,x2);
 if(y1>y2) swap(y1,y2);

 

Ну и затем цикл для заливки, здесь всё, я думаю понятно и объяснение не нужно

 

  if(y1>y2) swap(y1,y2);
  for(ypos=y1;ypos<=y2;ypos++)
  {
    for(xpos=x1;xpos<=x2;xpos++)
    {
   *(__IO uint16_t*) (hltdc.LayerCfg[0].FBStartAdress + (2*(ypos*hltdc.LayerCfg[0].ImageWidth + xpos))) = (uint16_t)color;
   }
  }

}

 

 

Теперь вернёмся в наш бесконечный цикл и напишем ещё один небольшой тест

 

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,
            (uint16_t)HAL_RNG_GetRandomNumber(&hrng));
   HAL_Delay(10);
}
TFT_FillScreen(0);
HAL_Delay(1000);

 

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

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

 

Image16

 

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

 

//————————————————-
void TFT_DrawPixel(uint16_t Xpos, uint16_t Ypos, uint32_t color)
{
   *(__IO uint16_t*) (hltdc.LayerCfg[0].FBStartAdress + (2*(Ypos*hltdc.LayerCfg[0].ImageWidth + Xpos))) = (uint16_t)color;
}
//————————————————-

 

Я думаю, рассчёт здесь предельно прост.

Попробуем теперь написать интересный тест по выводу случайных точек на экран в бесконечном цикле. Также добавим туда цикл

 

  HAL_Delay(1000);
  for(i=0;i<10000;i++)
  {
   TFT_DrawPixel(HAL_RNG_GetRandomNumber(&hrng)%480,
          HAL_RNG_GetRandomNumber(&hrng)%272,
          (uint16_t)HAL_RNG_GetRandomNumber(&hrng));
   HAL_Delay(1);
  }
  TFT_FillScreen(0);
  HAL_Delay(1000);

 

 

Только у нас всё это будет смотреться не очень хорошо и экран очень быстро усыпется весь точками. Если мы зажигаем точки, то мы их должны и тушить. Перед тем, как зажечь точку, мы потушим несколько точек. Причём путём эксперементов было получено то, что тушить нужно где-то 100 случайных точек, тогда у нас их слишком много не будет и будет очень красиво, то есть будет какой-то баланс количества случайных точек на экране. Поэтому вставим ещё код в наш цикл

 

  for(i=0;i<10000;i++)
  {
   for(j=0;j<100;j++)
   {
     TFT_DrawPixel(HAL_RNG_GetRandomNumber(&hrng)%480,
          HAL_RNG_GetRandomNumber(&hrng)%272,0);
   }

   TFT_DrawPixel(HAL_RNG_GetRandomNumber(&hrng)%480,
          HAL_RNG_GetRandomNumber(&hrng)%272,
          (uint16_t)HAL_RNG_GetRandomNumber(&hrng));

 

Теперь прошьём контроллер и посмотрим результат

 

Image17

 

Напишем ещё одну функцию по выводу линий на экран в нашу библиотеку, также пользуемся нашим накопленным опытом

 

void TFT_DrawLine(uint16_t x1, uint16_t y1,
        uint16_t x2, uint16_t y2, uint16_t color)
{
 int steep = abs(y2-y1)>abs(x2-x1);
 if (steep)
 {
  swap(x1,y1);
  swap(x2,y2);
 }
 if(x1>x2)
 {
  swap(x1,x2);
  swap(y1,y2);
 }
 int dx,dy;
 dx=x2-x1;
 dy=abs(y2-y1);
 int err=dx/2;
 int ystep;
 if(y1<y2) ystep = 1;
 else  ystep = -1;
 for (;x1<=x2;x1++)
 {
  if (steep) TFT_DrawPixel(y1,x1,color);
  else TFT_DrawPixel(x1,y1,color);
  err-=dy;
  if (err<0)
  {
   y1 += ystep;
   err+=dx;
  }
 }
}
//————————————————-

 

Функция практически не изменилась по сравнению с той, которая была в уроке 37.

 

Пишем прототип и пишем тест в бесконечном цикле

 

  HAL_Delay(1000);
  for(i=0;i<1000;i++)
  {    
    TFT_DrawLine(HAL_RNG_GetRandomNumber(&hrng)%480,
            HAL_RNG_GetRandomNumber(&hrng)%272,
            HAL_RNG_GetRandomNumber(&hrng)%480,
            HAL_RNG_GetRandomNumber(&hrng)%272,
            (uint16_t)HAL_RNG_GetRandomNumber(&hrng));
   HAL_Delay(10);
  }
  TFT_FillScreen(0);
  HAL_Delay(1000);

}

 

Собираем, прошиваем, смотрим

 

Image18

 

Всё у нас получилось.

Я думаю, знаний, приобретённых в этом уроке достаточно для хотя бы какого-то понимания интерфейса LTDC, а также его программирования с помощью библиотеки HAL.

 

 

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

 

Исходный код

 

 

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

 

 

Смотреть ВИДЕОУРОК

 

STM32 HAL. LTDC

4 комментария на “STM Урок 64. HAL. LTDC. Часть 3
  1. Георгий:

    Доброго времени суток. В функции DrawLine ошибка в последнем условии if. Написано "err =dx;" , а должно быть "err +=dx;". Из за этого лигия прорисованная по диагонали рисуется неправильно. Исправте пожалуйста. 

  2. Владимир:

    Доброго времени суток.
    Сдублирую вопрос в двух темах, может кто откликнется.
    Разбираюсь с отладкой STM32F4-disco на 429 камне. Вроде разобрался с записью и чтением с sdram, но при подключении дисплея возникла странная проблемка. После записи в SDRAM буфера для экрана (просто заливаю зеленым), после нескольких чтений экран из зеленого перетекает в белый. Где я мог накосячить в работе с памятью?

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

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

*