
Uradowany faktem, że mój wpis wskoczył na główną czuję się zobowiązany zakasać rękawy i zabrać się do pisania biblioteki sterownika. W zasadzie mam ją już gotową i działającą, ale przecież nic nie stoi na przeszkodzie żebym napisał go jeszcze raz od nowa, może poprawimy to i owo? W pierwszej części, sterowaliśmy wyświetlaczem dosyć topornie:
- Zwalniamy zatrzask
- Wysyłamy na wejście rejestru kolejno 3 bajty (adres wiersza jako pierwszy bajt)
- Zamykamy zatrzask
- Czekamy milisekundę
- Zwalniamy zatrzask
- Wysyłamy na wejście rejestru kolejno 3 bajty (adres kolejnego wiersza jako pierwszy bajt)
- Zamykamy zatrzask
- Czekamy milisekundę
- ...
memcpy(wskaźnik celu, wskaźnik źródła, ilość bajtów do skopiowania);
I tu pojawia się tajemnicze słowo wskaźnik. Coś mi mówi, że gdybym zaczął tłumaczyć czym są wskaźniki i jak można ich sprytnie używać, to skończyłbym pisać ten post w okolicach świąt wielkiej nocy, więc postaram się ograniczyć do niezbędnego minimum. Wskaźnik to pojedyncza liczba, wskazująca położenie zmiennej/funkcji/struktury w fizycznej pamięci naszego Arduino. Pewnie zauważyliście przy pierwszym parametrze funkcji memcpy jakim jest m_Ekran pojawił się znaczek & (ampersand). Wskazuje on kompilatorowi, że pierwszym parametrem nie jest zawartość naszej struktury danych, tylko jej fizyczny adres (wskaźnik). Dlaczego zatem przy drugim parametrze nie wskazujemy kompilatorowi że nie chcemy zawartości tablicy tylko jej adres? No właśnie... dlatego, że zmienna t została przekazana jako parametr funkcji, a że jest tablicą, to została przekazana do funkcji właśnie jako wskaźnik. Więcej mogę wytłumaczyć w komentarzach, albo zapytajcie szwagra. W ostateczności googla. To naprawdę temat rzeka, a jest już dobrze po północy. Dla naszego przykładu wystarczy, że uwierzycie mi na słowo, że tablica przekazana do funkcji jest od razu wskaźnikiem i nie potrzebuje ampersanda. Trzeci parametr już chyba nie wymaga komentarza. Drugą rzeczą która dla początkujących może wydać się niezrozumiała, może być definicja struktury na początku pliku. Skleciłem ją sobie dla wygody. Pozwala mi to odwoływać się do zmiennej m_Ekran.dane[wiersz][bajt], adresując sobie zgrabnie wiersze i bajty. Kolejna rzecz - dlaczego w funkcji rysującej wiersz nie zrobiłem pętli do wyświetlania kolejnych bajtów, tylko podałem je "wprost"? Nie z wrodzonego lenistwa. Funkcja ta ma być wywoływana jak najczęściej, aby uniknąć efektu widocznego migotania matrycy. Prosty eksperyment. Zmieniam wartość opóźnienia cyklu w ostatnim wierszu na 5 milisekund. Niby niewiele. Ale migotanie matrycy już widać i jest nawet całkiem nieznośne. Czyli jeżeli ładowanie rejestrów będzie trwało dłużej niż 5ms, to już lipa. A wyobraźmy sobie matrycę RGB gdzie dla każdego pojedynczego bitu matrycy podajemy 3 bajty danych? Dlatego właśnie nie użyłem pętli. W wypadku podania dwóch bajtów dużo szybciej będzie podać je wprost. Ale co w przypadku gdy nasza matryca byłaby faktycznie większa? Jak jeszcze możemy przyspieszyć nasz kod? W Arduino jak i w wielu innych kontrolerach mamy interfejs SPI. To nic innego jak bardzo szybkie wyjście szeregowe, które może nam zastąpić dosyć powolną funkcję shiftOut(). W Arduino UNO jakie aktualnie katuję, działa ono domyślnie na pinach 10,11,12,13. Znających język Szekspira odsyłam pod adres: http://arduino.cc/en/Reference/SPI My wykorzystamy tylko dwa piny, a to dlatego, że będziemy "gadać" tylko w jedną stronę i tylko z jednym urządzeniem. Przypinamy Arduno do matrycy w następujący sposób: 13 - do wejście zegarowego rejestru 11 - do wejścia danych rejestru Zatrzask śmiało może pozostać na razie na pinie 4. Do obsługi interfejsu SPI wykorzystamy dołączoną do Arduino IDE bibliotekę SPI.h [crayon-51423628bf474/] Jak widać, kod zmienił się minimalnie, ale wierzcie mi na słowo - różnica ogromna. Można to w prosty sposób sprawdzić, wysyłając w funkcji m_RysujWiersz kilkanaście pustych bajtów zanim wyślemy nasze trzy istotne. Przy kilkudziesięciu "sztucznych kolumnach" funkcja shiftOut zaczyna powodować widoczne migotanie matrycy, a SPI radzi sobie absolutnie bez mrugnięcia ;) Na dzisiaj to tyle. Jutro może uda mi się napisać, jak całkowicie przenieść funkcję rysującą wiersz poza pętlę loop, aby wykonywała się samoczynnie w tle w zadanym odstępie czasu. Tyle na dziś i zapraszam do komentowania. Nikt nie ma żadnych pytań? Nie wierzę. Czytaj dalej...