fbpx

Wiele osób rozwodzi się nad pięknem wyświetlaczy OLED bowiem mają w sobie coś niesamowitego. Nieskończony kontrast i wysokia częstotliwość odświeżania są niesamowitymi atutami tej technologii. W sprzedaży możemy znaleźć mnóstwo malutkich monochromatycznych OLEDów w rozmiarach od ok 0.49″ do nawet około 4″. Ich cena w ostatnich latach mocno spadła przez co są szalenie popularne. Sprawdźmy jak ujarzmić OLED SSD1306 za pomocą STM32!

Technologia OLED

Chyba najważniejszą cechą tej technologii jest fakt, że każdy pixel to pojedyncza organiczna dioda świecąca. Wiąże się to z brakiem konieczności oświetlenia matrycy od tyłu dzięki temu wyświetlacz jest cieniutki oraz składa się w zasadzie z samego szkła. Dzięki temu wyświetlacze te mogą osiągać teoretycznie nieskończony kontrast. W skrócie – czarny pixel nie świeci, a biały to biały.

Brak prądożernego podświetlenia oznacza energooszczędność bowiem ten element pochłania największe ilości prądu w klasycznych wyświetlaczach LCD.

Lecz nie ma nic za darmo… Przez to, że pixele to diody dochodzi to zjawiska wypalania się ich. Diody z czasem tracą jasność. W zależności od koloru, zejście do połowy początkowej jasności może trwać ok 20-100 tys. godzin. Jest to zaznaczone w każdej karcie katalogowej. Wydaje się to sporą wartością i faktycznie jest. Niestety ludzkie oko potrafi zobaczyć względną różnicę w jasności już po obniżeniu jasności o kilka procent. Stąd widzimy wypalenia na obszarach, gdzie OLED wyświetla stały obraz. Widoczne będzie to za rok-dwa(o ile już nie jest) w telewizorach OLED które raczkują i będzie to dosyć sporym problemem w pierwszych modelach.

Bardzo dobry artykuł na temat OLEDów napisał kiedyś mój kolega. Zapraszam do lektury(link).

Kontroler OLED SSD1306

Nigdy nie mamy dostępu do żywej matrycy. Zawsze po drodze stoi jakiś kontroler. Tak jest przy wyświetlaczach alfanumerycznych(HD44780), TFT oraz OLED. Kontroler ma za zadanie Odebrać od układu sterującego instrukcje w jaki sposób ma ustawić pixele na matrycy. Często posiadają wbudowane dodatkowe funkcje.

Popularnym producentem kontrolerów do wyświetlaczy OLED jest Solomon Systech Limited. Produkują one bardzo dobre, popularne kontrolery o oznaczeniach SSD. Mają w swojej ofercie kilkanaście układów zdolnych opanować matryce OLED. Różnią się wielkościami obsługiwanych matryc, interfejsami czy możliwymi stopmiami szarości. Zainteresowanych odsyłam do broszury – SSD_OLED_IC_Catalog. Niewątpliwie na rynku najpopularniejszym jest SSD1306. Jest on stosunkowo prosty. Obsługuje maksymalnie matryce o rozmiarze 128×64 punktów. Posiada 256-stopniową skalę jasności i uwaga, to nie jest skala szarości. On po prostu całą matrycę przyciemnia/rozjaśnia. Posiada wbudowaną pamięć RAM dla wyświetlanego obrazu. Porozmawiać z nim można za pomocą 8-bitowego interfejsu równoległego, I²C lub SPI(3/4 przewodowego) z czego interfejs równoległy rzadko jest implementowany w chińskich modułach. I dobrze bo uważam, że I²C i SPI są wystarczająco szybkie. Ważną cechą jest wbudowana przetwornica napięcia bowiem panele OLED wymagają do działania napięcia ok. 12 V. Dzięki tej przetwornicy nie trzeba się tym martwić, chociaż ponoć potrafią piszczeć. Mi na szczęście nigdy się taki nie trafił.

Kontroler ten posiada kilka wbudowanych efektów:

    • Scrollowanie ekranu np. w celu prostego wygaszacza ekranu – równomierne zużycie pixeli.
    • Funcja Fade Out oraz Blinking
  • Zoom

Więcej cennych informacji znajdziesz w nocie katalogowej układu – SSD1306 Datasheet. Zajmę się wyświetlaczem opartym o ten właśnie sterownik. Będzie to 0.96″.

Sterowanie

Chińskie moduły dają do wyboru dwa interfejsy – I²C i SPI. Komunikacja dzieli się na komendy oraz dane. Wybór typu przesyłanej informacji w I²C dokonuje się przez zapis pod odpowiedni rejestr(0x00 dla danych i 0x40 dla komend). W SPI jest trochę inaczej bo do wyboru jest komunikacja 3 lub 4-ro przewodowa. Przy czterech przewodach oprócz standardowych syngałów interfejsu SPI jest jeszcze sygnał D/C, który determinuje co wysyłane jest do wyświetlacza. Jeżeli wybrany został tryb 3-przewodowy, trzeba wysłać dodatkowy bit na początku każdego bajtu. Robi się wtedy komunikacja 9-bitowa. No to co? Lecę z koksem!

Biblioteka

Kod udostępnia kilka definicji, które można zmieniać takie jak:

  • wybór interfejsu i jego ustawienia jak np. adres I2C
  • Rozdzielczość matrycy
  • Wybór funkcji graficznych oferowanych przez kontroler wyświetlacza

Pozostała kontrola realizowana jest przez odpowiednie funkcje. Tworzenie obrazu oparte jest na buforze RAM w MCU. Mieszczą się w nim informacje o każdym pixelu – tzw. ramka. Jest to wyświetlacz monochromatyczny, więc cały bufor zajmuje tylko 1 kB RAM. Nie jest to dużo dla STM32, a zastosowanie takiego bufora daje ogromną wygodę użytkowania. Dzięki niemu można w łatwy sposób zrealizować nakładanie się obrazów(argument transparency).

Podstawową funkcja jest inicjalizacja. W zależności od interfejsu przyjmuje ona jako argument wskaźnik na odpowiednią strukturę I²C lub SPI. Uwaga. W funkcji tej ustawiane są m. in. rozmiar matrycy, napięcie COM czy kierunki rysowania które mogą się różnić zwłaszcza mając inne rozdzielczości i rozmiary. Upewnij się, że masz odpowiednie i ewentualnie zmień na takie, które zaleca producent Twojego wyświetlacza. Mniejsze rozdzielczości mogą mieć inną organizację pixeli względem pamięci. Jednak dla większości przypadków ustawienia te powinny być poprawne.

4 funkcje konfiguracyjne umożliwiają:

  • Włączenie/wyłączenie pixeli.
  • Odwrócenie kolorów
  • Obrót wyświetlacza o 180°
  • Ustawienie kontrastu – 256-stopniowa jasność wyświetlacza

Następnie najważniejsze funkcje wyświetlacza.

Rysowanie pojedynczego pixela w buforze RAM. Funkcja ta rusyje pixel o podanych współrzędnych i kolorze w pamięci RAM. Nie jest on wysyłany do wyświetlacza. Dzięki temu można przygotowywać całą grafikę zanim zostanie ona wysłana do RAM’u OLED.

Wypełnienie bufora RAM wybranym kolorem. Do dyspozycji jest jedynie WHITE i BLACK. Każda inna wartość będzie ignorowana. Służy ona do kasowania zawartości ramki.

Wysłanie całego bufora do pamięci RAM wyświetlacza. Dopiero w momencie wywołania tej funkcji przygotowany wcześniej bufor jest wysyłany do wyświetlacza i jego obraz ostatecznie pojawia się na matrycy.

Ta funkcja jest podobna do SSD1306_Display z tą różnicą, że możemy wysłać obraz, który znajduje się poza buforem, np. w pamięci Flash. Musi on mieć rozmiar zgodny z rozmiarem matrycy. Inaczej zostanie wysłana jakaś kasza z pamięci lub wystąpi HardFault.

W dalszej kolejności zaimplementowałem funkcje graficzne które oferuje kontroler. Jest więc scrollowanie kontentu wyświetlacza w różnych kierunkach.

Argumenty typu scroll_horizontal_speed decydują co ile klatek następuje animacja. Nie jest to liczba klatek które wysyłasz do kontrolera. Są to klatki odświeżania kontrolera m. in. na podstawie wartości Display Clock oraz Multiplex Ratio podawanych przy inicjalizacji. Dla ułatwienia są one w postaci enumeracyjnej. Zachęcam do eksperymentowania z tymi funkcjami.

Ostatnią sekcją są “zaawansowane” komendy graficzne. Pierwszą jest Fade Out.

Polega ona na stopniowym wygaszeniu wyświetlacza, czyli zmniejszaniu kontrastu. Zmiana dokonuje się od podanej wartości Interval do zera i w nim pozostaje do odwołania.

Podobnym efektem jest mruganie.

Efekt jest podobny do Fade Out z tym, że wyświetlacz wraca do wartości Interval i “mruga” w zapętleniu.

Po wygaszeniu lub ustawieniu mrugania wyświeltacz nie wraca do “normalnego” stanu. Trzeba go z niego wyciągnąć funkcją

Pozostaje ostatnia, najbardziej bezsensowna jak dla mnie funkcja Zoom In.

Działa ona jedynie przy pełnej możliwej matrycy, czyli 128×64 a polega ona na tym, że górna połowa wyświetlacza (128×32) jest rozciągana w dół. Sam zobacz jak to działa. Czy będzie to przydatne?

Biblioteka graficzna

Biblioteka graficzna, którą używam jest bazowana na różnych przykładach z Internetu. Można ją stosować zarówno z STM32 jak i AVR. Wymaga ona przekazania trzech wartości, aby działała poprawnie. Jest to funkcja, która rysuje pojedynczy pixel oraz wymiary wyświetlacza w pixelach.

Bibloteka w moim przykładzie będzie rysowała w buforze RAM ponieważ funkcja pixela to robi. Do wysłania tego do kontrolera OLED będzie trzeba już użyć funkcji SSD1306_Display().

Umieściłem również kilka przełączników w celu decydowania które funkcje rysowania będą potrzebne. Można trochę miejsca we Flashu przyoszczędzić rezygnując z kompilacji zbędnych rzeczy. O tym co będzie kompilowane decydują przełączniki(#define) typu USING_XXX. Ustawienie zera powoduje wycięcie danej funkcji, a jedynka z kolei dorzuci je do kodu. Niektóre funkcje wymagają innych i zastosowałem mały “automat” który to ogarnia. Do dyspozycji są:

  • Stringi w różnych wielkościach
  • Obrazy
  • Obrócony obrazy z krokiem 1° – bardzo prymitywna funkcja, któa potrafi zostawić puste pixele przy obrocie
  • Rysowanie figur geometrycznych(kwardaty, koła, trójkąty – puste, pełne, zaokrąglone lub nie)

Zachęcam do zabawy z biblioteką i zgłaszania mi błędów lub propozycji modyfikacji. Teraz przejdę do głównej części wpisu.

I²C

Na pierwszy ogień wezmę pod lupę I²C. Z STM32 potrzebuję jedynie dwóch przewodów dla zaspokojenia tego interfejsu, więc jest to kusząca opcja do default’owego użytku. Nota SSD1306 mówi o tym, że maksymalny obsługiwany zegar I²C wynosi 400 kHz. W dzisiejszych testach posłużę się płytką Nucleo z STM32L476RG na pokładzie. Umożliwia on komunikację I²C w Standard Mode(100 bit/s), Fast Mode(400 bit/s) oraz Fast Mode Plus(1 Mbit/s). Spróbuję zrobić overclock zegara I²C kontrolera SSD1306, a co! Zobaczymy co z tego wyjdzie.

Jako, że użyłem gotowego modułu z wyświetlaczem to schemat dla podłączenia go do I2C1 jest banalnie prosty.

Najpierw sprawdzę na “pewnej” wartości zegara – 100 kHZ. Konfiguracja Cube jest banalna.

W późniejszych krokach będę zmieniał prędkość przez menu I2C Speed Mode, ale nie będę tego pokazywał na screenach. Przesłanie kompletnej ramki dla częstotliwości zegara I²C równej 100 kHz wygląda następująco:

Czas wysłania wszystkich pixeli wynosi około 103 ms. Całkiem sporo biorąc pod uwagę fakt, że wysyłając ramki jedną za drugą otrzymamy tylko 10 klatek na sekundę przy obciążeniu MCU 100%. Zwiększę trochę prędkość.

Jest już zdecydowanie lepiej. 27,4 ms jest już fajną wartością która da ok 36 klatek na sekundę. Mimo tego, że karta SSD1306 mówi, że maksymalną częstotliwością zegara I2C może być 400 kHz, spróbuję trochę przetaktować komunikację. STM32L476RG oferuje standard Fast Mode Plus. Oto efekt.

Czas przesłania ramki to tylko 12,38 ms. Liczba ta pozwala na uzyskanie około 80 FPS. Jest już to całkiem spora liczba. Na ogół nie jest potrzebna aż tak duża liczba klatek na sekundę, więc można ją ograniczyć zwalniając nieco CPU na inne operacje. No właśnie, czy można trochę ulżyć procesorowi przy transferze? Oczywiście! Za pomocą DMA 🙂 Tą samą operację wykonam teraz wysyłając cały bufor przy pomocy DMA. Zobacz jak bardzo spada zużycie CPU.

100 kHz:

Jak widzisz procesor jest zajęty tylko przez jedną milisekundę. Jest to czas w którym wysyłam po I2C do wyświetlacza informację, że będę wysyłał ramkę. Można ten czas odrobinę skrócić.

400 kHz:

0,3 ms zajętości CPU dla 400 kHz jest świetnym wynikiem. Pozostaje jeszcze 1000 kHz.

W prakryce STM32L476RG ustawia zegar I2C na wartość 800 kHz mimo, że w Cube ustawione jest 1000. Stąd wynik “tylko” dwukrotnie niższy – 0,15 ms. Jak to jest szybko? Ano bardzo.

Jeśli nadal nie wiesz jakie korzyści wiążą się z użyciem DMA, pozwól, że przedstawię ile głównych pętli przeleci CPU podczas każdej sekundy działania z wyświetlaczem. Będą to wyniki z wyłączonym oraz z włączonym DMA. Pierwsze zdjęcia dotyczą blokującego transferu, czyli bez DMA.

Jak widzisz program wykona tylko tyle pętli głównych ile jest w stanie wyświetlić klatek na sekunde na wyświetlaczu. Jest to w zasadzie logiczne, bo CPU czeka aż transfer fo OLED się zakończy. Teraz wyniki z DMA. Transfer kolejnej ramki odbywa się tylko jeżeli transfer poprzedniej się zakończył. W tym samym czasie cały czas chodzi główna pętla while.

Nie dość, że liczba FPS podskoczyła to w program wykonuje ok 300 tys obiegów pętli while na sekundę. W czasie transferu ramki przez DMA, CPU nudzi się i może np. odebrać dane z czujników. Można pokusić się o podwójne buforowanie i płynne przygotowywanie danych dla wyświetlacza.

Wybór obsługi – czy DMA czy bez – oprócz konfiguracji w Cube odbywa się w bibliotece za pomocą definicji #define SSD1306_I2C_DMA_ENABLE

A jak wygląda to wszystko przy pracy z interfejsem SPI?

SPI

Kontroler SSD1306 umożliwia pracę interfejsu SPI przy pomocy trzech lub czterech połączeń. Różnica polega na podłączeniu pinu DC odpowiadającego za informacje dla układu czy wysyłane są dane czy komendy. Komunikacja w trybie 4-przewodowych jest 8-bitowa natomiast 3-przewodowa wymaga przesyłania za każdym razem 9 bitów po SPI(jeden informacyjny zamiast połączenia przewodem). Mój egzemplarz wyświetlacza nie pozwala mi na sprawdzenie trybu 3-przewodowego, dlatego ograniczę się tylko do dostępnych czterech połączeń. Zresztą 9-bitowy SPI wydaje się dosyć nienaturalny… Moduł który posiadam nie ma wyprowadzonego pinu MISO lecz i tak nie ma potrzeby czytania czegokolwiek z wyświetlacza. Tryb SPI w takim wypadku ustawię na Half-Duplex. SPI + DC to 4 piny, a jeszcze jest taki pin jak RESET. Nie jest on obligatoryjny, ale jeśli mamy wolne piny w układzie to czemu by go nie użyć. Załącza się go w bibliotece wygodnie jednym ‘difajnem’ – #define SSD1306_RESET_USE. Należy wtedy pin ten podłączyć do 3,3 V.

Ja podłącze wszystkie możliwe piny do MCU. Schemat przedstawia się następująco.

Pin CS trochę odleciał od reszty grupy, ale ma to swoje uzasadnienie o czym za chwilę.

Nota SSD1306 mówi, że maksymalną częstotliwością zegara na SPI może być 10 MHz. STM32L476RG taktowany jest zegarem 80 MHz, więc prescaler powinien być ustawiony na wartość 8. Podobnie jak przy I²C jestem w stanie podkręcić komunikację. W wypadku SPI mogę podnieść częstotliwość linii SCK aż do 40 MHz. Sprawdzę to oczywiście 🙂

Początkowo jednak ustawię wartość w miarę bezpieczną. Preskaler wielkości 64 da mi zegar ~1,25 MHz. Później wystarczy jedynie zmniejszać tą wartość. Piny I²C są pozostałością po poprzednim trybie i nie są niezbędne w tej chwili.

Czas zobaczyć co słychać w analizatorze. Przy 1,25 MHz już otrzymujemy dobry wynik. Przesłanie całej ramki to 8,25 ms. Zdecydowanie lepiej niż maksymalna częstotliwość po I²C a to dopiero 12% możliwości kontrolera na interfejsie SPI.

Dla porównania jeszcze 5 MHz – 2,07 ms.

Oraz 10 MHz – 1,04 ms. Bardzo szybko!

No dobra, ale co z overclockingiem? 🙂 Sprawdziłem to co umożliwia mi preskaler, czyli 20 MHz i 40 MHz. Podobnie jak przy I²C kontroler nawet nie zająknął. Żadnych randomowych czy zgubionych pixeli na ekranie nie zobaczyłem. Wszystko idzie gładko. A czasy? Nie patrząc na to co interpretuje analizator na MOSI i SCK (16 MHz próbkowanie), test jednak pokazuje prawdę.

Transfer ramki przy 20 MHz trwa zaledwie 0,53 ms.

A przy 40 MHz… 0,27 ms! Co za prędkość. Przy takiej prędkości można nie używać DMA 🙂

Jednak należy pamiętać, że jest to 4-krotnie przekroczona maksymalna wartość podana przez producenta. To, że mi się udało w warunkach biurkowych nie oznacza, że wyświetlacz taki będzie działał bez problemu na 40 MHz w środowisku roboczym! Lepiej trzymać się maksymalnie 10 MHz i użyć DMA.

SPI DMA

Oczywiście przewidziałem taką możliwość w bibiotece. DMA włącz w ten sam sposób jak dla I²C i użyj definicji #define SSD1306_SPI_DMA_ENABLE aby przełączyć kod na nadawanie DMA. Niestety to nie wszystko. Jak wiesz w SPI trzeba jeszcze kontrolować pin CS. Należy wrócić nim do stanu wysokiego po zakończeniu nadawania po DMA. Przecież nie będę czekał na zakończenie transferu, aby przestawić pin. Nie po to konfiguruję DMA, aby czekać jak przy zwykłym transferze… Są dwie drogi, które zaimplementowałem w bibliotece:

  1. Przerwanie void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) czyli od zakończenia transferu DMA. Jest to dobre rozwiązanie, ale należy pamiętać o tym, aby aktywować przerwanie w Cube oraz wstawić funkcję void SSD1306_DmaEndCallback(SPI_HandleTypeDef *hspi) w jego kod obsługi. Ma to taką zaletę, że dowolny pin może być CS’em
  2. Drugim sposobem jest ustawienie pinu CS w tryb sprzętowej kontroli. MCU sam może nim machać wtedy, kiedy jest potrzebny. Wtedy można zapomnieć o przerwaniu od końca transferu DMA. Wadą takiego rozwiązania jest to, że musi to być dedykowany pin. Dla SPI1 jest to PA4 stąd od początku “dziwny” wybór padł na niego. Drugą wadą jest to, że na tym SPI nie podłączysz już innego urządzenia bo CS od wyświetlacza będzie aktywował się zawsze, gdy puścisz transfer po użytym SPI.

Sam musisz zadecydować co będzie dla Ciebie odpowiednie. Jak wyglądają czasy zajęcia MCU przy SPI DMA? 1,25 MHz – 38,37 µs.

5 MHz – 28,81µs.

10 MHz – 21,81 µs.


Lepiej już nie będzie. Przy 20 i 40 MHz czas ten jest taki sam. Zapewne operacje oboktransferowe jak powroty z funkcji czy HAL’owa obsługa SPI zajmują wielokrotnie więcej niż sam transfer trzech komend. Jednakże wynik jest imponujący.

Pozostała liczba FPSów oraz ilość obiegów pętli while przy DMA. Pozwól, że pominę zdjęcia wyświetlacza pokazujące wyniki. Przedstawię je tabeli zestawiając razem z I²C.

Więc który interfejs wybrać?

 CPU time Poll(ms)FPS PollCPU time DMAFPS DMALoops DMA
I2C 100 kHz109101,08 ms11331655
I2C 400 kHz27,4360,3 ms38317300
I2C 800 kHz12,38800,15 ms81293911
SPI 1,25 MHz8,2510438,37 us1022368545
SPI 5 MHz2,0728528,81 us2721585956
SPI 10 MHz1,0440321,81 us3781098468
SPI 20 MHz0,5350721,81 us477691864
SPI 40 MHz0,2758321,81 us544393303

Jakie wnioski można z tego wyciągnąć? Którego interfejsu użyć w projekcje? Do zabawy lub prostego urządzenia nie będzie miało większego znaczenia jaki interfejs wybierzesz. Jednak jeśli:

    1. Masz mało pinów, wielkość systemu dowolna – możesz użyć I²C.
    2. Masz mało pinów, a system jest krytyczny czasowo(posiada wiele elementów i tonę wykonującego się kodu na raz) – weź SPI bez resetu w trybie 3-przewodowym. Wymagać to będzie lekkiej przebudowy biblioteki.
  1. Dowolna ilość pinów i dowolna złożoność – SPI jest zdecydowanie lepszym wyborem. Chyba, że już nie jest dostępne.

Czy zwracać uwagę na maksymalną liczbę FPS? Jedynym “zagrożeniem” dla płynności animacji jest I²C 100 kHz. Cała reszta obsłuży 30 klatek dla zapewnienia płynności. Lepiej też programowo ograniczyć klatkaż do 30 czy 60. To nie Counter Strike.

A DMA? Moim zdaniem jest to must have. Szkoda życia na czekanie aż MCU wyśle dane “ręcznie”. Można na prawdę w tym czasie robić inne rzeczy jak akwizycja danych ze wszystkich czujników. Działanie dzięki temu będzie płynne, a wyświetlacz będzie cieszył oko stałą wysoką liczbą klatek.

Wcześniej wspomniałem o podwójnym buforowaniu. Chcąc wysyłać ramki w równych odstępach czasu na przykład przy pomocy przerwania na timerze może zdażyć się tak, że timer wyzwoli transfer DMA w momencie, gdy MCU wpisuje jakieś dane do bufora wyświetlacza. Wtedy co najmniej jedna ramka będzie zepsuta, co wprawne oko może zauważyć. Można zaimplementować podwójne buforowanie, które powinno to rozwiązać. Co to jest? Jak to zrobić? To kiedy indziej 😉

Podsumowanie

OLEDy są świetnymi wyświetlaczami. Używanie ich jest bardzo przyjemne i chętnie je stosuje w swoich urządzeniach. Myślę, że dobrze wykazałem różnicę między interfejsami i bardziej świadomie będziesz wybierał odpowiednie sterowanie dla siebie.

Jeżeli wyświetlacze OLEDowe Ci się spodbały, możesz nabyć je w różnych wariantach u mnie w sklepie.

Projekt z kodem znajduje się na moim GitHubie: link

Jeśli zauważyłeś jakiś błąd, nie zgadzasz się z czymś, chciałbyś coś dodać istotnego lub po prostu uważasz, że chciałbyś podystkutować w tym temacie, napisz komentarz. Pamiętaj, że dyskusja ma być kulturalna i zgodna z zasadami języka polskiego.


Raz na jakiś czas wyślę Ci też e-mail z ciekawymi rzeczami które znalazłem


7 Komentarzy

SaS · 03/12/2019 o 13:03

CS nie można zdjąć zaraz po zakończeniu transferu DMA bo transfer JESZCZE TRWA! Sprawdź na analizatorze.
To, że transfer trwa wynika z tego, że przerwanie DMA wywołuje przerwanie po wysłaniu danej do SPI a:
– Po pierwsze “primo” skoro wpisano bajt, to dopiero zacznie on być transmitowany.
– Po drugie “primo” SPI ma 2 bajtowe FIFO.
Problem zbyt wczesnego zdejmowania CS 9problem z ostatnimi pikselami na wyświetlaczu) rozwiązałem używając timera systemowego 1ms. W przerwaniu od DMA ustawiam licznik na 2, który w przerwaniu zmniejsza swoją zawartość. W chwili przejścia z 1 na 0 zdejmuje CS. Dlaczego licznik na 2 a nie 1? Proszę się zastanowić.
Ze względu na problem z CS, to że potrzeba 4 linii (MOSI, SCK, C/D, CS) najczęściej używam I2C.

Kamil · 02/09/2019 o 21:22

Cześć
Mam takie dość nietypowe pytanie.Skąd wiesz że adres dla komend to 0x00 a dla danych to 0x40? Przeglądałem dokumentację do SSD1306 i nie mogę znaleźć.
Pytam bo mam do zrobienia wyświetlacz na 1327 i chciałem się trochę wzorować na Twoim kodzie 😉

    Mateusz Salamon · 02/09/2019 o 21:26

    Dokumentacja kontrolera SSD1306 strona 21 🙂 Masz tam Control Byte który wysyłasz zaraz za Slave Address’em, czyli niejako jest to “rejestr” urządzenia.
    https://msalamon.pl/download/515/

Fonak · 04/05/2019 o 11:53

Ok dzięki, będę wyczekiwał na artykuły. Na internecie można znaleźć sporo informacji na temat tych wyświetlaczy. Szczególnie dużo jest odnośnie typu ST7735 (TFT 1.8″ 128×160 SPI) oraz matrycy IPS 1,3″ 240×240 (ST7789) jednak brakuje szybkiego i łatwego w implementacji drivera pod STM32F1 lub STM32F4 z użyciem CUBEMX i SPI z DMA. Niewątpliwą zaletą jest też ich cena, model na matrycy 1,8″ TFT ST7735S (czerwone PCB) można kupić za około 12zł a model na sterowniku ST7789 (IPS 1,3″ 64k kolorów) za 10zł z przesyłką od myfredów 🙂

    SaS · 03/12/2019 o 13:12

    Poszukaj biblioteki dla Arduino, najlepiej sprawdź czy z “Srajduino” zadziała (nie przerażaj się prędkością a raczej wolnością wyświetlania) i przenieś na STM32. Jak zadziała (z pewnością tez wolno jak na Srajduino) to zmodyfikuj biblioteki tak aby “drawPixel” zapisywał do bufora w RAM. Dodaj jeszcze funkcję “display”, która przez DMA wyśle do wyświetlacza (pamiętaj o problemie zdejmowania CS). Od teraz wyświetlacz bedzie potrafił działać z max prędkością.
    W ten sposób zrealizowałem obsługę wielu wyświetlaczy, nawet akceleratora dla Srajduino https://www.youtube.com/playlist?list=PLdtkbzWTUVMnNf_gExmLmiaacjvhzPRdM
    Większa wersja w trakcie realizacji https://www.youtube.com/playlist?list=PLdtkbzWTUVMnNUNH3MiWQ9s86bcULhy33
    Na problem małej ilości RAM przy dużych rozdzielczościach tez jest lekarstwo ale bez RTOS sie raczej nie obejdzie.

Fonak · 03/05/2019 o 13:37

Hej,
Czy jest w planach podobny artykuł dotyczący wyświetlaczy LCD opartych o kontroler ST7789 i ST7735S. Są to bardzo popularne moduły używane w wielu projektach.

    Mateusz Salamon · 03/05/2019 o 21:23

    Cześć! Dzięki za podrzucenie ciekawego wyświetlacza. Nie znam ich, ale wyglądają ciekawie. Zobaczę co da się zrobić 😉

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Serwis wykorzystuje pliki cookies. Korzystając ze strony wyrażasz zgodę na wykorzystywanie plików cookies. Więcej informacji znajdziesz na stronie Polityka Prywatności

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close