Skocz do zawartości

[STM32] Optymalizacja sterowania wyświetlaczem TFT


Pomocna odpowiedź

Napisano

Kombinuję nad przyśpieszeniem pracy wyświetlacza (opartego na sterowniku ST7735S) a konkretnie funkcji "czyszczenia" ekranu poprzez wypełnienie jednolitym kolorem. 

Punktem wyjścia były metody przedstawione w kursach dotyczących STM32L4 (czyli wysyłanie dwubajtowego koloru "na dwa razy") ale udało mi się to trochę usprawnić, poprzez deinicjalizację i ponowną inicjalizację SPI ze zmienioną długością ramki (8 -> 16 bitów). Choć działa to 2x szybciej to wciąż jest bieda bo muszę dla każdego piksela osobno wywoływać HAL_SPI_Transmit(). 

        LCD_Set_Window(0, 0, 160, 128);  //Ustawienie obszaru na cały ekran
		LCD_Cmd(RAMWR);          //Komenda zapisu danych 

		LCD_CS(HIGH);            //Odcięcie wyświetlacza od MOSI i CLK
		HAL_SPI_DeInit(&hspi1);  //Deinicjalizacja SPI
		MX_SPI1_Init16();        //Inicjalizacja ze zmienioną długością ramki na 16 bit

		LCD_DC(HIGH);            //Rozpoczęcie przesyłu danych
		LCD_CS(LOW);
		for (int i = 0; i < 20480; i++) {
		HAL_SPI_Transmit(&hspi1, &color, 1, HAL_MAX_DELAY);
		}
		HAL_SPI_DeInit(&hspi1);      //Deinicjalizacja zmodyfikowanego SPI
		MX_SPI1_Init();              //Powrót do pierwotnej konfiguracji SPI

(wybaczcie magiczne liczby, jestem na etapie tworzenia koncepcji dopiero 😛 )

Drugą metodą było stworzenie tablicy wypełnionej bajtami (interesują mnie tylko kolory czarny i biały więc wystarczyło wypełnić tablicę wartościami 0x00 lub 0xFF) za pomocą funkcji memset() i wysłanie jej jako "obrazu". Osiągnąłem fajną szybkość działania ale oczywiście zapełniłem ogromną ilość RAM (ponad 40KB wyszło).

Pytanie - czy da się w jakiś przystępny sposób "zmusić" SPI to wielokrotnego wysłania pojedynczego bajtu za jednym wywołaniem funkcji "Transmit" bez konieczności tworzenia wieloelementowej tablicy? Że się w ogóle da to nie mam wątpliwości ale bazuję na HALu i tutaj jestem chyba trochę ograniczony...

 

 

(edytowany)
2 godziny temu, Wloczykij555 napisał:

Pytanie - czy da się w jakiś przystępny sposób "zmusić" SPI to wielokrotnego wysłania pojedynczego bajtu za jednym wywołaniem funkcji "Transmit" bez konieczności tworzenia wieloelementowej tablicy? Że się w ogóle da to nie mam wątpliwości ale bazuję na HALu i tutaj jestem chyba trochę ograniczony...

DMA 😉 Ale do pojedynczości to raczej ciężko bez tablicy... Robisz DMA do SPI, podpinasz transfer DMA do żądania SPI i uruchamiasz transfer SPI dla 'n' bajtów, gdzie DMA jest ustawione jako cykliczne. (pisane na bazie doświadczenia z RP2040, ale powinno zadziałać)

Edytowano przez H1M4W4R1
  • Lubię! 1

Może zrób jednak tablicę ale niekoniecznie na całą ramkę? Wysłanie 2048 po 10 bajtów zamiast 20480 po jednym powinno dać znaczne przyspieszenie. Poza tym ta implementacja HAL_SPI_Transmit jest dosyć nieoptymalna bo za każdym razem sprawdza strasznie dużo rzeczy. To by się pewnie dało znacznie odchudzić.

  • Lubię! 1
6 godzin temu, H1M4W4R1 napisał:

DMA 😉 Ale do pojedynczości to raczej ciężko bez tablicy.

Raczej nic specjalnego, tylko odp. konfiguracja kanału DMA bez inkrementacji, wysyłanie pojedynczego bajtu do kontrolera, co spowoduje wypełnienie bufora odbiorczego, a kanał DMA będzie nadawał cały czas to samo. 

  • Pomogłeś! 1

Fajny pomysł, potrzeba jeszcze licznika (w przerwaniu DMA, SPI?) aby po wysłaniu danych wyłączyć dma

7 godzin temu, H1M4W4R1 napisał:

DMA 😉

O widzisz, muszę temat zgłębić

 

2 godziny temu, etet100 napisał:

Może zrób jednak tablicę ale niekoniecznie na całą ramkę? Wysłanie 2048 po 10 bajtów zamiast 20480 po jednym powinno dać znaczne przyspieszenie. 

Też właśnie wpadłem na taki pomysł, jak nic innego nie pomoże to pójdę w tym kierunku ;)

57 minut temu, _LM_ napisał:

Fajny pomysł, potrzeba jeszcze licznika (w przerwaniu DMA, SPI?)

Nie jest konieczne. Również konfiguracja kanału DMA z odp. liczbą transakcji. Kanał sam się "wyłączy" gdy wewn. licznik kanału się wyzeruje.

Tak właśnie działa DMA wyłączonym trybem circular

  • Pomogłeś! 2
2 godziny temu, Wloczykij555 napisał:

Też właśnie wpadłem na taki pomysł, jak nic innego nie pomoże to pójdę w tym kierunku 😉

Przecież @Zealotanapisał dokładnie to co trzeba zrobić.

A tak z ciekawości, po co koledze taka dziwna funkcja T_CLRS (Turbo_Clear_Screan)? ogólnie przy tworzeniu szybkich animacji nie korzysta z funkcji czyszczenia ekranu, tylko go po prostu nadpisuje.

@Wloczykij555 Błąd inicjalizacji DMA to nic nowego... Pisałem o tym samym błędzie dwa lata temu:

Podczas przygotowywania kursu STM32L4 inicjalizacja DMA wyglądała poprawnie, więc jak widać błąd wrócił później.

Ciekawe jak ST wykonuje testy zmian kodu, jak widać mają jeszcze sporo do poprawy 😄

  • Lubię! 1

Albo coś źle zrozumiałem, albo autor wątku coś źle zrozumiał... Jeżeli jest to wyświetlacz z własnym sterownikiem, to zwykle sterownik wyświetlacza ma zaimplementowane procedury czyszczenia/wypełniania obszaru zadanego (okna)prostokąta. Podaje się zakres (rozmiar i położenie okna) i komendę wypełnienia zadanego obszaru przez sterownik wybranym kolorem. Sposób z wypełnianiem pikseli "na piechotę" zawsze będzie trwał o wiele dłużej jak komenda sterownika, bez względu na użycie DMA i czegokolwiek innego.

@virtualny Nazwa użytego sterownika jest wymieniona w pierwszym poście i jest to ST7735S. Mógłbyś podać gdzie dokładnie znalazłeś informację o "zaimplementowanej procedurze czyszczenia/wypełniania wypełnianiu obszaru" przez ten sterownik?

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...